Author: marcel
Date: Tue Jul  3 00:06:14 2012
New Revision: 238045
URL: http://svn.freebsd.org/changeset/base/238045

Log:
  Support lbc interrupts:
  o   Save and clear the LTESR register in the interrupt handler.
  o   In lbc_read_reg(), return the saved LTESR register value if applicable
      (i.e. when the saved value is not invalid (read: ~0U)).
  o   In lbc_write_reg(), clear the bits in the saved register when when it's
      written to and when the asved value is not invalid.
  o   Also in lbc_write_reg(), the LTESR register is unlocked (in H/W) when
      bit 1 of LTEATR is cleared. We use this to invalidate our saved LTESR
      register value. Subsequent reads and write go to H/W directly.
  
  While here:
  o   In lbc_read_reg() & lbc_write_reg(), add some belts and suspenders to
      catch when register offsets are out of range.
  o   In lbc_attach(), initialize completely and don't leave something left
      for lbc_banks_enable().

Modified:
  head/sys/powerpc/mpc85xx/lbc.c
  head/sys/powerpc/mpc85xx/lbc.h

Modified: head/sys/powerpc/mpc85xx/lbc.c
==============================================================================
--- head/sys/powerpc/mpc85xx/lbc.c      Mon Jul  2 23:53:08 2012        
(r238044)
+++ head/sys/powerpc/mpc85xx/lbc.c      Tue Jul  3 00:06:14 2012        
(r238045)
@@ -273,13 +273,8 @@ lbc_banks_enable(struct lbc_softc *sc)
 
        for (i = 0; i < LBC_DEV_MAX; i++) {
                size = sc->sc_banks[i].size;
-               if (size == 0) {
-                       bus_space_write_4(sc->sc_bst, sc->sc_bsh,
-                           LBC85XX_BR(i), 0);
-                       bus_space_write_4(sc->sc_bst, sc->sc_bsh,
-                           LBC85XX_OR(i), 0);
+               if (size == 0)
                        continue;
-               }
 
                /*
                 * Compute and program BR value.
@@ -331,23 +326,6 @@ lbc_banks_enable(struct lbc_softc *sc)
                    LBC85XX_OR(i), regval);
        }
 
-       /*
-        * Initialize configuration register:
-        * - enable Local Bus
-        * - set data buffer control signal function
-        * - disable parity byte select
-        * - set ECC parity type
-        * - set bus monitor timing and timer prescale
-        */
-       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
-
-       /*
-        * Initialize clock ratio register:
-        * - disable PLL bypass mode
-        * - configure LCLK delay cycles for the assertion of LALE
-        * - set system clock divider
-        */
-       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
        return (0);
 
 fail:
@@ -426,6 +404,18 @@ out:
        return (rv);
 }
 
+static void
+lbc_intr(void *arg)
+{
+       struct lbc_softc *sc = arg;
+       uint32_t ltesr;
+
+       ltesr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR);
+       sc->sc_ltesr = ltesr;
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ltesr);
+       wakeup(sc->sc_dev);
+}
+
 static int
 lbc_probe(device_t dev)
 {
@@ -455,14 +445,59 @@ lbc_attach(device_t dev)
        sc = device_get_softc(dev);
        sc->sc_dev = dev;
 
-       sc->sc_rid = 0;
-       sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
+       sc->sc_mrid = 0;
+       sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
            RF_ACTIVE);
-       if (sc->sc_res == NULL)
+       if (sc->sc_mres == NULL)
                return (ENXIO);
 
