Merge remote-tracking branches 'spi/fix/atmel', 'spi/fix/bcm2835', 'spi/fix/doc'...
[sfrench/cifs-2.6.git] / drivers / spi / spi-bcm2835.c
index ed74786e68cbc62cf8eddae463e23d8af272f286..3e8eeb23d4e9c4e8d9c91084181a6c0ad2e51cd2 100644 (file)
@@ -480,7 +480,7 @@ static int bcm2835_spi_transfer_one_poll(struct spi_master *master,
                                         struct spi_device *spi,
                                         struct spi_transfer *tfr,
                                         u32 cs,
-                                        unsigned long xfer_time_us)
+                                        unsigned long long xfer_time_us)
 {
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
        unsigned long timeout;
@@ -531,7 +531,8 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
 {
        struct bcm2835_spi *bs = spi_master_get_devdata(master);
        unsigned long spi_hz, clk_hz, cdiv;
-       unsigned long spi_used_hz, xfer_time_us;
+       unsigned long spi_used_hz;
+       unsigned long long xfer_time_us;
        u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
 
        /* set clock */
@@ -553,13 +554,11 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        spi_used_hz = cdiv ? (clk_hz / cdiv) : (clk_hz / 65536);
        bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv);
 
-       /* handle all the modes */
+       /* handle all the 3-wire mode */
        if ((spi->mode & SPI_3WIRE) && (tfr->rx_buf))
                cs |= BCM2835_SPI_CS_REN;
-       if (spi->mode & SPI_CPOL)
-               cs |= BCM2835_SPI_CS_CPOL;
-       if (spi->mode & SPI_CPHA)
-               cs |= BCM2835_SPI_CS_CPHA;
+       else
+               cs &= ~BCM2835_SPI_CS_REN;
 
        /* for gpio_cs set dummy CS so that no HW-CS get changed
         * we can not run this in bcm2835_spi_set_cs, as it does
@@ -575,9 +574,10 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        bs->rx_len = tfr->len;
 
        /* calculate the estimated time in us the transfer runs */
-       xfer_time_us = tfr->len
+       xfer_time_us = (unsigned long long)tfr->len
                * 9 /* clocks/byte - SPI-HW waits 1 clock after each byte */
-               * 1000000 / spi_used_hz;
+               * 1000000;
+       do_div(xfer_time_us, spi_used_hz);
 
        /* for short requests run polling*/
        if (xfer_time_us <= BCM2835_SPI_POLLING_LIMIT_US)
@@ -592,6 +592,25 @@ static int bcm2835_spi_transfer_one(struct spi_master *master,
        return bcm2835_spi_transfer_one_irq(master, spi, tfr, cs);
 }
 
+static int bcm2835_spi_prepare_message(struct spi_master *master,
+                                      struct spi_message *msg)
+{
+       struct spi_device *spi = msg->spi;
+       struct bcm2835_spi *bs = spi_master_get_devdata(master);
+       u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS);
+
+       cs &= ~(BCM2835_SPI_CS_CPOL | BCM2835_SPI_CS_CPHA);
+
+       if (spi->mode & SPI_CPOL)
+               cs |= BCM2835_SPI_CS_CPOL;
+       if (spi->mode & SPI_CPHA)
+               cs |= BCM2835_SPI_CS_CPHA;
+
+       bcm2835_wr(bs, BCM2835_SPI_CS, cs);
+
+       return 0;
+}
+
 static void bcm2835_spi_handle_err(struct spi_master *master,
                                   struct spi_message *msg)
 {
@@ -739,6 +758,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
        master->set_cs = bcm2835_spi_set_cs;
        master->transfer_one = bcm2835_spi_transfer_one;
        master->handle_err = bcm2835_spi_handle_err;
+       master->prepare_message = bcm2835_spi_prepare_message;
        master->dev.of_node = pdev->dev.of_node;
 
        bs = spi_master_get_devdata(master);