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