Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Oct 2006 07:55:28 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 108392 for review
Message-ID:  <200610250755.k9P7tScW009780@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=108392

Change 108392 by imp@imp_lighthouse on 2006/10/25 07:54:28

	Merge in preliminary write support.

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91_ssc.c#12 edit
.. //depot/projects/arm/src/sys/arm/at91/at91_sscreg.h#7 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91_ssc.c#12 (text+ko) ====

@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/arm/at91/at91_ssc.c,v 1.3 2006/10/20 07:08:59 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/arm/at91/at91_ssc.c,v 1.2 2006/07/14 22:30:44 imp Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -34,9 +34,13 @@
 #include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/rman.h>
+#include <sys/uio.h>
 #include <machine/bus.h>
 
 #include <arm/at91/at91_sscreg.h>
+#include <arm/at91/at91_pdcreg.h>
+
+#define MAX_BUF	1024
 
 struct at91_ssc_softc
 {
@@ -48,6 +52,11 @@
 	struct cdev *cdev;
 	int flags;
 #define OPENED 1
+	bus_dma_tag_t tag;		/* bus dma tag  */
+	bus_dmamap_t tx_map;
+	int txdone;
+	uint8_t rx_buf[MAX_BUF];
+	bus_dmamap_t rx_map;
 };
 
 static inline uint32_t
@@ -129,6 +138,22 @@
 		AT91_SSC_LOCK_DESTROY(sc);
 		goto out;
 	}
+
+	/*
+	 * Allocate DMA tags and maps
+	 */
+	err = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
+	    BUS_SPACE_MAXADDR, NULL, NULL, 2048, 1, 2048, BUS_DMA_ALLOCNOW,
+	    NULL, NULL, &sc->tag);
+	if (err != 0)
+		goto out;
+	err = bus_dmamap_create(sc->tag, 0,  &sc->tx_map);
+	if (err != 0)
+		goto out;
+	err = bus_dmamap_create(sc->tag, 0,  &sc->rx_map);
+	if (err != 0)
+		goto out;
+
 	sc->cdev = make_dev(&at91_ssc_cdevsw, device_get_unit(dev), UID_ROOT,
 	    GID_WHEEL, 0600, "ssc%d", device_get_unit(dev));
 	if (sc->cdev == NULL) {
@@ -149,7 +174,7 @@
 	WR4(sc, SSC_TFMR,
 	    0x1f | SSC_TFMR_DATDEF | SSC_TFMR_MSFBF | SSC_TFMR_FSOS_NEG_PULSE);
 
-out:;
+out:
 	if (err)
 		at91_ssc_deactivate(dev);
 	return (err);
@@ -209,16 +234,19 @@
 at91_ssc_intr(void *xsc)
 {
 	struct at91_ssc_softc *sc = xsc;
-#if 0
 	uint32_t status;
 
 	/* Reading the status also clears the interrupt */
 	status = RD4(sc, SSC_SR);
 	if (status == 0)
 		return;
+	if (status & SSC_SR_ENDTX) {
+		WR4(sc, SSC_IDR, SSC_SR_ENDTX);
+		sc->txdone++;
+		wakeup(&sc->txdone);
+	}
 	AT91_SSC_LOCK(sc);
 	AT91_SSC_UNLOCK(sc);
-#endif
 	wakeup(sc);
 	return;
 }
@@ -232,9 +260,6 @@
 	AT91_SSC_LOCK(sc);
 	if (!(sc->flags & OPENED)) {
 		sc->flags |= OPENED;
-#if 0
-	// Enable interrupts
-#endif
 	}
 	AT91_SSC_UNLOCK(sc);
     	return (0);
@@ -248,13 +273,23 @@
 	sc = CDEV2SOFTC(dev);
 	AT91_SSC_LOCK(sc);
 	sc->flags &= ~OPENED;
-#if 0
-	// Disable interrupts
-#endif
 	AT91_SSC_UNLOCK(sc);
 	return (0);
 }
 
+static void
+at91_ssc_loadwrite(void *arg, bus_dma_segment_t *segs, int nsegs,
+    bus_size_t size, int error)
+{
+	struct at91_ssc_softc *sc;
+
+	sc = arg;
+	if (error != 0)
+		return;
+	WR4(sc, PDC_TPR, segs[0].ds_addr);
+	WR4(sc, PDC_TCR, size);
+}
+
 static int
 at91_ssc_read(struct cdev *dev, struct uio *uio, int flag)
 {
@@ -264,7 +299,29 @@
 static int
 at91_ssc_write(struct cdev *dev, struct uio *uio, int flag)
 {
-	return EIO;
+	struct at91_ssc_softc *sc;
+	int err, txdone;
+
+	sc = CDEV2SOFTC(dev);
+	// must write a multiple of 4 bytes
+	if ((uio->uio_resid & 0x3) != 0 || uio->uio_resid > MAX_BUF)
+		return (EINVAL);
+	WR4(sc, SSC_CR, SSC_CR_TXDIS);
+	WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS);
+	err = bus_dmamap_load_uio(sc->tag, sc->tx_map, uio, at91_ssc_loadwrite,
+	    sc, 0);
+	if (err != 0)
+		return (err);
+	WR4(sc, SSC_IER, SSC_SR_ENDTX);
+	WR4(sc, SSC_CR, SSC_CR_TXEN);
+	WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN);
+	txdone = sc->txdone;
+	do {
+		err = msleep(&sc->txdone, NULL, PCATCH | PZERO, "sscwr", hz);
+	} while (txdone == sc->txdone && err != EINTR);
+	if (err == 0)
+		uio->uio_resid = 0;
+	return err;
 }
 
 static device_method_t at91_ssc_methods[] = {

==== //depot/projects/arm/src/sys/arm/at91/at91_sscreg.h#7 (text+ko) ====

@@ -22,7 +22,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* $FreeBSD: src/sys/arm/at91/at91_sscreg.h,v 1.2 2006/10/20 07:08:15 imp Exp $ */
+/* $FreeBSD: src/sys/arm/at91/at91_sscreg.h,v 1.1 2006/03/24 07:42:33 imp Exp $ */
 
 #ifndef ARM_AT91_AT91_SSCREG_H
 #define ARM_AT91_AT91_SSCREG_H
@@ -132,4 +132,18 @@
 #define	SSC_TFMR_DATDEF	(1u << 5)	/* DATDEF: Data Default Value */
 #define	SSC_TFMR_DATLEN	(0x1fu << 0)	/* DATLEN: Data Length */
 
+/* SSC_SR */
+#define	SSC_SR_TXRDY	(1u << 0)
+#define	SSC_SR_TXEMPTY	(1u << 1)
+#define	SSC_SR_ENDTX	(1u << 2)
+#define	SSC_SR_TXBUFE	(1u << 3)
+#define	SSC_SR_RXRDY	(1u << 4)
+#define	SSC_SR_OVRUN	(1u << 5)
+#define	SSC_SR_ENDRX	(1u << 6)
+#define	SSC_SR_RXBUFF	(1u << 7)
+#define	SSC_SR_TXSYN	(1u << 10)
+#define	SSC_SR_RSSYN	(1u << 11)
+#define	SSC_SR_TXEN	(1u << 16)
+#define	SSC_SR_RXEN	(1u << 17)
+
 #endif /* ARM_AT91_AT91_SSCREG_H */



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