[BACK]Return to sa11x0_com.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / sa11x0

File: [local] / sys / arch / arm / sa11x0 / sa11x0_com.c (download)

Revision 1.2, Wed Mar 5 15:35:40 2008 UTC (16 years, 2 months ago) by nbrk
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +2 -2 lines

add volatile modifiers to avoid caching of status registers.
makes UART nice at 115200

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/conf.h>
#include <sys/device.h>

#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>

#include <dev/cons.h>

#include <arm/sa11x0/sa11x0_comreg.h>
#include <arm/sa11x0/sa11x0_reg.h>
#include <arm/sa11x0/sa11x0_var.h>

#ifdef DDB
#include <ddb/db_var.h>
#endif

cons_decl(sacom);
cons_decl(sacomfake);
void	sacominit(bus_space_tag_t bust, bus_addr_t busa, int speed);
int	sacomcnattach(bus_space_tag_t bust, bus_addr_t busa, int speed);
void	sacomfakecnattach(bus_addr_t addr);

/*
 * Fake autoconf stuff.
 */
struct cfdriver	sacom_cd = {
	NULL,
	"sacom",
	DV_TTY
};

struct sacom_softc {
	struct device	sc_dev;
};

int	sacom_match(struct device *parent, void *match, void *aux);
void	sacom_attach(struct device *parent, struct device *self, void *aux);

struct cfattach	sacom_ca = {
	sizeof(struct sacom_softc),
	sacom_match,
	sacom_attach,
};

int
sacom_match(struct device *parent, void *match, void *aux)
{
	return (1);
}

void
sacom_attach(struct device *parent, struct device *self, void *aux)
{
	printf(": SA-11x0 UART\n");
	return;
}

/*
 * Stuff for early sacom console support.
 */
bus_space_tag_t	sacom_bust;
bus_space_handle_t	sacom_bush;
bus_addr_t	sacom_base;	/* XXX for early sacom */
int sacom_speed;
int sacom_attached;
struct consdev	sacom_consdev = {
	NULL /* probe */,
	NULL, /* init */
	sacomcngetc,
	sacomcnputc,
	NULL /* poll */,
	NULL /* bell */,
	NODEV,
	CN_NORMAL
};
/* fake one (to use in bootstrap) */
struct consdev	sacom_fakeconsdev = {
	NULL /* probe */,
	NULL, /* init */
	sacomfakecngetc,
	sacomfakecnputc,
	NULL /* poll */,
	NULL /* bell */,
	NODEV,
	CN_NORMAL
};


void
sacominit(bus_space_tag_t bust, bus_addr_t busa, int speed)
{
	if (!sacom_attached && bus_space_map(bust, busa, 0x24, 0, &sacom_bush))
		panic("sacomcninit: mapping failed");

	sacom_bust = bust;
	sacom_attached = 1;
	sacom_speed = speed;
}

void
sacomcninit(struct consdev *p)
{
	sacominit(sacom_bust, sacom_bush, sacom_speed);
}

void
sacomfakecnattach(bus_addr_t addr)
{
	/*
	 * XXX assume that loader (hpcboot) already set up UART3.
	 * Just point cn_tab at our fake putc & getc routines.
	 */

	sacom_base = addr;
	cn_tab = &sacom_fakeconsdev;

//	sacom_attached = 1;
}

int
sacomcnattach(bus_space_tag_t bust, bus_addr_t busa, int speed)
{
	/*
	 * Early console attachment.
	 * Called from initarm() to print messages on boot.
	 */
//	int s = splhigh();

	/* TODO: check state in which hpcboot leaves uart */

	if (!sacom_attached) {
		sacominit(bust, busa, speed);

		cn_tab = &sacom_consdev;
		sacom_attached = 1;
	}

//	splx(s);

	return(0);
}

/* ARGSUSED */
int
sacomcngetc(dev_t dev)
{
	/* TODO */
#if 0
	u_char stat;
	int c, s;

#ifdef lint
	stat = dev; if (stat) return (0);
#endif

	s = splhigh();
	while (((stat = sacom_cn->sacom_lsr) & LSR_RXRDY) == 0)
		;
	c = sacom_cn->sacom_data;
	stat = sacom_cn->sacom_iir;
	splx(s);
	return (c);
#endif /* 0 */
	return(0);
}

/* ARGSUSED */
int
sacomfakecngetc(dev_t dev)
{
	/* TODO */
	return(0);
}

/*
 * Console kernel output character routine.
 */
/* ARGSUSED */
void
sacomcnputc(dev_t dev, int c)
{
	int timo;
//	int s = splhigh();
	if (sacom_attached == 0) {
		/* XXX */
		panic("sacomcnputc: write to unattached device");

	}
	/* wait for any pending transmission to finish */
	timo = 50000;
	while ((bus_space_read_4(sacom_bust, sacom_bush, SACOM_SR1) & SR1_TBY) == 1 && --timo)
		;

	bus_space_write_4(sacom_bust, sacom_bush, SACOM_DR, c);

	/* wait for this transmission to complete */
	timo = 1500000;
	while ((bus_space_read_4(sacom_bust, sacom_bush, SACOM_SR1) & SR1_TBY) == 1 && --timo)
		;
	/* XXX clear just generated intrs */
//	splx(s);

}
/* ARGSUSED */
void
sacomfakecnputc(dev_t dev, int c)
{
	int timo;

	/* wait for any pending transmission to finish */
	timo = 50000;
	while (((*(volatile uint32_t *)(sacom_base + SACOM_SR1)) & SR1_TBY) == 1 && --timo)
		;

	*(uint32_t *)(sacom_base + SACOM_DR) = c;

	/* wait for this transmission to complete */
	timo = 1500000;
	while (((*(volatile uint32_t *)(sacom_base + SACOM_SR1)) & SR1_TBY) == 1 && --timo)
		;
}