From d500e922b750a2bea554d32d8f12937f4da9c80a Mon Sep 17 00:00:00 2001
From: Matteo Fortini <[EMAIL PROTECTED]>
Date: Wed, 10 Dec 2008 19:33:16 +0100
Subject: [PATCH] Fix: put dummy byte to enable fixing EOF bug to first place in order not to break some drivers
Use ALARM interrupt to avoid waiting for data to come in


Signed-off-by: Matteo Fortini <[EMAIL PROTECTED]>
---
drivers/spi/mpc512x_psc_spi.c | 53 ++++++++++++++++++++++++-----------------
1 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
index 1fd7ad4..41faa49 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -136,6 +136,7 @@ static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
                   (spi->mode & SPI_CS_HIGH) ? 1 : 0);
}

+
/*
 * Current MPC5121's have a bug in the SS logic that requires setting
 * the EOF flag on the next to last byte instead of the last
@@ -155,7 +156,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,

    if (!tx_buf && !rx_buf && t->len)
        return -EINVAL;
-
+ /*
     * zero out Mode register 2
     * From the ref man:
@@ -175,6 +176,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
        u8 data;
        size_t fifosz;
        int rxcount;
+        int txcount;

        /*
         * The number of bytes that can be sent at a time
@@ -183,41 +185,49 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
        fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
        count = min(fifosz, len);

+        txcount = 0;
+        /*
+ * Insert a dummy byte before a message of len 1 to make it at least 2 bytes long
+         * to be able to set EOF correctly
+         */
+        if (t->len == 1) {
+            out_8(&fifo->txdata_8, 0);
+            txcount++;
+        }
        for (i = count; i > 0; i--) {
            if (len == EOFBYTE || t->len == 1)
                setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
            data = tx_buf ? *tx_buf++ : 0;
            out_8(&fifo->txdata_8, data);
-            if (t->len == 1)
-                out_8(&fifo->txdata_8, 0);
+            txcount++;
            len--;
        }

        INIT_COMPLETION(mps->done);

-        /* interrupt on tx fifo empty */
-        out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
-        out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
+        /* Enable FIFO_ALARM interrupts for rx_fifo */
+        out_be32(&fifo->rxalarm, txcount);
+        out_be32(&fifo->rxisr, MPC512x_PSC_FIFO_ALARM);
+        out_be32(&fifo->rximr, MPC512x_PSC_FIFO_ALARM);

-        /* enable transmiter/receiver */
- out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
-
-        wait_for_completion(&mps->done);
+        /* Disable tx_fifo interrupts */
+        out_be32(&fifo->txisr, 0xffffffff);
+        out_be32(&fifo->tximr, 0);

-        mdelay(1);
+ out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);

-        /* rx fifo should have count bytes in it */
-        rxcount = in_be32(&fifo->rxcnt);
-        if (rxcount != count)
-            mdelay(1);
+        wait_for_completion (&mps->done);

        rxcount = in_be32(&fifo->rxcnt);
-        if (rxcount != count && t->len != 1)
+        if (rxcount != txcount)
            printk(KERN_WARNING "expected %d bytes in rx fifo "
-                       "but got %d\n", count, rxcount);
-
+                    "but got %d\n", txcount, rxcount);
        rxcount = min(rxcount, count);
        {
+            /* Throw away possible initial dummy byte */
+            if (t->len == 1) {
+                (void)in_8(&fifo->rxdata_8);
+            }
            for (i = rxcount; i > 0; i--) {
                data = in_8(&fifo->rxdata_8);
                if (rx_buf)
@@ -418,10 +428,9 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
    struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;

    /* clear interrupt and wake up the work queue */
-    if (in_be32(&fifo->txisr)
-        & in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
-        out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
-        out_be32(&fifo->tximr, 0);
+ if (in_be32(&fifo->rxisr) & in_be32(&fifo->rximr) & MPC512x_PSC_FIFO_ALARM) {
+        out_be32(&fifo->rxisr, MPC512x_PSC_FIFO_ALARM);
+        out_be32(&fifo->rximr, 0);
        complete(&mps->done);
        return IRQ_HANDLED;
    }
--
1.5.4.3

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to