Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Jul 2012 00:06:14 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r238045 - head/sys/powerpc/mpc85xx
Message-ID:  <201207030006.q6306EDD007847@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207030006.q6306EDD007847>