Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/evbarm Add support for the PL011 to plcom. Pull acr...
details: https://anonhg.NetBSD.org/src/rev/d0670d0cddaf
branches: trunk
changeset: 780455:d0670d0cddaf
user: skrll <skrll%NetBSD.org@localhost>
date: Wed Jul 25 07:26:17 2012 +0000
description:
Add support for the PL011 to plcom. Pull across a bunch of fixes from
com(4) while I'm here and do some other tidyup.
Tested on a RaspberryPi.
PL010 not tested.
diffstat:
sys/arch/evbarm/dev/plcom.c | 761 +++++++++++++++++------
sys/arch/evbarm/dev/plcomreg.h | 54 +-
sys/arch/evbarm/dev/plcomvar.h | 54 +-
sys/arch/evbarm/ifpga/ifpgareg.h | 3 +-
sys/arch/evbarm/ifpga/plcom_ifpga.c | 19 +-
sys/arch/evbarm/integrator/integrator_machdep.c | 60 +-
6 files changed, 704 insertions(+), 247 deletions(-)
diffs (truncated from 1795 to 300 lines):
diff -r 1abfbee8362d -r d0670d0cddaf sys/arch/evbarm/dev/plcom.c
--- a/sys/arch/evbarm/dev/plcom.c Wed Jul 25 03:09:01 2012 +0000
+++ b/sys/arch/evbarm/dev/plcom.c Wed Jul 25 07:26:17 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: plcom.c,v 1.39 2012/07/05 10:56:52 skrll Exp $ */
+/* $NetBSD: plcom.c,v 1.40 2012/07/25 07:26:17 skrll Exp $ */
/*-
* Copyright (c) 2001 ARM Ltd
@@ -28,11 +28,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 1999, 2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Charles M. Hannum.
+ * by Charles M. Hannum and Nick Hudson.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -88,13 +88,13 @@
*/
/*
- * COM driver for the Prime Cell PL010 UART, which is similar to the 16C550,
- * but has a completely different programmer's model.
+ * COM driver for the Prime Cell PL010 and PL011 UARTs. Both are is similar to
+ * the 16C550, but have a completely different programmer's model.
* Derived from the NS16550AF com driver.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.39 2012/07/05 10:56:52 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: plcom.c,v 1.40 2012/07/25 07:26:17 skrll Exp $");
#include "opt_plcom.h"
#include "opt_ddb.h"
@@ -103,9 +103,6 @@
#include "opt_multiprocessor.h"
#include "rnd.h"
-#ifdef RND_COM
-#include <sys/rnd.h>
-#endif
/*
* Override cnmagic(9) macro before including <sys/systm.h>.
@@ -138,6 +135,9 @@
#include <sys/kauth.h>
#include <sys/intr.h>
#include <sys/bus.h>
+#ifdef RND_COM
+#include <sys/rnd.h>
+#endif
#include <evbarm/dev/plcomreg.h>
#include <evbarm/dev/plcomvar.h>
@@ -148,7 +148,8 @@
void plcom_config (struct plcom_softc *);
void plcom_shutdown (struct plcom_softc *);
-int plcomspeed (long, long);
+int pl010comspeed (long, long);
+int pl011comspeed (long, long);
static u_char cflag2lcr (tcflag_t);
int plcomparam (struct tty *, struct termios *);
void plcomstart (struct tty *);
@@ -162,11 +163,10 @@
int plcom_to_tiocm (struct plcom_softc *);
void plcom_iflush (struct plcom_softc *);
-int plcom_common_getc (dev_t, bus_space_tag_t, bus_space_handle_t);
-void plcom_common_putc (dev_t, bus_space_tag_t, bus_space_handle_t, int);
+int plcom_common_getc (dev_t, struct plcom_instance *);
+void plcom_common_putc (dev_t, struct plcom_instance *, int);
-int plcominit (bus_space_tag_t, bus_addr_t, int, int, tcflag_t,
- bus_space_handle_t *);
+int plcominit (struct plcom_instance *, int, int, tcflag_t);
dev_type_open(plcomopen);
dev_type_close(plcomclose);
@@ -189,6 +189,8 @@
integrate void plcom_schedrx (struct plcom_softc *);
void plcomdiag (void *);
+bool plcom_intstatus(struct plcom_instance *, u_int *);
+
extern struct cfdriver plcom_cd;
const struct cdevsw plcom_cdevsw = {
@@ -207,9 +209,9 @@
u_int plcom_rbuf_lowat = (PLCOM_RING_SIZE * 3) / 4;
static int plcomconsunit = -1;
-static bus_space_tag_t plcomconstag;
-static bus_space_handle_t plcomconsioh;
-static int plcomconsattached;
+static struct plcom_instance plcomcons_info;
+
+static int plcomconsattached;
static int plcomconsrate;
static tcflag_t plcomconscflag;
static struct cnm_state plcom_cnm_state;
@@ -226,16 +228,14 @@
#ifdef KGDB
#include <sys/kgdb.h>
-static int plcom_kgdb_unit;
-static bus_space_tag_t plcom_kgdb_iot;
-static bus_space_handle_t plcom_kgdb_ioh;
+static struct plcom_instance plcomkgdb_info;
static int plcom_kgdb_attached;
int plcom_kgdb_getc (void *);
void plcom_kgdb_putc (void *, int);
#endif /* KGDB */
-#define PLCOMUNIT_MASK 0x7ffff
+#define PLCOMUNIT_MASK 0x7ffff
#define PLCOMDIALOUT_MASK 0x80000
#define PLCOMUNIT(x) (minor(x) & PLCOMUNIT_MASK)
@@ -246,10 +246,58 @@
#define BR BUS_SPACE_BARRIER_READ
#define BW BUS_SPACE_BARRIER_WRITE
-#define PLCOM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, PLCOM_UART_SIZE, (f))
+#define PLCOM_BARRIER(pi, f) \
+ bus_space_barrier((pi)->pi_iot, (pi)->pi_ioh, 0, (pi)->pi_size, (f))
+
+static uint8_t
+pread1(struct plcom_instance *pi, bus_size_t reg)
+{
+ if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS))
+ return bus_space_read_1(pi->pi_iot, pi->pi_ioh, reg);
+
+ return bus_space_read_4(pi->pi_iot, pi->pi_ioh, reg & -4) >>
+ (8 * (reg & 3));
+}
+int nhcr;
+static void
+pwrite1(struct plcom_instance *pi, bus_size_t o, uint8_t val)
+{
+ if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS)) {
+ bus_space_write_1(pi->pi_iot, pi->pi_ioh, o, val);
+ } else {
+ const size_t shift = 8 * (o & 3);
+ o &= -4;
+ uint32_t tmp = bus_space_read_4(pi->pi_iot, pi->pi_ioh, o);
+ tmp = (val << shift) | (tmp & ~(0xff << shift));
+ bus_space_write_4(pi->pi_iot, pi->pi_ioh, o, tmp);
+ }
+}
+
+static void
+pwritem1(struct plcom_instance *pi, bus_size_t o, const uint8_t *datap,
+ bus_size_t count)
+{
+ if (!ISSET(pi->pi_flags, PLC_FLAG_32BIT_ACCESS)) {
+ bus_space_write_multi_1(pi->pi_iot, pi->pi_ioh, o, datap, count);
+ } else {
+ KASSERT((o & 3) == 0);
+ while (count--) {
+ bus_space_write_4(pi->pi_iot, pi->pi_ioh, o, *datap++);
+ };
+ }
+}
+
+#define PREAD1(pi, reg) pread1(pi, reg)
+#define PREAD4(pi, reg) \
+ (bus_space_read_4((pi)->pi_iot, (pi)->pi_ioh, (reg)))
+
+#define PWRITE1(pi, reg, val) pwrite1(pi, reg, val)
+#define PWRITEM1(pi, reg, d, c) pwritem1(pi, reg, d, c)
+#define PWRITE4(pi, reg, val) \
+ (bus_space_write_4((pi)->pi_iot, (pi)->pi_ioh, (reg), (val)))
int
-plcomspeed(long speed, long frequency)
+pl010comspeed(long speed, long frequency)
{
#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
@@ -274,6 +322,20 @@
#undef divrnd
}
+int
+pl011comspeed(long speed, long frequency)
+{
+ int denom = 16 * speed;
+ int div = frequency / denom;
+ int rem = frequency % denom;
+
+ int ibrd = div << 6;
+ int fbrd = (((8 * rem) / speed) + 1) / 2;
+
+ /* Tolerance? */
+ return ibrd | fbrd;
+}
+
#ifdef PLCOM_DEBUG
int plcom_debug = 0;
@@ -301,7 +363,7 @@
}
#endif
-/* XXX this function is not used? */
+#if 0
int
plcomprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
{
@@ -327,6 +389,7 @@
return 1;
}
+#endif
/*
* No locking in this routine; it is only called during attach,
@@ -335,55 +398,106 @@
static void
plcom_enable_debugport(struct plcom_softc *sc)
{
+ struct plcom_instance *pi = &sc->sc_pi;
+
+ sc->sc_cr = PL01X_CR_UARTEN;
+ SET(sc->sc_mcr, PL01X_MCR_DTR | PL01X_MCR_RTS);
/* Turn on line break interrupt, set carrier. */
- sc->sc_cr = PL010_CR_RIE | PL010_CR_RTIE | PL01X_CR_UARTEN;
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, plcom_cr, sc->sc_cr);
- SET(sc->sc_mcr, PL01X_MCR_DTR | PL01X_MCR_RTS);
- /* XXX device_unit() abuse */
- sc->sc_set_mcr(sc->sc_set_mcr_arg, device_unit(sc->sc_dev),
- sc->sc_mcr);
+ switch (pi->pi_type) {
+ case PLCOM_TYPE_PL010:
+ SET(sc->sc_cr, PL010_CR_RIE | PL010_CR_RTIE);
+ PWRITE1(pi, PL010COM_CR, sc->sc_cr);
+ if (sc->sc_set_mcr) {
+ /* XXX device_unit() abuse */
+ sc->sc_set_mcr(sc->sc_set_mcr_arg,
+ device_unit(sc->sc_dev), sc->sc_mcr);
+ }
+ break;
+ case PLCOM_TYPE_PL011:
+ sc->sc_imsc = PL011_INT_RX | PL011_INT_RT;
+ SET(sc->sc_cr, PL011_CR_RXE | PL011_CR_TXE);
+ SET(sc->sc_cr, PL011_MCR(sc->sc_mcr));
+ PWRITE4(pi, PL011COM_CR, sc->sc_cr);
+ PWRITE4(pi, PL011COM_IMSC, sc->sc_imsc);
+ break;
+ }
+
}
void
plcom_attach_subr(struct plcom_softc *sc)
{
- int unit = sc->sc_iounit;
- bus_space_tag_t iot = sc->sc_iot;
- bus_space_handle_t ioh = sc->sc_ioh;
+ struct plcom_instance *pi = &sc->sc_pi;
struct tty *tp;
+ aprint_naive("\n");
+
callout_init(&sc->sc_diag_callout, 0);
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH);
+ switch (pi->pi_type) {
+ case PLCOM_TYPE_PL010:
+ case PLCOM_TYPE_PL011:
+ break;
+ default:
+ aprint_error_dev(sc->sc_dev,
+ "Unknown plcom type: %d\n", pi->pi_type);
+ return;
+ }
+
/* Disable interrupts before configuring the device. */
sc->sc_cr = 0;
+ sc->sc_imsc = 0;
- if (plcomconstag && unit == plcomconsunit) {
+ if (bus_space_is_equal(pi->pi_iot, plcomcons_info.pi_iot) &&
+ pi->pi_iobase == plcomcons_info.pi_iobase) {
plcomconsattached = 1;
- plcomconstag = iot;
- plcomconsioh = ioh;
-
/* Make sure the console is always "hardwired". */
delay(1000); /* wait for output to finish */
Home |
Main Index |
Thread Index |
Old Index