@@ -63,6 +63,10 @@
#define BCM2835_AUX_SPI_CNTL0_VAR_CS 0x00008000
#define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000
#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD_0 0x00000000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD_1 0x00001000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD_4 0x00002000
+#define BCM2835_AUX_SPI_CNTL0_DOUTHOLD_7 0x00003000
#define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800
#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400
#define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200
@@ -341,10 +345,35 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *
} else { /* the slowest we can go */
speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
}
+ /* mask out old speed from previous spi_transfer */
+ bs->cntl[0] &= ~BCM2835_AUX_SPI_CNTL0_SPEED;
+ /* and set speed for this round */
bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
spi_used_hz = clk_hz / (2 * (speed + 1));
+ /* and configure hold time - needs to take speed into account */
+ /* first clear it */
+ bs->cntl[0] &= ~BCM2835_AUX_SPI_CNTL0_DOUTHOLD;
+ switch (speed) {
+ case 0: /* divider 2 */
+ case 1: /* divider 4 */
+ /* data hold time of 1 system clock cycle */
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_DOUTHOLD_1;
+ break;
+ case 2: /* divider 6 */
+ case 3: /* divider 8 */
+ case 4: /* divider 10 */
+ case 5: /* divider 12 */
+ /* data hold time of 4 system clock cycle */
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_DOUTHOLD_4;
+ break;
+ default: /* divider 14 and above */
+ /* data hold time of 7 system clock cycle */
+ bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_DOUTHOLD_7;
+ break;
+ }
+
/* set transmit buffers and length */
bs->tx_buf = tfr->tx_buf;
bs->rx_buf = tfr->rx_buf;