-       sc->sc_bst = rman_get_bustag(sc->sc_res);
-       sc->sc_bsh = rman_get_bushandle(sc->sc_res);
+       sc->sc_bst = rman_get_bustag(sc->sc_mres);
+       sc->sc_bsh = rman_get_bushandle(sc->sc_mres);
+
+       for (bank = 0; bank < LBC_DEV_MAX; bank++) {
+               bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
+               bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
+       }
+
+       /*
+        * Initialize configuration register:
+        * - enable Local Bus
+        * - set data buffer control signal function
+        * - disable parity byte select
+        * - set ECC parity type
+        * - set bus monitor timing and timer prescale
+        */
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);
+
+       /*
+        * Initialize clock ratio register:
+        * - disable PLL bypass mode
+        * - configure LCLK delay cycles for the assertion of LALE
+        * - set system clock divider
+        */
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);
+
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);
+
+       sc->sc_irid = 0;
+       sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
+           RF_ACTIVE | RF_SHAREABLE);
+       if (sc->sc_ires != NULL) {
+               error = bus_setup_intr(dev, sc->sc_ires,
+                   INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
+                   &sc->sc_icookie);
+               if (error) {
+                       device_printf(dev, "could not activate interrupt\n");
+                       bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
+                           sc->sc_ires);
+                       sc->sc_ires = NULL;
+               }
+       }
+
+       sc->sc_ltesr = ~0;
+
        rangesptr = NULL;
 
        rm = &sc->sc_rman;
@@ -614,7 +649,7 @@ lbc_attach(device_t dev)
 
 fail:
        free(rangesptr, M_OFWPROP);
-       bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
+       bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
        return (error);
 }
 
@@ -742,17 +777,49 @@ lbc_get_devinfo(device_t bus, device_t c
 void
 lbc_write_reg(device_t child, u_int off, uint32_t val)
 {
+       device_t dev;
        struct lbc_softc *sc;
 
-       sc = device_get_softc(device_get_parent(child));
+       dev = device_get_parent(child);
+
+       if (off >= 0x1000) {
+               device_printf(dev, "%s(%s): invalid offset %#x\n",
+                   __func__, device_get_nameunit(child), off);
+               return;
+       }
+
+       sc = device_get_softc(dev);
+
+       if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0u) {
+               sc->sc_ltesr ^= (val & sc->sc_ltesr);
+               return;
+       }
+
+       if (off == LBC85XX_LTEATR && (val & 1) == 0)
+               sc->sc_ltesr = ~0u;
        bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
 }
 
 uint32_t
 lbc_read_reg(device_t child, u_int off)
 {
+       device_t dev;
        struct lbc_softc *sc;
+       uint32_t val;
+
+       dev = device_get_parent(child);
+
+       if (off >= 0x1000) {
+               device_printf(dev, "%s(%s): invalid offset %#x\n",
+                   __func__, device_get_nameunit(child), off);
+               return (~0U);
+       }
+
+       sc = device_get_softc(dev);
 
-       sc = device_get_softc(device_get_parent(child));
-       return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
+       if (off == LBC85XX_LTESR && sc->sc_ltesr != ~0U)
+               val = sc->sc_ltesr;
+       else
+               val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
+       return (val);
 }

Modified: head/sys/powerpc/mpc85xx/lbc.h
==============================================================================
--- head/sys/powerpc/mpc85xx/lbc.h      Mon Jul  2 23:53:08 2012        
(r238044)
+++ head/sys/powerpc/mpc85xx/lbc.h      Tue Jul  3 00:06:14 2012        
(r238045)
@@ -105,10 +105,15 @@ struct lbc_bank {
 
 struct lbc_softc {
        device_t                sc_dev;
-       struct resource         *sc_res;
+
+       struct resource         *sc_mres;
        bus_space_handle_t      sc_bsh;
        bus_space_tag_t         sc_bst;
-       int                     sc_rid;
+       int                     sc_mrid;
+
+       int                     sc_irid;
+       struct resource         *sc_ires;
+       void                    *sc_icookie;
 
        struct rman             sc_rman;
 
@@ -117,6 +122,8 @@ struct lbc_softc {
 
        struct lbc_memrange     sc_range[LBC_DEV_MAX];
        struct lbc_bank         sc_banks[LBC_DEV_MAX];
+
+       uint32_t                sc_ltesr;
 };
 
 struct lbc_devinfo {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to