X-Git-Url: http://git.monstr.eu/?a=blobdiff_plain;f=drivers%2Fspi%2Fspi.c;h=b69c14082c52853b8bc6235e428fe441a3980872;hb=329f0dac4cad9fa4b1439a88180d91bcb5c4eaf8;hp=7ba981cdb86bde1e752f6ecc8ba020b2d368ecb1;hpb=6b3f236a998550dba91a46a22feb1cc02f39fb06;p=linux-2.6-microblaze.git diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7ba981cdb86b..b69c14082c52 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1106,19 +1106,14 @@ static void _spi_transfer_delay_ns(u32 ns) } } -static void _spi_transfer_cs_change_delay(struct spi_message *msg, - struct spi_transfer *xfer) +static int _spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer) { - u32 delay = xfer->cs_change_delay; - u32 unit = xfer->cs_change_delay_unit; + u32 delay = _delay->value; + u32 unit = _delay->unit; u32 hz; - /* return early on "fast" mode - for everything but USECS */ - if (!delay) { - if (unit == SPI_DELAY_UNIT_USECS) - _spi_transfer_delay_ns(10000); - return; - } + if (!delay) + return 0; switch (unit) { case SPI_DELAY_UNIT_USECS: @@ -1127,20 +1122,62 @@ static void _spi_transfer_cs_change_delay(struct spi_message *msg, case SPI_DELAY_UNIT_NSECS: /* nothing to do here */ break; case SPI_DELAY_UNIT_SCK: + /* clock cycles need to be obtained from spi_transfer */ + if (!xfer) + return -EINVAL; /* if there is no effective speed know, then approximate * by underestimating with half the requested hz */ hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2; + if (!hz) + return -EINVAL; delay *= DIV_ROUND_UP(1000000000, hz); break; default: + return -EINVAL; + } + + return delay; +} + +int spi_delay_exec(struct spi_delay *_delay, struct spi_transfer *xfer) +{ + int delay; + + if (!_delay) + return -EINVAL; + + delay = _spi_delay_to_ns(_delay, xfer); + if (delay < 0) + return delay; + + _spi_transfer_delay_ns(delay); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_delay_exec); + +static void _spi_transfer_cs_change_delay(struct spi_message *msg, + struct spi_transfer *xfer) +{ + u32 delay = xfer->cs_change_delay.value; + u32 unit = xfer->cs_change_delay.unit; + int ret; + + /* return early on "fast" mode - for everything but USECS */ + if (!delay) { + if (unit == SPI_DELAY_UNIT_USECS) + _spi_transfer_delay_ns(10000); + return; + } + + ret = spi_delay_exec(&xfer->cs_change_delay, xfer); + if (ret) { dev_err_once(&msg->spi->dev, "Use of unsupported delay unit %i, using default of 10us\n", - xfer->cs_change_delay_unit); - delay = 10000; + unit); + _spi_transfer_delay_ns(10000); } - /* now sleep for the requested amount of time */ - _spi_transfer_delay_ns(delay); } /*