2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2008-08-06 00:01:09 +04:00
/*
2011-06-06 11:16:30 +04:00
* Marvell Orion SPI controller driver
2008-08-06 00:01:09 +04:00
*
* Author : Shadi Ammouri < shadi @ marvell . com >
* Copyright ( C ) 2007 - 2008 Marvell Ltd .
*/
# include <linux/interrupt.h>
# include <linux/delay.h>
# include <linux/platform_device.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/spi/spi.h>
2011-07-03 23:44:29 +04:00
# include <linux/module.h>
2014-06-21 15:22:37 +04:00
# include <linux/pm_runtime.h>
2012-07-23 14:08:09 +04:00
# include <linux/of.h>
2016-05-19 10:07:05 +03:00
# include <linux/of_address.h>
2014-09-28 17:24:04 +04:00
# include <linux/of_device.h>
2012-04-06 19:17:26 +04:00
# include <linux/clk.h>
2013-07-29 08:10:21 +04:00
# include <linux/sizes.h>
2008-08-06 00:01:09 +04:00
# include <asm/unaligned.h>
# define DRIVER_NAME "orion_spi"
2014-06-21 15:22:37 +04:00
/* Runtime PM autosuspend timeout: PM is fairly light on this driver */
# define SPI_AUTOSUSPEND_TIMEOUT 200
2015-01-16 06:10:47 +03:00
/* Some SoCs using this driver support up to 8 chip selects.
* It is up to the implementer to only use the chip selects
* that are available .
*/
# define ORION_NUM_CHIPSELECTS 8
2008-08-06 00:01:09 +04:00
# define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
# define ORION_SPI_IF_CTRL_REG 0x00
# define ORION_SPI_IF_CONFIG_REG 0x04
2017-04-07 16:52:33 +03:00
# define ORION_SPI_IF_RXLSBF BIT(14)
# define ORION_SPI_IF_TXLSBF BIT(13)
2008-08-06 00:01:09 +04:00
# define ORION_SPI_DATA_OUT_REG 0x08
# define ORION_SPI_DATA_IN_REG 0x0c
# define ORION_SPI_INT_CAUSE_REG 0x10
2015-08-11 12:58:47 +03:00
# define ORION_SPI_TIMING_PARAMS_REG 0x18
2016-05-19 10:07:05 +03:00
/* Register for the "Direct Mode" */
# define SPI_DIRECT_WRITE_CONFIG_REG 0x20
2015-08-11 12:58:47 +03:00
# define ORION_SPI_TMISO_SAMPLE_MASK (0x3 << 6)
# define ORION_SPI_TMISO_SAMPLE_1 (1 << 6)
# define ORION_SPI_TMISO_SAMPLE_2 (2 << 6)
2008-08-06 00:01:09 +04:00
2012-11-21 23:23:35 +04:00
# define ORION_SPI_MODE_CPOL (1 << 11)
# define ORION_SPI_MODE_CPHA (1 << 12)
2008-08-06 00:01:09 +04:00
# define ORION_SPI_IF_8_16_BIT_MODE (1 << 5)
# define ORION_SPI_CLK_PRESCALE_MASK 0x1F
2014-09-28 17:24:04 +04:00
# define ARMADA_SPI_CLK_PRESCALE_MASK 0xDF
2012-11-21 23:23:35 +04:00
# define ORION_SPI_MODE_MASK (ORION_SPI_MODE_CPOL | \
ORION_SPI_MODE_CPHA )
2015-01-16 06:10:47 +03:00
# define ORION_SPI_CS_MASK 0x1C
# define ORION_SPI_CS_SHIFT 2
# define ORION_SPI_CS(cs) ((cs << ORION_SPI_CS_SHIFT) & \
ORION_SPI_CS_MASK )
2008-08-06 00:01:09 +04:00
2014-09-28 17:24:04 +04:00
enum orion_spi_type {
ORION_SPI ,
ARMADA_SPI ,
} ;
struct orion_spi_dev {
enum orion_spi_type typ ;
2015-05-26 12:44:42 +03:00
/*
* min_divisor and max_hz should be exclusive , the only we can
* have both is for managing the armada - 370 - spi case with old
* device tree
*/
unsigned long max_hz ;
2014-09-28 17:24:04 +04:00
unsigned int min_divisor ;
unsigned int max_divisor ;
u32 prescale_mask ;
2015-08-11 12:58:47 +03:00
bool is_errata_50mhz_ac ;
2014-09-28 17:24:04 +04:00
} ;
2016-05-19 10:07:05 +03:00
struct orion_direct_acc {
void __iomem * vaddr ;
u32 size ;
} ;
2018-02-10 14:20:23 +03:00
struct orion_child_options {
struct orion_direct_acc direct_access ;
} ;
2008-08-06 00:01:09 +04:00
struct orion_spi {
struct spi_master * master ;
void __iomem * base ;
2012-04-06 19:17:26 +04:00
struct clk * clk ;
2018-01-12 13:42:33 +03:00
struct clk * axi_clk ;
2014-09-28 17:24:04 +04:00
const struct orion_spi_dev * devdata ;
2016-05-19 10:07:05 +03:00
2018-02-10 14:20:23 +03:00
struct orion_child_options child [ ORION_NUM_CHIPSELECTS ] ;
2008-08-06 00:01:09 +04:00
} ;
static inline void __iomem * spi_reg ( struct orion_spi * orion_spi , u32 reg )
{
return orion_spi - > base + reg ;
}
static inline void
orion_spi_setbits ( struct orion_spi * orion_spi , u32 reg , u32 mask )
{
void __iomem * reg_addr = spi_reg ( orion_spi , reg ) ;
u32 val ;
val = readl ( reg_addr ) ;
val | = mask ;
writel ( val , reg_addr ) ;
}
static inline void
orion_spi_clrbits ( struct orion_spi * orion_spi , u32 reg , u32 mask )
{
void __iomem * reg_addr = spi_reg ( orion_spi , reg ) ;
u32 val ;
val = readl ( reg_addr ) ;
val & = ~ mask ;
writel ( val , reg_addr ) ;
}
static int orion_spi_baudrate_set ( struct spi_device * spi , unsigned int speed )
{
u32 tclk_hz ;
u32 rate ;
u32 prescale ;
u32 reg ;
struct orion_spi * orion_spi ;
2014-09-28 17:24:04 +04:00
const struct orion_spi_dev * devdata ;
2008-08-06 00:01:09 +04:00
orion_spi = spi_master_get_devdata ( spi - > master ) ;
2014-09-28 17:24:04 +04:00
devdata = orion_spi - > devdata ;
2008-08-06 00:01:09 +04:00
2012-04-06 19:17:26 +04:00
tclk_hz = clk_get_rate ( orion_spi - > clk ) ;
2008-08-06 00:01:09 +04:00
2014-09-28 17:24:04 +04:00
if ( devdata - > typ = = ARMADA_SPI ) {
2016-12-08 19:37:08 +03:00
/*
* Given the core_clk ( tclk_hz ) and the target rate ( speed ) we
* determine the best values for SPR ( in [ 0 . . 15 ] ) and SPPR ( in
* [ 0. .7 ] ) such that
*
* core_clk / ( SPR * 2 * * SPPR )
*
* is as big as possible but not bigger than speed .
*/
2008-08-06 00:01:09 +04:00
2016-12-08 19:37:08 +03:00
/* best integer divider: */
unsigned divider = DIV_ROUND_UP ( tclk_hz , speed ) ;
unsigned spr , sppr ;
if ( divider < 16 ) {
/* This is the easy case, divider is less than 16 */
spr = divider ;
sppr = 0 ;
} else {
unsigned two_pow_sppr ;
/*
* Find the highest bit set in divider . This and the
* three next bits define SPR ( apart from rounding ) .
* SPPR is then the number of zero bits that must be
* appended :
*/
sppr = fls ( divider ) - 4 ;
/*
* As SPR only has 4 bits , we have to round divider up
* to the next multiple of 2 * * sppr .
*/
two_pow_sppr = 1 < < sppr ;
divider = ( divider + two_pow_sppr - 1 ) & - two_pow_sppr ;
/*
* recalculate sppr as rounding up divider might have
* increased it enough to change the position of the
* highest set bit . In this case the bit that now
* doesn ' t make it into SPR is 0 , so there is no need to
* round again .
*/
sppr = fls ( divider ) - 4 ;
spr = divider > > sppr ;
/*
* Now do range checking . SPR is constructed to have a
* width of 4 bits , so this is fine for sure . So we
* still need to check for sppr to fit into 3 bits :
*/
if ( sppr > 7 )
return - EINVAL ;
}
2014-09-28 17:24:04 +04:00
2016-12-08 19:37:08 +03:00
prescale = ( ( sppr & 0x6 ) < < 5 ) | ( ( sppr & 0x1 ) < < 4 ) | spr ;
2014-09-28 17:24:04 +04:00
} else {
/*
* the supported rates are : 4 , 6 , 8. . .30
* round up as we look for equal or less speed
*/
rate = DIV_ROUND_UP ( tclk_hz , speed ) ;
rate = roundup ( rate , 2 ) ;
/* check if requested speed is too small */
if ( rate > 30 )
return - EINVAL ;
2008-08-06 00:01:09 +04:00
2014-09-28 17:24:04 +04:00
if ( rate < 4 )
rate = 4 ;
/* Convert the rate to SPI clock divisor value. */
prescale = 0x10 + rate / 2 ;
}
2008-08-06 00:01:09 +04:00
reg = readl ( spi_reg ( orion_spi , ORION_SPI_IF_CONFIG_REG ) ) ;
2014-09-28 17:24:04 +04:00
reg = ( ( reg & ~ devdata - > prescale_mask ) | prescale ) ;
2008-08-06 00:01:09 +04:00
writel ( reg , spi_reg ( orion_spi , ORION_SPI_IF_CONFIG_REG ) ) ;
return 0 ;
}
2012-11-21 23:23:35 +04:00
static void
orion_spi_mode_set ( struct spi_device * spi )
{
u32 reg ;
struct orion_spi * orion_spi ;
orion_spi = spi_master_get_devdata ( spi - > master ) ;
reg = readl ( spi_reg ( orion_spi , ORION_SPI_IF_CONFIG_REG ) ) ;
reg & = ~ ORION_SPI_MODE_MASK ;
if ( spi - > mode & SPI_CPOL )
reg | = ORION_SPI_MODE_CPOL ;
if ( spi - > mode & SPI_CPHA )
reg | = ORION_SPI_MODE_CPHA ;
2017-04-07 16:52:33 +03:00
if ( spi - > mode & SPI_LSB_FIRST )
reg | = ORION_SPI_IF_RXLSBF | ORION_SPI_IF_TXLSBF ;
else
reg & = ~ ( ORION_SPI_IF_RXLSBF | ORION_SPI_IF_TXLSBF ) ;
2012-11-21 23:23:35 +04:00
writel ( reg , spi_reg ( orion_spi , ORION_SPI_IF_CONFIG_REG ) ) ;
}
2015-08-11 12:58:47 +03:00
static void
orion_spi_50mhz_ac_timing_erratum ( struct spi_device * spi , unsigned int speed )
{
u32 reg ;
struct orion_spi * orion_spi ;
orion_spi = spi_master_get_devdata ( spi - > master ) ;
/*
* Erratum description : ( Erratum NO . FE - 9144572 ) The device
* SPI interface supports frequencies of up to 50 MHz .
* However , due to this erratum , when the device core clock is
* 250 MHz and the SPI interfaces is configured for 50 MHz SPI
* clock and CPOL = CPHA = 1 there might occur data corruption on
* reads from the SPI device .
* Erratum Workaround :
* Work in one of the following configurations :
* 1. Set CPOL = CPHA = 0 in " SPI Interface Configuration
* Register " .
* 2. Set TMISO_SAMPLE value to 0x2 in " SPI Timing Parameters 1
* Register " before setting the interface.
*/
reg = readl ( spi_reg ( orion_spi , ORION_SPI_TIMING_PARAMS_REG ) ) ;
reg & = ~ ORION_SPI_TMISO_SAMPLE_MASK ;
if ( clk_get_rate ( orion_spi - > clk ) = = 250000000 & &
speed = = 50000000 & & spi - > mode & SPI_CPOL & &
spi - > mode & SPI_CPHA )
reg | = ORION_SPI_TMISO_SAMPLE_2 ;
else
reg | = ORION_SPI_TMISO_SAMPLE_1 ; /* This is the default value */
writel ( reg , spi_reg ( orion_spi , ORION_SPI_TIMING_PARAMS_REG ) ) ;
}
2008-08-06 00:01:09 +04:00
/*
* called only when no transfer is active on the bus
*/
static int
orion_spi_setup_transfer ( struct spi_device * spi , struct spi_transfer * t )
{
struct orion_spi * orion_spi ;
unsigned int speed = spi - > max_speed_hz ;
unsigned int bits_per_word = spi - > bits_per_word ;
int rc ;
orion_spi = spi_master_get_devdata ( spi - > master ) ;
if ( ( t ! = NULL ) & & t - > speed_hz )
speed = t - > speed_hz ;
if ( ( t ! = NULL ) & & t - > bits_per_word )
bits_per_word = t - > bits_per_word ;
2012-11-21 23:23:35 +04:00
orion_spi_mode_set ( spi ) ;
2015-08-11 12:58:47 +03:00
if ( orion_spi - > devdata - > is_errata_50mhz_ac )
orion_spi_50mhz_ac_timing_erratum ( spi , speed ) ;
2008-08-06 00:01:09 +04:00
rc = orion_spi_baudrate_set ( spi , speed ) ;
if ( rc )
return rc ;
2014-02-11 16:51:36 +04:00
if ( bits_per_word = = 16 )
orion_spi_setbits ( orion_spi , ORION_SPI_IF_CONFIG_REG ,
ORION_SPI_IF_8_16_BIT_MODE ) ;
else
orion_spi_clrbits ( orion_spi , ORION_SPI_IF_CONFIG_REG ,
ORION_SPI_IF_8_16_BIT_MODE ) ;
return 0 ;
2008-08-06 00:01:09 +04:00
}
2015-01-12 06:13:59 +03:00
static void orion_spi_set_cs ( struct spi_device * spi , bool enable )
2008-08-06 00:01:09 +04:00
{
2015-01-12 06:13:59 +03:00
struct orion_spi * orion_spi ;
2017-05-23 07:03:21 +03:00
2018-01-27 01:56:10 +03:00
orion_spi = spi_master_get_devdata ( spi - > master ) ;
2020-04-15 20:56:13 +03:00
/*
* If this line is using a GPIO to control chip select , this internal
* . set_cs ( ) function will still be called , so we clear any previous
* chip select . The CS we activate will not have any elecrical effect ,
* as it is handled by a GPIO , but that doesn ' t matter . What we need
* is to deassert the old chip select and assert some other chip select .
*/
2015-01-16 06:10:47 +03:00
orion_spi_clrbits ( orion_spi , ORION_SPI_IF_CTRL_REG , ORION_SPI_CS_MASK ) ;
orion_spi_setbits ( orion_spi , ORION_SPI_IF_CTRL_REG ,
2020-04-15 20:56:13 +03:00
ORION_SPI_CS ( spi - > chip_select ) ) ;
2015-01-16 06:10:47 +03:00
2020-04-15 20:56:13 +03:00
/*
* Chip select logic is inverted from spi_set_cs ( ) . For lines using a
* GPIO to do chip select SPI_CS_HIGH is enforced and inversion happens
* in the GPIO library , but we don ' t care about that , because in those
* cases we are dealing with an unused native CS anyways so the polarity
* doesn ' t matter .
*/
2015-01-12 06:13:59 +03:00
if ( ! enable )
2008-08-06 00:01:09 +04:00
orion_spi_setbits ( orion_spi , ORION_SPI_IF_CTRL_REG , 0x1 ) ;
else
orion_spi_clrbits ( orion_spi , ORION_SPI_IF_CTRL_REG , 0x1 ) ;
}
static inline int orion_spi_wait_till_ready ( struct orion_spi * orion_spi )
{
int i ;
for ( i = 0 ; i < ORION_SPI_WAIT_RDY_MAX_LOOP ; i + + ) {
if ( readl ( spi_reg ( orion_spi , ORION_SPI_INT_CAUSE_REG ) ) )
return 1 ;
2014-09-02 06:51:39 +04:00
udelay ( 1 ) ;
2008-08-06 00:01:09 +04:00
}
return - 1 ;
}
static inline int
orion_spi_write_read_8bit ( struct spi_device * spi ,
const u8 * * tx_buf , u8 * * rx_buf )
{
void __iomem * tx_reg , * rx_reg , * int_reg ;
struct orion_spi * orion_spi ;
orion_spi = spi_master_get_devdata ( spi - > master ) ;
tx_reg = spi_reg ( orion_spi , ORION_SPI_DATA_OUT_REG ) ;
rx_reg = spi_reg ( orion_spi , ORION_SPI_DATA_IN_REG ) ;
int_reg = spi_reg ( orion_spi , ORION_SPI_INT_CAUSE_REG ) ;
/* clear the interrupt cause register */
writel ( 0x0 , int_reg ) ;
if ( tx_buf & & * tx_buf )
writel ( * ( * tx_buf ) + + , tx_reg ) ;
else
writel ( 0 , tx_reg ) ;
if ( orion_spi_wait_till_ready ( orion_spi ) < 0 ) {
dev_err ( & spi - > dev , " TXS timed out \n " ) ;
return - 1 ;
}
if ( rx_buf & & * rx_buf )
* ( * rx_buf ) + + = readl ( rx_reg ) ;
return 1 ;
}
static inline int
orion_spi_write_read_16bit ( struct spi_device * spi ,
const u16 * * tx_buf , u16 * * rx_buf )
{
void __iomem * tx_reg , * rx_reg , * int_reg ;
struct orion_spi * orion_spi ;
orion_spi = spi_master_get_devdata ( spi - > master ) ;
tx_reg = spi_reg ( orion_spi , ORION_SPI_DATA_OUT_REG ) ;
rx_reg = spi_reg ( orion_spi , ORION_SPI_DATA_IN_REG ) ;
int_reg = spi_reg ( orion_spi , ORION_SPI_INT_CAUSE_REG ) ;
/* clear the interrupt cause register */
writel ( 0x0 , int_reg ) ;
if ( tx_buf & & * tx_buf )
writel ( __cpu_to_le16 ( get_unaligned ( ( * tx_buf ) + + ) ) , tx_reg ) ;
else
writel ( 0 , tx_reg ) ;
if ( orion_spi_wait_till_ready ( orion_spi ) < 0 ) {
dev_err ( & spi - > dev , " TXS timed out \n " ) ;
return - 1 ;
}
if ( rx_buf & & * rx_buf )
put_unaligned ( __le16_to_cpu ( readl ( rx_reg ) ) , ( * rx_buf ) + + ) ;
return 1 ;
}
static unsigned int
orion_spi_write_read ( struct spi_device * spi , struct spi_transfer * xfer )
{
unsigned int count ;
int word_len ;
2016-05-19 10:07:05 +03:00
struct orion_spi * orion_spi ;
int cs = spi - > chip_select ;
2018-08-15 22:04:49 +03:00
void __iomem * vaddr ;
2008-08-06 00:01:09 +04:00
word_len = spi - > bits_per_word ;
count = xfer - > len ;
2016-05-19 10:07:05 +03:00
orion_spi = spi_master_get_devdata ( spi - > master ) ;
/*
* Use SPI direct write mode if base address is available . Otherwise
* fall back to PIO mode for this transfer .
*/
2018-08-15 22:04:49 +03:00
vaddr = orion_spi - > child [ cs ] . direct_access . vaddr ;
if ( vaddr & & xfer - > tx_buf & & word_len = = 8 ) {
2016-05-19 10:07:05 +03:00
unsigned int cnt = count / 4 ;
unsigned int rem = count % 4 ;
/*
* Send the TX - data to the SPI device via the direct
* mapped address window
*/
2018-08-15 22:04:49 +03:00
iowrite32_rep ( vaddr , xfer - > tx_buf , cnt ) ;
2016-05-19 10:07:05 +03:00
if ( rem ) {
u32 * buf = ( u32 * ) xfer - > tx_buf ;
2018-08-15 22:04:49 +03:00
iowrite8_rep ( vaddr , & buf [ cnt ] , rem ) ;
2016-05-19 10:07:05 +03:00
}
return count ;
}
2008-08-06 00:01:09 +04:00
if ( word_len = = 8 ) {
const u8 * tx = xfer - > tx_buf ;
u8 * rx = xfer - > rx_buf ;
do {
if ( orion_spi_write_read_8bit ( spi , & tx , & rx ) < 0 )
goto out ;
count - - ;
2019-09-26 13:51:33 +03:00
spi_delay_exec ( & xfer - > word_delay , xfer ) ;
2008-08-06 00:01:09 +04:00
} while ( count ) ;
} else if ( word_len = = 16 ) {
const u16 * tx = xfer - > tx_buf ;
u16 * rx = xfer - > rx_buf ;
do {
if ( orion_spi_write_read_16bit ( spi , & tx , & rx ) < 0 )
goto out ;
count - = 2 ;
2019-09-26 13:51:33 +03:00
spi_delay_exec ( & xfer - > word_delay , xfer ) ;
2008-08-06 00:01:09 +04:00
} while ( count ) ;
}
out :
return xfer - > len - count ;
}
2015-01-12 06:13:59 +03:00
static int orion_spi_transfer_one ( struct spi_master * master ,
struct spi_device * spi ,
struct spi_transfer * t )
2008-08-06 00:01:09 +04:00
{
2012-07-23 15:16:55 +04:00
int status = 0 ;
2008-08-06 00:01:09 +04:00
2015-01-12 06:13:59 +03:00
status = orion_spi_setup_transfer ( spi , t ) ;
2012-07-23 15:16:55 +04:00
if ( status < 0 )
2015-01-12 06:13:59 +03:00
return status ;
2008-08-06 00:01:09 +04:00
2015-01-12 06:13:59 +03:00
if ( t - > len )
orion_spi_write_read ( spi , t ) ;
2012-07-23 15:16:55 +04:00
2015-01-12 06:13:59 +03:00
return status ;
}
2012-07-23 15:16:55 +04:00
2015-01-12 06:13:59 +03:00
static int orion_spi_setup ( struct spi_device * spi )
{
return orion_spi_setup_transfer ( spi , NULL ) ;
2008-08-06 00:01:09 +04:00
}
2013-02-05 17:27:35 +04:00
static int orion_spi_reset ( struct orion_spi * orion_spi )
2008-08-06 00:01:09 +04:00
{
/* Verify that the CS is deasserted */
2015-01-12 06:13:59 +03:00
orion_spi_clrbits ( orion_spi , ORION_SPI_IF_CTRL_REG , 0x1 ) ;
2016-05-19 10:07:05 +03:00
/* Don't deassert CS between the direct mapped SPI transfers */
writel ( 0 , spi_reg ( orion_spi , SPI_DIRECT_WRITE_CONFIG_REG ) ) ;
2008-08-06 00:01:09 +04:00
return 0 ;
}
2014-09-28 17:24:04 +04:00
static const struct orion_spi_dev orion_spi_dev_data = {
. typ = ORION_SPI ,
. min_divisor = 4 ,
. max_divisor = 30 ,
. prescale_mask = ORION_SPI_CLK_PRESCALE_MASK ,
} ;
2015-05-26 12:44:43 +03:00
static const struct orion_spi_dev armada_370_spi_dev_data = {
2014-09-28 17:24:04 +04:00
. typ = ARMADA_SPI ,
2015-05-26 12:44:42 +03:00
. min_divisor = 4 ,
2014-09-28 17:24:04 +04:00
. max_divisor = 1920 ,
2015-05-26 12:44:42 +03:00
. max_hz = 50000000 ,
2014-09-28 17:24:04 +04:00
. prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK ,
} ;
2015-05-26 12:44:43 +03:00
static const struct orion_spi_dev armada_xp_spi_dev_data = {
. typ = ARMADA_SPI ,
. max_hz = 50000000 ,
. max_divisor = 1920 ,
. prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK ,
} ;
static const struct orion_spi_dev armada_375_spi_dev_data = {
. typ = ARMADA_SPI ,
. min_divisor = 15 ,
. max_divisor = 1920 ,
. prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK ,
} ;
2015-08-11 12:58:47 +03:00
static const struct orion_spi_dev armada_380_spi_dev_data = {
. typ = ARMADA_SPI ,
. max_hz = 50000000 ,
. max_divisor = 1920 ,
. prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK ,
. is_errata_50mhz_ac = true ,
} ;
2014-09-28 17:24:04 +04:00
static const struct of_device_id orion_spi_of_match_table [ ] = {
2015-05-26 12:44:43 +03:00
{
. compatible = " marvell,orion-spi " ,
. data = & orion_spi_dev_data ,
} ,
{
. compatible = " marvell,armada-370-spi " ,
. data = & armada_370_spi_dev_data ,
} ,
{
. compatible = " marvell,armada-375-spi " ,
. data = & armada_375_spi_dev_data ,
} ,
{
. compatible = " marvell,armada-380-spi " ,
2015-08-11 12:58:47 +03:00
. data = & armada_380_spi_dev_data ,
2015-05-26 12:44:43 +03:00
} ,
{
. compatible = " marvell,armada-390-spi " ,
. data = & armada_xp_spi_dev_data ,
} ,
{
. compatible = " marvell,armada-xp-spi " ,
. data = & armada_xp_spi_dev_data ,
} ,
2014-09-28 17:24:04 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , orion_spi_of_match_table ) ;
2013-02-05 17:27:35 +04:00
static int orion_spi_probe ( struct platform_device * pdev )
2008-08-06 00:01:09 +04:00
{
2014-09-28 17:24:04 +04:00
const struct of_device_id * of_id ;
const struct orion_spi_dev * devdata ;
2008-08-06 00:01:09 +04:00
struct spi_master * master ;
struct orion_spi * spi ;
struct resource * r ;
2012-04-06 19:17:26 +04:00
unsigned long tclk_hz ;
2008-08-06 00:01:09 +04:00
int status = 0 ;
2016-05-19 10:07:05 +03:00
struct device_node * np ;
2008-08-06 00:01:09 +04:00
2013-10-14 05:35:08 +04:00
master = spi_alloc_master ( & pdev - > dev , sizeof ( * spi ) ) ;
2008-08-06 00:01:09 +04:00
if ( master = = NULL ) {
dev_dbg ( & pdev - > dev , " master allocation failed \n " ) ;
return - ENOMEM ;
}
if ( pdev - > id ! = - 1 )
master - > bus_num = pdev - > id ;
2012-07-23 14:08:09 +04:00
if ( pdev - > dev . of_node ) {
2014-07-28 01:53:19 +04:00
u32 cell_index ;
2014-09-02 06:51:39 +04:00
2014-07-28 01:53:19 +04:00
if ( ! of_property_read_u32 ( pdev - > dev . of_node , " cell-index " ,
& cell_index ) )
master - > bus_num = cell_index ;
2012-07-23 14:08:09 +04:00
}
2008-08-06 00:01:09 +04:00
2017-04-07 16:52:33 +03:00
/* we support all 4 SPI modes and LSB first option */
master - > mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST ;
2015-01-12 06:13:59 +03:00
master - > set_cs = orion_spi_set_cs ;
master - > transfer_one = orion_spi_transfer_one ;
2008-08-06 00:01:09 +04:00
master - > num_chipselect = ORION_NUM_CHIPSELECTS ;
2015-01-12 06:13:59 +03:00
master - > setup = orion_spi_setup ;
2014-02-11 16:51:36 +04:00
master - > bits_per_word_mask = SPI_BPW_MASK ( 8 ) | SPI_BPW_MASK ( 16 ) ;
2014-06-21 15:22:37 +04:00
master - > auto_runtime_pm = true ;
2020-04-15 20:56:13 +03:00
master - > use_gpio_descriptors = true ;
2017-05-23 07:03:21 +03:00
master - > flags = SPI_MASTER_GPIO_SS ;
2008-08-06 00:01:09 +04:00
2013-05-23 14:20:40 +04:00
platform_set_drvdata ( pdev , master ) ;
2008-08-06 00:01:09 +04:00
spi = spi_master_get_devdata ( master ) ;
spi - > master = master ;
2014-09-28 17:24:04 +04:00
of_id = of_match_device ( orion_spi_of_match_table , & pdev - > dev ) ;
2014-10-21 09:57:48 +04:00
devdata = ( of_id ) ? of_id - > data : & orion_spi_dev_data ;
2014-09-28 17:24:04 +04:00
spi - > devdata = devdata ;
2013-12-09 14:21:22 +04:00
spi - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
2012-04-06 19:17:26 +04:00
if ( IS_ERR ( spi - > clk ) ) {
status = PTR_ERR ( spi - > clk ) ;
goto out ;
}
2014-06-21 14:32:23 +04:00
status = clk_prepare_enable ( spi - > clk ) ;
if ( status )
goto out ;
2018-01-12 13:42:33 +03:00
/* The following clock is only used by some SoCs */
spi - > axi_clk = devm_clk_get ( & pdev - > dev , " axi " ) ;
2020-02-04 04:37:45 +03:00
if ( PTR_ERR ( spi - > axi_clk ) = = - EPROBE_DEFER ) {
2018-01-25 23:16:17 +03:00
status = - EPROBE_DEFER ;
goto out_rel_clk ;
}
2018-01-12 13:42:33 +03:00
if ( ! IS_ERR ( spi - > axi_clk ) )
clk_prepare_enable ( spi - > axi_clk ) ;
2012-04-06 19:17:26 +04:00
tclk_hz = clk_get_rate ( spi - > clk ) ;
2015-05-26 12:44:42 +03:00
/*
* With old device tree , armada - 370 - spi could be used with
* Armada XP , however for this SoC the maximum frequency is
* 50 MHz instead of tclk / 4. On Armada 370 , tclk cannot be
* higher than 200 MHz . So , in order to be able to handle both
* SoCs , we can take the minimum of 50 MHz and tclk / 4.
*/
if ( of_device_is_compatible ( pdev - > dev . of_node ,
" marvell,armada-370-spi " ) )
master - > max_speed_hz = min ( devdata - > max_hz ,
DIV_ROUND_UP ( tclk_hz , devdata - > min_divisor ) ) ;
2015-05-26 12:44:43 +03:00
else if ( devdata - > min_divisor )
2015-05-26 12:44:42 +03:00
master - > max_speed_hz =
DIV_ROUND_UP ( tclk_hz , devdata - > min_divisor ) ;
2015-05-26 12:44:43 +03:00
else
master - > max_speed_hz = devdata - > max_hz ;
2014-09-28 17:24:04 +04:00
master - > min_speed_hz = DIV_ROUND_UP ( tclk_hz , devdata - > max_divisor ) ;
2008-08-06 00:01:09 +04:00
r = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2013-07-28 17:38:06 +04:00
spi - > base = devm_ioremap_resource ( & pdev - > dev , r ) ;
if ( IS_ERR ( spi - > base ) ) {
status = PTR_ERR ( spi - > base ) ;
2018-01-25 23:16:17 +03:00
goto out_rel_axi_clk ;
2008-08-06 00:01:09 +04:00
}
2016-05-19 10:07:05 +03:00
for_each_available_child_of_node ( pdev - > dev . of_node , np ) {
2018-08-15 22:04:49 +03:00
struct orion_direct_acc * dir_acc ;
2016-05-19 10:07:05 +03:00
u32 cs ;
/* Get chip-select number from the "reg" property */
status = of_property_read_u32 ( np , " reg " , & cs ) ;
if ( status ) {
dev_err ( & pdev - > dev ,
2017-07-19 00:43:31 +03:00
" %pOF has no valid 'reg' property (%d) \n " ,
np , status ) ;
2016-05-19 10:07:05 +03:00
continue ;
}
/*
* Check if an address is configured for this SPI device . If
* not , the MBus mapping via the ' ranges ' property in the ' soc '
* node is not configured and this device should not use the
* direct mode . In this case , just continue with the next
* device .
*/
status = of_address_to_resource ( pdev - > dev . of_node , cs + 1 , r ) ;
if ( status )
continue ;
/*
* Only map one page for direct access . This is enough for the
* simple TX transfer which only writes to the first word .
2020-07-16 08:11:44 +03:00
* This needs to get extended for the direct SPI NOR / SPI NAND
2016-05-19 10:07:05 +03:00
* support , once this gets implemented .
*/
2018-08-15 22:04:49 +03:00
dir_acc = & spi - > child [ cs ] . direct_access ;
dir_acc - > vaddr = devm_ioremap ( & pdev - > dev , r - > start , PAGE_SIZE ) ;
if ( ! dir_acc - > vaddr ) {
2016-06-13 17:32:23 +03:00
status = - ENOMEM ;
2018-01-25 23:16:17 +03:00
goto out_rel_axi_clk ;
2016-05-19 10:07:05 +03:00
}
2018-08-15 22:04:49 +03:00
dir_acc - > size = PAGE_SIZE ;
2016-05-19 10:07:05 +03:00
dev_info ( & pdev - > dev , " CS%d configured for direct access \n " , cs ) ;
}
2014-06-21 15:22:37 +04:00
pm_runtime_set_active ( & pdev - > dev ) ;
pm_runtime_use_autosuspend ( & pdev - > dev ) ;
pm_runtime_set_autosuspend_delay ( & pdev - > dev , SPI_AUTOSUSPEND_TIMEOUT ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2014-07-20 18:03:14 +04:00
status = orion_spi_reset ( spi ) ;
if ( status < 0 )
2014-06-21 15:22:37 +04:00
goto out_rel_pm ;
2012-07-23 14:08:09 +04:00
master - > dev . of_node = pdev - > dev . of_node ;
2014-06-21 15:22:37 +04:00
status = spi_register_master ( master ) ;
2008-08-06 00:01:09 +04:00
if ( status < 0 )
2014-06-21 15:22:37 +04:00
goto out_rel_pm ;
2008-08-06 00:01:09 +04:00
return status ;
2014-06-21 15:22:37 +04:00
out_rel_pm :
pm_runtime_disable ( & pdev - > dev ) ;
2018-01-25 23:16:17 +03:00
out_rel_axi_clk :
2018-01-12 13:42:33 +03:00
clk_disable_unprepare ( spi - > axi_clk ) ;
2018-01-25 23:16:17 +03:00
out_rel_clk :
2012-04-06 19:17:26 +04:00
clk_disable_unprepare ( spi - > clk ) ;
2008-08-06 00:01:09 +04:00
out :
spi_master_put ( master ) ;
return status ;
}
2013-02-05 17:27:35 +04:00
static int orion_spi_remove ( struct platform_device * pdev )
2008-08-06 00:01:09 +04:00
{
2014-06-21 15:22:37 +04:00
struct spi_master * master = platform_get_drvdata ( pdev ) ;
struct orion_spi * spi = spi_master_get_devdata ( master ) ;
2008-08-06 00:01:09 +04:00
2014-06-21 15:22:37 +04:00
pm_runtime_get_sync ( & pdev - > dev ) ;
2018-01-12 13:42:33 +03:00
clk_disable_unprepare ( spi - > axi_clk ) ;
2012-04-06 19:17:26 +04:00
clk_disable_unprepare ( spi - > clk ) ;
2014-06-21 15:22:37 +04:00
spi_unregister_master ( master ) ;
pm_runtime_disable ( & pdev - > dev ) ;
2008-08-06 00:01:09 +04:00
return 0 ;
}
MODULE_ALIAS ( " platform: " DRIVER_NAME ) ;
2014-12-13 02:41:15 +03:00
# ifdef CONFIG_PM
2014-06-21 15:22:37 +04:00
static int orion_spi_runtime_suspend ( struct device * dev )
{
struct spi_master * master = dev_get_drvdata ( dev ) ;
struct orion_spi * spi = spi_master_get_devdata ( master ) ;
2018-01-12 13:42:33 +03:00
clk_disable_unprepare ( spi - > axi_clk ) ;
2014-06-21 15:22:37 +04:00
clk_disable_unprepare ( spi - > clk ) ;
return 0 ;
}
static int orion_spi_runtime_resume ( struct device * dev )
{
struct spi_master * master = dev_get_drvdata ( dev ) ;
struct orion_spi * spi = spi_master_get_devdata ( master ) ;
2018-01-12 13:42:33 +03:00
if ( ! IS_ERR ( spi - > axi_clk ) )
clk_prepare_enable ( spi - > axi_clk ) ;
2014-06-21 15:22:37 +04:00
return clk_prepare_enable ( spi - > clk ) ;
}
# endif
static const struct dev_pm_ops orion_spi_pm_ops = {
SET_RUNTIME_PM_OPS ( orion_spi_runtime_suspend ,
orion_spi_runtime_resume ,
NULL )
} ;
2008-08-06 00:01:09 +04:00
static struct platform_driver orion_spi_driver = {
. driver = {
. name = DRIVER_NAME ,
2014-06-21 15:22:37 +04:00
. pm = & orion_spi_pm_ops ,
2012-07-23 14:08:09 +04:00
. of_match_table = of_match_ptr ( orion_spi_of_match_table ) ,
2008-08-06 00:01:09 +04:00
} ,
2013-02-04 16:26:26 +04:00
. probe = orion_spi_probe ,
2013-02-05 17:27:35 +04:00
. remove = orion_spi_remove ,
2008-08-06 00:01:09 +04:00
} ;
2013-02-04 16:26:26 +04:00
module_platform_driver ( orion_spi_driver ) ;
2008-08-06 00:01:09 +04:00
MODULE_DESCRIPTION ( " Orion SPI driver " ) ;
MODULE_AUTHOR ( " Shadi Ammouri <shadi@marvell.com> " ) ;
MODULE_LICENSE ( " GPL " ) ;