On MX23 the XFER_COUNT part in ctrl0 field in DMA descriptor was
improperly OR'd during the construction of DMA descriptor chain, instead
of being freshly set. Because of that too many bytes were being
expected from SPI during the last DMA cycle. This caused a timeout
(SSP_TIMEOUT) to happen in the processing of the last DMA descriptor,
and thus reads and writes were failing. This is a fix for the problem,
by clearing XFER_COUNT bytes in ctrl0 before setting the new XFER_COUNT
for DMA descriptor.
Signed-off-by: Juha Lumme <juha.lumme@gmail.com>
Acked-by: Marek Vasut <marex@denx.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Convert all uses of devm_request_and_ioremap() to the newly introduced
devm_ioremap_resource() which provides more consistent error handling.
devm_ioremap_resource() provides its own error messages so all explicit
error messages can be removed from the failure code paths.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CONFIG_HOTPLUG is going away as an option. As result the __dev*
markings will be going away.
Remove use of __devinit, __devexit_p, __devinitdata, __devinitconst,
and __devexit.
Bill Pemberton has done most of the legwork on this series. I've used
his script to purge the attributes from the drivers/gpio tree.
Reported-by: Bill Pemberton <wfp5p@virginia.edu>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
In case the SPI DMA times out, the DMA might still be in some kind of
inconsistent state. Issue dmaengine_terminate_all() on the particular
channel to kill off all operations before continuing.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
In the current code implementing the MXS SPI driver, every transferred
message had assigned status = 0, which is not correct. Properly assign
status returned from the I/O functions.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Add "clock-frequency" property, which allows configuring the SPI block's
base speed.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Rework the mxs_ssp_timeout() function to make it a bit more readable
and hopefully less error prone. Also, have only one successful exit
from the function and one failing exit instead of two.
Finally, discard the udelay() from this function altogether, as this
tightloop is quick enough it's pointless.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This driver checks the length of transfer to be made and based
on this information, either chooses to transfer data via DMA or
PIO. Decrement this border further to gain better performace eg.
during SPI flash writes.
Empiric measurement shows that this gives extra 3kB/s write speed
with a M25P80 flash clocked at 40MHz.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
The transfer function incremented (struct spi_message)->actual_length
unconditionally, even if the transfer failed. Rectify this by incrementing
this only if transfer succeeded.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
When doing long continuous transfer, eg. from SPI flash via /dev/mtd,
the driver dies. This is caused by a bug in the DMA chaining. Rework
the DMA transfer code so that this issue does not happen any longer.
This involves proper allocation of correct amount of sg-list members.
Also, this means proper creation of DMA descriptors. There is actually an
important catch to this, the data transfer descriptors must be interleaved
with PIO register write descriptor, otherwise the transfer stalls. This
can be done in one descriptor, but due to the limitation of the DMA API,
it's not possible.
It turns out that in order for the SPI DMA to properly support
continuous transfers longer than 65280 bytes, there are some very
important parts that were left out from the documentation about about
the PIO transfer that is used.
Firstly, the XFER_SIZE register is not written with the whole length
of a transfer, but is written by each and every chained descriptor
with the length of the descriptors data buffer.
Next, unlike the demo code supplied by FSL, which only writes one PIO
word per descriptor, this does not apply if the descriptors are chained,
since the XFER_SIZE register must be written. Therefore, it is essential
to use four PIO words, CTRL0, CMD0, CMD1, XFER_SIZE. CMD0 and CMD1 are
written with zero, since they don't apply. The DMA programs the PIO words
in an incrementing order, so four PIO words.
Finally, unlike the demo code supplied by FSL, the SSP_CTRL0_IGNORE_CRC
must not be set during the whole transfer, but it must be set only on the
last descriptor in the chain.
Lastly, this code lends code from drivers/mtd/nand/omap2.c, which solves
trouble when the buffer supplied to the DMA transfer was vmalloc()'d. So
with this patch, it's safe to use /dev/mtdblockX interface again.
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
The call sequence spi_alloc_master/spi_register_master/spi_unregister_master
is complete; it reduces the device reference count to zero, which results in
device memory being freed. The remove function accesses the freed memory after
the call to spi_unregister_master(), _and_ it calls spi_master_put on the freed
memory.
Acquire a reference to the SPI master device and release it after cleanup is
complete (with the existing spi_master_put) to solve the problem.
Also, the device subsystem ensures that the remove function is only called once,
and resets device driver data to NULL. Remove the unnecessaary calls to
platform_set_drvdata().
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Marek Vasut <marex@denx.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
The init_completion() call does reinit not only the variable carrying
the flag that the completion finished, but also initialized the
waitqueue associated with the completion. On the contrary, the
INIT_COMPLETION() call only reinits the flag.
In case there was anything still stuck in the waitqueue, subsequent call
to init_completion() would be able to create possible race condition. This
patch uses the proper function and moves init_completion() into .probe() call
of the driver, to be issued only once.
Note that such scenario is impossible, since two threads can never enter the
mxs_spi_txrx_dma(), since whole this section is protected by mutex in SPI core.
This by no means allows this issue to exit though.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Restart the SSP block in case the SSP transfer failed in any way.
The block hung in some cases otherwise.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Acked-by: Chris Ball <cjb@laptop.org>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
These parts will be used by the MXS SPI driver too.
Signed-off-by: Marek Vasut <marex@denx.de>
Acked-by: Chris Ball <cjb@laptop.org>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This is slightly reworked version of the SPI driver.
Support for DT has been added and it's been converted
to queued API.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Acked-by: Chris Ball <cjb@laptop.org>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>