Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 56285
b: refs/heads/master
c: e12deb8
h: refs/heads/master
i:
  56283: 8f87b5d
v: v3
  • Loading branch information
Mark A. Greer authored and Paul Mackerras committed May 12, 2007
1 parent 1aa3edb commit ec04638
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0f81b11d2a14adaa9b2c944f104e13d72fedc769
refs/heads/master: e12deb840ceed7051ab4799ae71b675a83c58c7c
2 changes: 1 addition & 1 deletion trunk/arch/powerpc/boot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c \
44x.c ebony.c mv64x60.c
44x.c ebony.c mv64x60.c mpsc.c
src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
cuboot-ebony.c treeboot-ebony.c
src-boot := $(src-wlib) $(src-plat) empty.c
Expand Down
170 changes: 170 additions & 0 deletions trunk/arch/powerpc/boot/mpsc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* MPSC/UART driver for the Marvell mv64360, mv64460, ...
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 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 <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "string.h"
#include "stdio.h"
#include "io.h"
#include "ops.h"

extern void udelay(long delay);

#define MPSC_CHR_1 0x000c

#define MPSC_CHR_2 0x0010
#define MPSC_CHR_2_TA (1<<7)
#define MPSC_CHR_2_TCS (1<<9)
#define MPSC_CHR_2_RA (1<<23)
#define MPSC_CHR_2_CRD (1<<25)
#define MPSC_CHR_2_EH (1<<31)

#define MPSC_CHR_4 0x0018
#define MPSC_CHR_4_Z (1<<29)

#define MPSC_CHR_5 0x001c
#define MPSC_CHR_5_CTL1_INTR (1<<12)
#define MPSC_CHR_5_CTL1_VALID (1<<15)

#define MPSC_CHR_10 0x0030

#define MPSC_INTR_CAUSE 0x0000
#define MPSC_INTR_CAUSE_RCC (1<<6)
#define MPSC_INTR_MASK 0x0080

#define SDMA_SDCM 0x0008
#define SDMA_SDCM_AR (1<<15)
#define SDMA_SDCM_AT (1<<31)

static volatile char *mpsc_base;
static volatile char *mpscintr_base;
static u32 chr1, chr2;

static int mpsc_open(void)
{
chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000;
chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA
| MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD
| MPSC_CHR_2_EH);
out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z);
out_le32((u32 *)(mpsc_base + MPSC_CHR_5),
MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID);
out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH);
return 0;
}

static void mpsc_putc(unsigned char c)
{
while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS);

out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c);
out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS);
}

static unsigned char mpsc_getc(void)
{
u32 cause = 0;
unsigned char c;

while (!(cause & MPSC_INTR_CAUSE_RCC))
cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE));

c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2));
out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c);
out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE),
cause & ~MPSC_INTR_CAUSE_RCC);

return c;
}

static u8 mpsc_tstc(void)
{
return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE))
& MPSC_INTR_CAUSE_RCC) != 0);
}

static void mpsc_stop_dma(volatile char *sdma_base)
{
out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA);
out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT);

while ((in_le32((u32 *)(sdma_base + SDMA_SDCM))
& (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0)
udelay(100);
}

static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop)
{
void *v;
int n;

n = getprop(devp, prop, &v, sizeof(v));
if (n != sizeof(v))
goto err_out;

devp = find_node_by_linuxphandle((u32)v);
if (devp == NULL)
goto err_out;

n = getprop(devp, "virtual-reg", &v, sizeof(v));
if (n == sizeof(v))
return v;

err_out:
return NULL;
}

int mpsc_console_init(void *devp, struct serial_console_data *scdp)
{
void *v;
int n, reg_set;
volatile char *sdma_base;

n = getprop(devp, "virtual-reg", &v, sizeof(v));
if (n != sizeof(v))
goto err_out;
mpsc_base = v;

sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma");
if (sdma_base == NULL)
goto err_out;

mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr");
if (mpscintr_base == NULL)
goto err_out;

n = getprop(devp, "block-index", &v, sizeof(v));
if (n != sizeof(v))
goto err_out;
reg_set = (int)v;

mpscintr_base += (reg_set == 0) ? 0x4 : 0xc;

/* Make sure the mpsc ctlrs are shutdown */
out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0);
out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);
out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0);

mpsc_stop_dma(sdma_base);

scdp->open = mpsc_open;
scdp->putc = mpsc_putc;
scdp->getc = mpsc_getc;
scdp->tstc = mpsc_tstc;
scdp->close = NULL;

return 0;

err_out:
return -1;
}
1 change: 1 addition & 0 deletions trunk/arch/powerpc/boot/ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ void start(void);
int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
int serial_console_init(void);
int ns16550_console_init(void *devp, struct serial_console_data *scdp);
int mpsc_console_init(void *devp, struct serial_console_data *scdp);
void *simple_alloc_init(char *base, unsigned long heap_size,
unsigned long granularity, unsigned long max_allocs);
extern void flush_cache(void *, unsigned long);
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/powerpc/boot/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ int serial_console_init(void)

if (!strcmp(compat, "ns16550"))
rc = ns16550_console_init(devp, &serial_cd);
else if (!strcmp(compat, "marvell,mpsc"))
rc = mpsc_console_init(devp, &serial_cd);

/* Add other serial console driver calls here */

Expand Down

0 comments on commit ec04638

Please sign in to comment.