[PATCH v6 2/4] spi: bcm2835: add bcm2835 auxiliary spi device driver
Stephan Olbrich
stephanolbrich at gmx.de
Mon Jan 4 05:51:12 PST 2016
Hi Martin,
I have tested the auxiliary spi device driver. It works in general for me, but
I have two issues regarding the clock an chip select timing.
Am Freitag, 11. September 2015, 11:22:04 schrieb kernel at martin.sperl.org:
> +static int bcm2835aux_spi_transfer_one(struct spi_master *master,
> + struct spi_device *spi,
> + struct spi_transfer *tfr)
> +{
> + struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
> + unsigned long spi_hz, clk_hz, speed;
> + unsigned long spi_used_hz, xfer_time_us;
> +
> + /* calculate the registers to handle
> + *
> + * note that we use the variable data mode, which
> + * is not optimal for longer transfers as we waste registers
> + * resulting (potentially) in more interrupts when transferring
> + * more than 12 bytes
> + */
> + bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE |
> + BCM2835_AUX_SPI_CNTL0_VAR_WIDTH |
> + BCM2835_AUX_SPI_CNTL0_MSBF_OUT;
> + bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN;
> +
> + /* set clock */
> + spi_hz = tfr->speed_hz;
> + clk_hz = clk_get_rate(bs->clk);
> +
> + if (spi_hz >= clk_hz / 2) {
> + speed = 0;
> + } else if (spi_hz) {
> + speed = DIV_ROUND_UP(clk_hz, 2 * spi_hz) - 1;
> + if (speed > BCM2835_AUX_SPI_CNTL0_SPEED_MAX)
> + speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
> + } else { /* the slowest we can go */
> + speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX;
> + }
> + bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
> +
> + spi_used_hz = clk_hz / (2 * (speed + 1));
> +
> + /* handle all the modes */
> + if (spi->mode & SPI_CPOL)
> + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL;
> + if (spi->mode & SPI_CPHA)
> + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT |
> + BCM2835_AUX_SPI_CNTL0_CPHA_IN;
According to the spi documentation [1]: "CPHA indicates the clock phase used
to sample data; CPHA=0 says sample on the leading edge, CPHA=1 means the
trailing edge."
Which is from my understanding different from what the BMC2835 ARM Peripherals
[2] says for BCM2835_AUX_SPI_CNTL0_CPHA_IN:
"If 1 data is clocked in on the rising edge of the SPI clock
If 0 data is clocked in on the falling edge of the SPI clock"
I would expect the bits to be set dependant on the clock polarity (CPOL).
The other issue I have, is that the chip select is set before the clock
polarity and the polarity is reset and set again between each transfers of a
message. If CPOL is set to 1 this leads to additional rising and falling edges
of the clock while chip select is active, where no data is sampled.
Stephan
[1] http://lxr.free-electrons.com/source/Documentation/spi/spi-summary
[2] https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
More information about the linux-rpi-kernel
mailing list