]> err.no Git - linux-2.6/blobdiff - drivers/spi/atmel_spi.c
Merge commit 'kumar/kumar-next'
[linux-2.6] / drivers / spi / atmel_spi.c
index 1749a27be0669f71670ec38f0670e1bf537588f4..0c7165660853a7194b16f8b2ed3cbf4849d78eb2 100644 (file)
@@ -313,14 +313,14 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
                xfer->tx_dma = dma_map_single(dev,
                                (void *) xfer->tx_buf, xfer->len,
                                DMA_TO_DEVICE);
-               if (dma_mapping_error(xfer->tx_dma))
+               if (dma_mapping_error(dev, xfer->tx_dma))
                        return -ENOMEM;
        }
        if (xfer->rx_buf) {
                xfer->rx_dma = dma_map_single(dev,
                                xfer->rx_buf, xfer->len,
                                DMA_FROM_DEVICE);
-               if (dma_mapping_error(xfer->rx_dma)) {
+               if (dma_mapping_error(dev, xfer->rx_dma)) {
                        if (xfer->tx_buf)
                                dma_unmap_single(dev,
                                                xfer->tx_dma, xfer->len,
@@ -497,7 +497,7 @@ static int atmel_spi_setup(struct spi_device *spi)
        struct atmel_spi        *as;
        u32                     scbr, csr;
        unsigned int            bits = spi->bits_per_word;
-       unsigned long           bus_hz, sck_hz;
+       unsigned long           bus_hz;
        unsigned int            npcs_pin;
        int                     ret;
 
@@ -536,14 +536,25 @@ static int atmel_spi_setup(struct spi_device *spi)
                return -EINVAL;
        }
 
-       /* speed zero convention is used by some upper layers */
+       /*
+        * Pre-new_1 chips start out at half the peripheral
+        * bus speed.
+        */
        bus_hz = clk_get_rate(as->clk);
+       if (!as->new_1)
+               bus_hz /= 2;
+
        if (spi->max_speed_hz) {
-               /* assume div32/fdiv/mbz == 0 */
-               if (!as->new_1)
-                       bus_hz /= 2;
-               scbr = ((bus_hz + spi->max_speed_hz - 1)
-                       / spi->max_speed_hz);
+               /*
+                * Calculate the lowest divider that satisfies the
+                * constraint, assuming div32/fdiv/mbz == 0.
+                */
+               scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz);
+
+               /*
+                * If the resulting divider doesn't fit into the
+                * register bitfield, we can't satisfy the constraint.
+                */
                if (scbr >= (1 << SPI_SCBR_SIZE)) {
                        dev_dbg(&spi->dev,
                                "setup: %d Hz too slow, scbr %u; min %ld Hz\n",
@@ -551,8 +562,8 @@ static int atmel_spi_setup(struct spi_device *spi)
                        return -EINVAL;
                }
        } else
+               /* speed zero means "as slow as possible" */
                scbr = 0xff;
-       sck_hz = bus_hz / scbr;
 
        csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8);
        if (spi->mode & SPI_CPOL)
@@ -589,7 +600,7 @@ static int atmel_spi_setup(struct spi_device *spi)
 
        dev_dbg(&spi->dev,
                "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n",
-               sck_hz, bits, spi->mode, spi->chip_select, csr);
+               bus_hz / scbr, bits, spi->mode, spi->chip_select, csr);
 
        spi_writel(as, CSR0 + 4 * spi->chip_select, csr);
 
@@ -616,7 +627,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg)
                return -ESHUTDOWN;
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
-               if (!(xfer->tx_buf || xfer->rx_buf)) {
+               if (!(xfer->tx_buf || xfer->rx_buf) && xfer->len) {
                        dev_dbg(&spi->dev, "missing rx or tx buf\n");
                        return -EINVAL;
                }