2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-05-06 08:47:04 +04:00
/*
* Driver for Cirrus Logic EP93xx SPI controller .
*
2011-05-29 14:10:06 +04:00
* Copyright ( C ) 2010 - 2011 Mika Westerberg
2010-05-06 08:47:04 +04:00
*
* Explicit FIFO handling code was inspired by amba - pl022 driver .
*
* Chip select support using other than built - in GPIOs by H . Hartley Sweeten .
*
* For more information about the SPI controller see documentation on Cirrus
* Logic web site :
2020-07-08 22:44:00 +03:00
* https : //www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
2010-05-06 08:47:04 +04:00
*/
# include <linux/io.h>
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/delay.h>
# include <linux/device.h>
2011-05-29 14:10:06 +04:00
# include <linux/dmaengine.h>
2010-05-06 08:47:04 +04:00
# include <linux/bitops.h>
# include <linux/interrupt.h>
2011-10-15 22:40:09 +04:00
# include <linux/module.h>
2010-05-06 08:47:04 +04:00
# include <linux/platform_device.h>
# include <linux/sched.h>
2011-05-29 14:10:06 +04:00
# include <linux/scatterlist.h>
2010-05-06 08:47:04 +04:00
# include <linux/spi/spi.h>
2012-08-24 17:12:11 +04:00
# include <linux/platform_data/dma-ep93xx.h>
# include <linux/platform_data/spi-ep93xx.h>
2010-05-06 08:47:04 +04:00
# define SSPCR0 0x0000
2020-04-02 15:10:22 +03:00
# define SSPCR0_SPO BIT(6)
# define SSPCR0_SPH BIT(7)
2010-05-06 08:47:04 +04:00
# define SSPCR0_SCR_SHIFT 8
# define SSPCR1 0x0004
# define SSPCR1_RIE BIT(0)
# define SSPCR1_TIE BIT(1)
# define SSPCR1_RORIE BIT(2)
# define SSPCR1_LBM BIT(3)
# define SSPCR1_SSE BIT(4)
# define SSPCR1_MS BIT(5)
# define SSPCR1_SOD BIT(6)
# define SSPDR 0x0008
# define SSPSR 0x000c
# define SSPSR_TFE BIT(0)
# define SSPSR_TNF BIT(1)
# define SSPSR_RNE BIT(2)
# define SSPSR_RFF BIT(3)
# define SSPSR_BSY BIT(4)
# define SSPCPSR 0x0010
# define SSPIIR 0x0014
# define SSPIIR_RIS BIT(0)
# define SSPIIR_TIS BIT(1)
# define SSPIIR_RORIS BIT(2)
# define SSPICR SSPIIR
/* timeout in milliseconds */
# define SPI_TIMEOUT 5
/* maximum depth of RX/TX FIFO */
# define SPI_FIFO_SIZE 8
/**
* struct ep93xx_spi - EP93xx SPI controller structure
* @ clk : clock for the controller
2017-08-08 23:51:25 +03:00
* @ mmio : pointer to ioremap ( ) ' d registers
2011-05-29 14:10:06 +04:00
* @ sspdr_phys : physical address of the SSPDR register
2010-05-06 08:47:04 +04:00
* @ tx : current byte in transfer to transmit
* @ rx : current byte in transfer to receive
* @ fifo_level : how full is FIFO ( % 0. . % SPI_FIFO_SIZE - % 1 ) . Receiving one
* frame decreases this level and sending one frame increases it .
2011-05-29 14:10:06 +04:00
* @ dma_rx : RX DMA channel
* @ dma_tx : TX DMA channel
* @ dma_rx_data : RX parameters passed to the DMA engine
* @ dma_tx_data : TX parameters passed to the DMA engine
* @ rx_sgt : sg table for RX transfers
* @ tx_sgt : sg table for TX transfers
* @ zeropage : dummy page used as RX buffer when only TX buffer is passed in by
* the client
2010-05-06 08:47:04 +04:00
*/
struct ep93xx_spi {
struct clk * clk ;
2017-08-08 23:51:25 +03:00
void __iomem * mmio ;
2011-05-29 14:10:06 +04:00
unsigned long sspdr_phys ;
2010-05-06 08:47:04 +04:00
size_t tx ;
size_t rx ;
size_t fifo_level ;
2011-05-29 14:10:06 +04:00
struct dma_chan * dma_rx ;
struct dma_chan * dma_tx ;
struct ep93xx_dma_data dma_rx_data ;
struct ep93xx_dma_data dma_tx_data ;
struct sg_table rx_sgt ;
struct sg_table tx_sgt ;
void * zeropage ;
2010-05-06 08:47:04 +04:00
} ;
/* converts bits per word to CR0.DSS value */
# define bits_per_word_to_dss(bpw) ((bpw) - 1)
/**
* ep93xx_spi_calc_divisors ( ) - calculates SPI clock divisors
2017-08-08 23:51:29 +03:00
* @ master : SPI master
2010-05-06 08:47:04 +04:00
* @ rate : desired SPI output clock rate
2013-07-02 21:10:29 +04:00
* @ div_cpsr : pointer to return the cpsr ( pre - scaler ) divider
* @ div_scr : pointer to return the scr divider
2010-05-06 08:47:04 +04:00
*/
2017-08-08 23:51:29 +03:00
static int ep93xx_spi_calc_divisors ( struct spi_master * master ,
2014-02-08 19:52:26 +04:00
u32 rate , u8 * div_cpsr , u8 * div_scr )
2010-05-06 08:47:04 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2010-05-06 08:47:04 +04:00
unsigned long spi_clk_rate = clk_get_rate ( espi - > clk ) ;
int cpsr , scr ;
/*
* Make sure that max value is between values supported by the
2017-08-08 23:51:31 +03:00
* controller .
2010-05-06 08:47:04 +04:00
*/
2014-02-08 19:52:26 +04:00
rate = clamp ( rate , master - > min_speed_hz , master - > max_speed_hz ) ;
2010-05-06 08:47:04 +04:00
/*
* Calculate divisors so that we can get speed according the
* following formula :
* rate = spi_clock_rate / ( cpsr * ( 1 + scr ) )
*
* cpsr must be even number and starts from 2 , scr can be any number
* between 0 and 255.
*/
for ( cpsr = 2 ; cpsr < = 254 ; cpsr + = 2 ) {
for ( scr = 0 ; scr < = 255 ; scr + + ) {
if ( ( spi_clk_rate / ( cpsr * ( scr + 1 ) ) ) < = rate ) {
2013-07-02 21:10:29 +04:00
* div_scr = ( u8 ) scr ;
* div_cpsr = ( u8 ) cpsr ;
2010-05-06 08:47:04 +04:00
return 0 ;
}
}
}
return - EINVAL ;
}
2017-08-08 23:51:29 +03:00
static int ep93xx_spi_chip_setup ( struct spi_master * master ,
2017-02-16 23:07:37 +03:00
struct spi_device * spi ,
struct spi_transfer * xfer )
2010-05-06 08:47:04 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2017-02-16 23:07:37 +03:00
u8 dss = bits_per_word_to_dss ( xfer - > bits_per_word ) ;
2013-07-02 21:10:29 +04:00
u8 div_cpsr = 0 ;
u8 div_scr = 0 ;
2010-05-06 08:47:04 +04:00
u16 cr0 ;
2013-07-02 21:10:29 +04:00
int err ;
2017-08-08 23:51:29 +03:00
err = ep93xx_spi_calc_divisors ( master , xfer - > speed_hz ,
2017-02-16 23:07:37 +03:00
& div_cpsr , & div_scr ) ;
2013-07-02 21:10:29 +04:00
if ( err )
return err ;
2010-05-06 08:47:04 +04:00
2013-07-02 21:10:29 +04:00
cr0 = div_scr < < SSPCR0_SCR_SHIFT ;
2020-04-02 15:10:22 +03:00
if ( spi - > mode & SPI_CPOL )
cr0 | = SSPCR0_SPO ;
if ( spi - > mode & SPI_CPHA )
cr0 | = SSPCR0_SPH ;
2013-07-02 21:09:29 +04:00
cr0 | = dss ;
2010-05-06 08:47:04 +04:00
2017-08-08 23:51:29 +03:00
dev_dbg ( & master - > dev , " setup: mode %d, cpsr %d, scr %d, dss %d \n " ,
2017-02-16 23:07:37 +03:00
spi - > mode , div_cpsr , div_scr , dss ) ;
2017-08-08 23:51:29 +03:00
dev_dbg ( & master - > dev , " setup: cr0 %#x \n " , cr0 ) ;
2010-05-06 08:47:04 +04:00
2017-08-08 23:51:26 +03:00
writel ( div_cpsr , espi - > mmio + SSPCPSR ) ;
writel ( cr0 , espi - > mmio + SSPCR0 ) ;
2013-07-02 21:10:29 +04:00
return 0 ;
2010-05-06 08:47:04 +04:00
}
2017-08-08 23:51:31 +03:00
static void ep93xx_do_write ( struct spi_master * master )
2010-05-06 08:47:04 +04:00
{
2017-08-08 23:51:31 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
struct spi_transfer * xfer = master - > cur_msg - > state ;
2017-08-08 23:51:26 +03:00
u32 val = 0 ;
2010-05-06 08:47:04 +04:00
2017-08-08 23:51:31 +03:00
if ( xfer - > bits_per_word > 8 ) {
if ( xfer - > tx_buf )
val = ( ( u16 * ) xfer - > tx_buf ) [ espi - > tx ] ;
2017-08-08 23:51:26 +03:00
espi - > tx + = 2 ;
2010-05-06 08:47:04 +04:00
} else {
2017-08-08 23:51:31 +03:00
if ( xfer - > tx_buf )
val = ( ( u8 * ) xfer - > tx_buf ) [ espi - > tx ] ;
2017-08-08 23:51:26 +03:00
espi - > tx + = 1 ;
2010-05-06 08:47:04 +04:00
}
2017-08-08 23:51:26 +03:00
writel ( val , espi - > mmio + SSPDR ) ;
2010-05-06 08:47:04 +04:00
}
2017-08-08 23:51:31 +03:00
static void ep93xx_do_read ( struct spi_master * master )
2010-05-06 08:47:04 +04:00
{
2017-08-08 23:51:31 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
struct spi_transfer * xfer = master - > cur_msg - > state ;
2017-08-08 23:51:26 +03:00
u32 val ;
2010-05-06 08:47:04 +04:00
2017-08-08 23:51:26 +03:00
val = readl ( espi - > mmio + SSPDR ) ;
2017-08-08 23:51:31 +03:00
if ( xfer - > bits_per_word > 8 ) {
if ( xfer - > rx_buf )
( ( u16 * ) xfer - > rx_buf ) [ espi - > rx ] = val ;
2017-08-08 23:51:26 +03:00
espi - > rx + = 2 ;
2010-05-06 08:47:04 +04:00
} else {
2017-08-08 23:51:31 +03:00
if ( xfer - > rx_buf )
( ( u8 * ) xfer - > rx_buf ) [ espi - > rx ] = val ;
2017-08-08 23:51:26 +03:00
espi - > rx + = 1 ;
2010-05-06 08:47:04 +04:00
}
}
/**
* ep93xx_spi_read_write ( ) - perform next RX / TX transfer
2020-07-17 16:54:14 +03:00
* @ master : SPI master
2010-05-06 08:47:04 +04:00
*
* This function transfers next bytes ( or half - words ) to / from RX / TX FIFOs . If
* called several times , the whole transfer will be completed . Returns
* % - EINPROGRESS when current transfer was not yet completed otherwise % 0.
*
* When this function is finished , RX FIFO should be empty and TX FIFO should be
* full .
*/
2017-08-08 23:51:29 +03:00
static int ep93xx_spi_read_write ( struct spi_master * master )
2010-05-06 08:47:04 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2017-08-08 23:51:31 +03:00
struct spi_transfer * xfer = master - > cur_msg - > state ;
2010-05-06 08:47:04 +04:00
/* read as long as RX FIFO has frames in it */
2017-08-08 23:51:26 +03:00
while ( ( readl ( espi - > mmio + SSPSR ) & SSPSR_RNE ) ) {
2017-08-08 23:51:31 +03:00
ep93xx_do_read ( master ) ;
2010-05-06 08:47:04 +04:00
espi - > fifo_level - - ;
}
/* write as long as TX FIFO has room */
2017-08-08 23:51:31 +03:00
while ( espi - > fifo_level < SPI_FIFO_SIZE & & espi - > tx < xfer - > len ) {
ep93xx_do_write ( master ) ;
2010-05-06 08:47:04 +04:00
espi - > fifo_level + + ;
}
2017-08-08 23:51:31 +03:00
if ( espi - > rx = = xfer - > len )
2010-05-06 08:47:04 +04:00
return 0 ;
return - EINPROGRESS ;
}
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
static enum dma_transfer_direction
ep93xx_dma_data_to_trans_dir ( enum dma_data_direction dir )
{
switch ( dir ) {
case DMA_TO_DEVICE :
return DMA_MEM_TO_DEV ;
case DMA_FROM_DEVICE :
return DMA_DEV_TO_MEM ;
default :
return DMA_TRANS_NONE ;
}
}
2011-05-29 14:10:06 +04:00
/**
* ep93xx_spi_dma_prepare ( ) - prepares a DMA transfer
2017-08-08 23:51:29 +03:00
* @ master : SPI master
2011-05-29 14:10:06 +04:00
* @ dir : DMA transfer direction
*
* Function configures the DMA , maps the buffer and prepares the DMA
* descriptor . Returns a valid DMA descriptor in case of success and ERR_PTR
* in case of failure .
*/
static struct dma_async_tx_descriptor *
2017-08-08 23:51:29 +03:00
ep93xx_spi_dma_prepare ( struct spi_master * master ,
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
enum dma_data_direction dir )
2011-05-29 14:10:06 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2017-08-08 23:51:31 +03:00
struct spi_transfer * xfer = master - > cur_msg - > state ;
2011-05-29 14:10:06 +04:00
struct dma_async_tx_descriptor * txd ;
enum dma_slave_buswidth buswidth ;
struct dma_slave_config conf ;
struct scatterlist * sg ;
struct sg_table * sgt ;
struct dma_chan * chan ;
const void * buf , * pbuf ;
2017-08-08 23:51:31 +03:00
size_t len = xfer - > len ;
2011-05-29 14:10:06 +04:00
int i , ret , nents ;
2017-08-08 23:51:31 +03:00
if ( xfer - > bits_per_word > 8 )
2011-05-29 14:10:06 +04:00
buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES ;
else
buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE ;
memset ( & conf , 0 , sizeof ( conf ) ) ;
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
conf . direction = ep93xx_dma_data_to_trans_dir ( dir ) ;
2011-05-29 14:10:06 +04:00
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
if ( dir = = DMA_FROM_DEVICE ) {
2011-05-29 14:10:06 +04:00
chan = espi - > dma_rx ;
2017-08-08 23:51:31 +03:00
buf = xfer - > rx_buf ;
2011-05-29 14:10:06 +04:00
sgt = & espi - > rx_sgt ;
conf . src_addr = espi - > sspdr_phys ;
conf . src_addr_width = buswidth ;
} else {
chan = espi - > dma_tx ;
2017-08-08 23:51:31 +03:00
buf = xfer - > tx_buf ;
2011-05-29 14:10:06 +04:00
sgt = & espi - > tx_sgt ;
conf . dst_addr = espi - > sspdr_phys ;
conf . dst_addr_width = buswidth ;
}
ret = dmaengine_slave_config ( chan , & conf ) ;
if ( ret )
return ERR_PTR ( ret ) ;
/*
* We need to split the transfer into PAGE_SIZE ' d chunks . This is
* because we are using @ espi - > zeropage to provide a zero RX buffer
* for the TX transfers and we have only allocated one page for that .
*
* For performance reasons we allocate a new sg_table only when
* needed . Otherwise we will re - use the current one . Eventually the
* last sg_table is released in ep93xx_spi_release_dma ( ) .
*/
nents = DIV_ROUND_UP ( len , PAGE_SIZE ) ;
if ( nents ! = sgt - > nents ) {
sg_free_table ( sgt ) ;
ret = sg_alloc_table ( sgt , nents , GFP_KERNEL ) ;
if ( ret )
return ERR_PTR ( ret ) ;
}
pbuf = buf ;
for_each_sg ( sgt - > sgl , sg , sgt - > nents , i ) {
size_t bytes = min_t ( size_t , len , PAGE_SIZE ) ;
if ( buf ) {
sg_set_page ( sg , virt_to_page ( pbuf ) , bytes ,
offset_in_page ( pbuf ) ) ;
} else {
sg_set_page ( sg , virt_to_page ( espi - > zeropage ) ,
bytes , 0 ) ;
}
pbuf + = bytes ;
len - = bytes ;
}
if ( WARN_ON ( len ) ) {
2017-08-08 23:51:29 +03:00
dev_warn ( & master - > dev , " len = %zu expected 0! \n " , len ) ;
2011-05-29 14:10:06 +04:00
return ERR_PTR ( - EINVAL ) ;
}
nents = dma_map_sg ( chan - > device - > dev , sgt - > sgl , sgt - > nents , dir ) ;
if ( ! nents )
return ERR_PTR ( - ENOMEM ) ;
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
txd = dmaengine_prep_slave_sg ( chan , sgt - > sgl , nents , conf . direction ,
DMA_CTRL_ACK ) ;
2011-05-29 14:10:06 +04:00
if ( ! txd ) {
dma_unmap_sg ( chan - > device - > dev , sgt - > sgl , sgt - > nents , dir ) ;
return ERR_PTR ( - ENOMEM ) ;
}
return txd ;
}
/**
* ep93xx_spi_dma_finish ( ) - finishes with a DMA transfer
2017-08-08 23:51:29 +03:00
* @ master : SPI master
2011-05-29 14:10:06 +04:00
* @ dir : DMA transfer direction
*
* Function finishes with the DMA transfer . After this , the DMA buffer is
* unmapped .
*/
2017-08-08 23:51:29 +03:00
static void ep93xx_spi_dma_finish ( struct spi_master * master ,
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
enum dma_data_direction dir )
2011-05-29 14:10:06 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2011-05-29 14:10:06 +04:00
struct dma_chan * chan ;
struct sg_table * sgt ;
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
if ( dir = = DMA_FROM_DEVICE ) {
2011-05-29 14:10:06 +04:00
chan = espi - > dma_rx ;
sgt = & espi - > rx_sgt ;
} else {
chan = espi - > dma_tx ;
sgt = & espi - > tx_sgt ;
}
dma_unmap_sg ( chan - > device - > dev , sgt - > sgl , sgt - > nents , dir ) ;
}
static void ep93xx_spi_dma_callback ( void * callback_param )
{
2017-08-08 23:51:31 +03:00
struct spi_master * master = callback_param ;
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
ep93xx_spi_dma_finish ( master , DMA_TO_DEVICE ) ;
ep93xx_spi_dma_finish ( master , DMA_FROM_DEVICE ) ;
2017-08-08 23:51:31 +03:00
spi_finalize_current_transfer ( master ) ;
2011-05-29 14:10:06 +04:00
}
2017-08-08 23:51:31 +03:00
static int ep93xx_spi_dma_transfer ( struct spi_master * master )
2011-05-29 14:10:06 +04:00
{
2017-08-08 23:51:29 +03:00
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2011-05-29 14:10:06 +04:00
struct dma_async_tx_descriptor * rxd , * txd ;
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
rxd = ep93xx_spi_dma_prepare ( master , DMA_FROM_DEVICE ) ;
2011-05-29 14:10:06 +04:00
if ( IS_ERR ( rxd ) ) {
2017-08-08 23:51:29 +03:00
dev_err ( & master - > dev , " DMA RX failed: %ld \n " , PTR_ERR ( rxd ) ) ;
2017-08-08 23:51:31 +03:00
return PTR_ERR ( rxd ) ;
2011-05-29 14:10:06 +04:00
}
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
txd = ep93xx_spi_dma_prepare ( master , DMA_TO_DEVICE ) ;
2011-05-29 14:10:06 +04:00
if ( IS_ERR ( txd ) ) {
spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
Clang warns when one enumerated type is implicitly converted to another.
drivers/spi/spi-ep93xx.c:342:62: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:428:58: note: expanded from macro
'dma_map_sg'
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:348:57: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
drivers/spi/spi-ep93xx.c:377:56: warning: implicit conversion from
enumeration type 'enum dma_transfer_direction' to different enumeration
type 'enum dma_data_direction' [-Wenum-conversion]
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
./include/linux/dma-mapping.h:429:62: note: expanded from macro
'dma_unmap_sg'
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
~~~~~~~~~~~~~~~~~~ ^
3 warnings generated.
dma_{,un}map_sg expect an enum of type dma_data_direction but this
driver uses dma_transfer_direction for everything. Convert the driver to
use dma_data_direction for these two functions.
There are two places that strictly require an enum of type
dma_transfer_direction: the direction member in struct dma_slave_config
and the direction parameter in dmaengine_prep_slave_sg. To avoid using
an explicit cast, add a simple function, ep93xx_dma_data_to_trans_dir,
to safely map between the two types because they are not 1 to 1 in
meaning.
Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2018-10-08 21:08:47 +03:00
ep93xx_spi_dma_finish ( master , DMA_FROM_DEVICE ) ;
2017-08-08 23:51:29 +03:00
dev_err ( & master - > dev , " DMA TX failed: %ld \n " , PTR_ERR ( txd ) ) ;
2017-08-08 23:51:31 +03:00
return PTR_ERR ( txd ) ;
2011-05-29 14:10:06 +04:00
}
/* We are ready when RX is done */
rxd - > callback = ep93xx_spi_dma_callback ;
2017-08-08 23:51:31 +03:00
rxd - > callback_param = master ;
2011-05-29 14:10:06 +04:00
2017-08-08 23:51:31 +03:00
/* Now submit both descriptors and start DMA */
2011-05-29 14:10:06 +04:00
dmaengine_submit ( rxd ) ;
dmaengine_submit ( txd ) ;
dma_async_issue_pending ( espi - > dma_rx ) ;
dma_async_issue_pending ( espi - > dma_tx ) ;
2017-08-08 23:51:31 +03:00
/* signal that we need to wait for completion */
return 1 ;
2010-05-06 08:47:04 +04:00
}
static irqreturn_t ep93xx_spi_interrupt ( int irq , void * dev_id )
{
2017-08-08 23:51:29 +03:00
struct spi_master * master = dev_id ;
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2017-08-08 23:51:28 +03:00
u32 val ;
2010-05-06 08:47:04 +04:00
/*
* If we got ROR ( receive overrun ) interrupt we know that something is
* wrong . Just abort the message .
*/
2017-08-08 23:51:26 +03:00
if ( readl ( espi - > mmio + SSPIIR ) & SSPIIR_RORIS ) {
2010-05-06 08:47:04 +04:00
/* clear the overrun interrupt */
2017-08-08 23:51:26 +03:00
writel ( 0 , espi - > mmio + SSPICR ) ;
2017-08-08 23:51:29 +03:00
dev_warn ( & master - > dev ,
2010-05-06 08:47:04 +04:00
" receive overrun, aborting the message \n " ) ;
2017-08-08 23:51:30 +03:00
master - > cur_msg - > status = - EIO ;
2010-05-06 08:47:04 +04:00
} else {
/*
* Interrupt is either RX ( RIS ) or TX ( TIS ) . For both cases we
* simply execute next data transfer .
*/
2017-08-08 23:51:29 +03:00
if ( ep93xx_spi_read_write ( master ) ) {
2010-05-06 08:47:04 +04:00
/*
* In normal case , there still is some processing left
* for current transfer . Let ' s wait for the next
* interrupt then .
*/
return IRQ_HANDLED ;
}
}
/*
* Current transfer is finished , either with error or with success . In
* any case we disable interrupts and notify the worker to handle
* any post - processing of the message .
*/
2017-08-08 23:51:28 +03:00
val = readl ( espi - > mmio + SSPCR1 ) ;
val & = ~ ( SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE ) ;
writel ( val , espi - > mmio + SSPCR1 ) ;
2017-08-08 23:51:31 +03:00
spi_finalize_current_transfer ( master ) ;
2017-08-08 23:51:28 +03:00
2010-05-06 08:47:04 +04:00
return IRQ_HANDLED ;
}
2017-08-08 23:51:31 +03:00
static int ep93xx_spi_transfer_one ( struct spi_master * master ,
struct spi_device * spi ,
struct spi_transfer * xfer )
{
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
u32 val ;
int ret ;
ret = ep93xx_spi_chip_setup ( master , spi , xfer ) ;
if ( ret ) {
dev_err ( & master - > dev , " failed to setup chip for transfer \n " ) ;
return ret ;
}
master - > cur_msg - > state = xfer ;
espi - > rx = 0 ;
espi - > tx = 0 ;
/*
* There is no point of setting up DMA for the transfers which will
* fit into the FIFO and can be transferred with a single interrupt .
* So in these cases we will be using PIO and don ' t bother for DMA .
*/
if ( espi - > dma_rx & & xfer - > len > SPI_FIFO_SIZE )
return ep93xx_spi_dma_transfer ( master ) ;
/* Using PIO so prime the TX FIFO and enable interrupts */
ep93xx_spi_read_write ( master ) ;
val = readl ( espi - > mmio + SSPCR1 ) ;
val | = ( SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE ) ;
writel ( val , espi - > mmio + SSPCR1 ) ;
/* signal that we need to wait for completion */
return 1 ;
}
static int ep93xx_spi_prepare_message ( struct spi_master * master ,
struct spi_message * msg )
{
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
unsigned long timeout ;
/*
* Just to be sure : flush any data from RX FIFO .
*/
timeout = jiffies + msecs_to_jiffies ( SPI_TIMEOUT ) ;
while ( readl ( espi - > mmio + SSPSR ) & SSPSR_RNE ) {
if ( time_after ( jiffies , timeout ) ) {
dev_warn ( & master - > dev ,
" timeout while flushing RX FIFO \n " ) ;
return - ETIMEDOUT ;
}
readl ( espi - > mmio + SSPDR ) ;
}
/*
* We explicitly handle FIFO level . This way we don ' t have to check TX
* FIFO status using % SSPSR_TNF bit which may cause RX FIFO overruns .
*/
espi - > fifo_level = 0 ;
return 0 ;
}
2017-08-08 23:51:27 +03:00
static int ep93xx_spi_prepare_hardware ( struct spi_master * master )
{
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
u32 val ;
int ret ;
ret = clk_enable ( espi - > clk ) ;
if ( ret )
return ret ;
val = readl ( espi - > mmio + SSPCR1 ) ;
val | = SSPCR1_SSE ;
writel ( val , espi - > mmio + SSPCR1 ) ;
return 0 ;
}
static int ep93xx_spi_unprepare_hardware ( struct spi_master * master )
{
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
u32 val ;
val = readl ( espi - > mmio + SSPCR1 ) ;
val & = ~ SSPCR1_SSE ;
writel ( val , espi - > mmio + SSPCR1 ) ;
clk_disable ( espi - > clk ) ;
return 0 ;
}
2011-05-29 14:10:06 +04:00
static bool ep93xx_spi_dma_filter ( struct dma_chan * chan , void * filter_param )
{
if ( ep93xx_dma_chan_is_m2p ( chan ) )
return false ;
chan - > private = filter_param ;
return true ;
}
static int ep93xx_spi_setup_dma ( struct ep93xx_spi * espi )
{
dma_cap_mask_t mask ;
int ret ;
espi - > zeropage = ( void * ) get_zeroed_page ( GFP_KERNEL ) ;
if ( ! espi - > zeropage )
return - ENOMEM ;
dma_cap_zero ( mask ) ;
dma_cap_set ( DMA_SLAVE , mask ) ;
espi - > dma_rx_data . port = EP93XX_DMA_SSP ;
2011-10-14 09:17:38 +04:00
espi - > dma_rx_data . direction = DMA_DEV_TO_MEM ;
2011-05-29 14:10:06 +04:00
espi - > dma_rx_data . name = " ep93xx-spi-rx " ;
espi - > dma_rx = dma_request_channel ( mask , ep93xx_spi_dma_filter ,
& espi - > dma_rx_data ) ;
if ( ! espi - > dma_rx ) {
ret = - ENODEV ;
goto fail_free_page ;
}
espi - > dma_tx_data . port = EP93XX_DMA_SSP ;
2011-10-14 09:17:38 +04:00
espi - > dma_tx_data . direction = DMA_MEM_TO_DEV ;
2011-05-29 14:10:06 +04:00
espi - > dma_tx_data . name = " ep93xx-spi-tx " ;
espi - > dma_tx = dma_request_channel ( mask , ep93xx_spi_dma_filter ,
& espi - > dma_tx_data ) ;
if ( ! espi - > dma_tx ) {
ret = - ENODEV ;
goto fail_release_rx ;
}
return 0 ;
fail_release_rx :
dma_release_channel ( espi - > dma_rx ) ;
espi - > dma_rx = NULL ;
fail_free_page :
free_page ( ( unsigned long ) espi - > zeropage ) ;
return ret ;
}
static void ep93xx_spi_release_dma ( struct ep93xx_spi * espi )
{
if ( espi - > dma_rx ) {
dma_release_channel ( espi - > dma_rx ) ;
sg_free_table ( & espi - > rx_sgt ) ;
}
if ( espi - > dma_tx ) {
dma_release_channel ( espi - > dma_tx ) ;
sg_free_table ( & espi - > tx_sgt ) ;
}
if ( espi - > zeropage )
free_page ( ( unsigned long ) espi - > zeropage ) ;
}
2012-12-07 20:57:14 +04:00
static int ep93xx_spi_probe ( struct platform_device * pdev )
2010-05-06 08:47:04 +04:00
{
struct spi_master * master ;
struct ep93xx_spi_info * info ;
struct ep93xx_spi * espi ;
struct resource * res ;
2012-05-09 18:26:26 +04:00
int irq ;
2010-05-06 08:47:04 +04:00
int error ;
2013-07-30 11:58:59 +04:00
info = dev_get_platdata ( & pdev - > dev ) ;
2017-02-16 23:07:37 +03:00
if ( ! info ) {
dev_err ( & pdev - > dev , " missing platform data \n " ) ;
return - EINVAL ;
}
2010-05-06 08:47:04 +04:00
2013-07-02 21:07:53 +04:00
irq = platform_get_irq ( pdev , 0 ) ;
2019-07-30 21:15:41 +03:00
if ( irq < 0 )
2013-07-02 21:07:53 +04:00
return - EBUSY ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( ! res ) {
dev_err ( & pdev - > dev , " unable to get iomem resource \n " ) ;
return - ENODEV ;
}
2010-05-06 08:47:04 +04:00
master = spi_alloc_master ( & pdev - > dev , sizeof ( * espi ) ) ;
2013-07-02 21:08:59 +04:00
if ( ! master )
2010-05-06 08:47:04 +04:00
return - ENOMEM ;
2019-04-20 14:05:59 +03:00
master - > use_gpio_descriptors = true ;
2017-08-08 23:51:27 +03:00
master - > prepare_transfer_hardware = ep93xx_spi_prepare_hardware ;
master - > unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware ;
2017-08-08 23:51:31 +03:00
master - > prepare_message = ep93xx_spi_prepare_message ;
master - > transfer_one = ep93xx_spi_transfer_one ;
2010-05-06 08:47:04 +04:00
master - > bus_num = pdev - > id ;
master - > mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH ;
2013-05-22 06:36:35 +04:00
master - > bits_per_word_mask = SPI_BPW_RANGE_MASK ( 4 , 16 ) ;
2019-04-20 14:05:59 +03:00
/*
* The SPI core will count the number of GPIO descriptors to figure
* out the number of chip selects available on the platform .
*/
master - > num_chipselect = 0 ;
2017-02-16 23:07:37 +03:00
2010-05-06 08:47:04 +04:00
platform_set_drvdata ( pdev , master ) ;
espi = spi_master_get_devdata ( master ) ;
2013-07-02 21:08:21 +04:00
espi - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
2010-05-06 08:47:04 +04:00
if ( IS_ERR ( espi - > clk ) ) {
dev_err ( & pdev - > dev , " unable to get spi clock \n " ) ;
error = PTR_ERR ( espi - > clk ) ;
goto fail_release_master ;
}
/*
* Calculate maximum and minimum supported clock rates
* for the controller .
*/
2014-02-08 19:52:26 +04:00
master - > max_speed_hz = clk_get_rate ( espi - > clk ) / 2 ;
master - > min_speed_hz = clk_get_rate ( espi - > clk ) / ( 254 * 256 ) ;
2010-05-06 08:47:04 +04:00
2011-05-29 14:10:06 +04:00
espi - > sspdr_phys = res - > start + SSPDR ;
2012-05-09 18:26:26 +04:00
2017-08-08 23:51:25 +03:00
espi - > mmio = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( espi - > mmio ) ) {
error = PTR_ERR ( espi - > mmio ) ;
2013-07-02 21:08:21 +04:00
goto fail_release_master ;
2010-05-06 08:47:04 +04:00
}
2012-05-09 18:26:26 +04:00
error = devm_request_irq ( & pdev - > dev , irq , ep93xx_spi_interrupt ,
2017-08-08 23:51:29 +03:00
0 , " ep93xx-spi " , master ) ;
2010-05-06 08:47:04 +04:00
if ( error ) {
dev_err ( & pdev - > dev , " failed to request irq \n " ) ;
2013-07-02 21:08:21 +04:00
goto fail_release_master ;
2010-05-06 08:47:04 +04:00
}
2011-05-29 14:10:06 +04:00
if ( info - > use_dma & & ep93xx_spi_setup_dma ( espi ) )
dev_warn ( & pdev - > dev , " DMA setup failed. Falling back to PIO \n " ) ;
2010-05-06 08:47:04 +04:00
/* make sure that the hardware is disabled */
2017-08-08 23:51:26 +03:00
writel ( 0 , espi - > mmio + SSPCR1 ) ;
2010-05-06 08:47:04 +04:00
2013-09-24 08:30:41 +04:00
error = devm_spi_register_master ( & pdev - > dev , master ) ;
2010-05-06 08:47:04 +04:00
if ( error ) {
dev_err ( & pdev - > dev , " failed to register SPI master \n " ) ;
2013-07-08 20:12:37 +04:00
goto fail_free_dma ;
2010-05-06 08:47:04 +04:00
}
dev_info ( & pdev - > dev , " EP93xx SPI Controller at 0x%08lx irq %d \n " ,
2012-05-09 18:26:26 +04:00
( unsigned long ) res - > start , irq ) ;
2010-05-06 08:47:04 +04:00
return 0 ;
2011-05-29 14:10:06 +04:00
fail_free_dma :
ep93xx_spi_release_dma ( espi ) ;
2010-05-06 08:47:04 +04:00
fail_release_master :
spi_master_put ( master ) ;
return error ;
}
2012-12-07 20:57:14 +04:00
static int ep93xx_spi_remove ( struct platform_device * pdev )
2010-05-06 08:47:04 +04:00
{
struct spi_master * master = platform_get_drvdata ( pdev ) ;
struct ep93xx_spi * espi = spi_master_get_devdata ( master ) ;
2011-05-29 14:10:06 +04:00
ep93xx_spi_release_dma ( espi ) ;
2010-05-06 08:47:04 +04:00
return 0 ;
}
static struct platform_driver ep93xx_spi_driver = {
. driver = {
. name = " ep93xx-spi " ,
} ,
2011-10-05 21:29:49 +04:00
. probe = ep93xx_spi_probe ,
2012-12-07 20:57:14 +04:00
. remove = ep93xx_spi_remove ,
2010-05-06 08:47:04 +04:00
} ;
2011-10-05 21:29:49 +04:00
module_platform_driver ( ep93xx_spi_driver ) ;
2010-05-06 08:47:04 +04:00
MODULE_DESCRIPTION ( " EP93xx SPI Controller driver " ) ;
MODULE_AUTHOR ( " Mika Westerberg <mika.westerberg@iki.fi> " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform:ep93xx-spi " ) ;