@ -32,37 +32,37 @@
# include <spi.h>
# include "cadence_qspi.h"
# define CQSPI_REG_POLL_US ( 1) /* 1us */
# define CQSPI_REG_RETRY ( 10000)
# define CQSPI_POLL_IDLE_RETRY ( 3)
# define CQSPI_REG_POLL_US 1 /* 1us */
# define CQSPI_REG_RETRY 10000
# define CQSPI_POLL_IDLE_RETRY 3
# define CQSPI_FIFO_WIDTH ( 4)
# define CQSPI_FIFO_WIDTH 4
# define CQSPI_REG_SRAM_THRESHOLD_WORDS ( 50)
# define CQSPI_REG_SRAM_THRESHOLD_WORDS 50
/* Transfer mode */
# define CQSPI_INST_TYPE_SINGLE ( 0)
# define CQSPI_INST_TYPE_DUAL ( 1)
# define CQSPI_INST_TYPE_QUAD ( 2)
# define CQSPI_INST_TYPE_SINGLE 0
# define CQSPI_INST_TYPE_DUAL 1
# define CQSPI_INST_TYPE_QUAD 2
# define CQSPI_STIG_DATA_LEN_MAX (8)
# define CQSPI_DUMMY_CLKS_PER_BYTE (8)
# define CQSPI_DUMMY_BYTES_MAX (4)
# define CQSPI_STIG_DATA_LEN_MAX 8
# define CQSPI_DUMMY_CLKS_PER_BYTE 8
# define CQSPI_DUMMY_BYTES_MAX 4
# define CQSPI_REG_SRAM_FILL_THRESHOLD \
( ( CQSPI_REG_SRAM_SIZE_WORD / 2 ) * CQSPI_FIFO_WIDTH )
/****************************************************************************
* Controller ' s configuration and status register ( offset from QSPI_BASE )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define CQSPI_REG_CONFIG 0x00
# define CQSPI_REG_CONFIG_CLK_POL_LSB 1
# define CQSPI_REG_CONFIG_CLK_PHA_LSB 2
# define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0 )
# define CQSPI_REG_CONFIG_DIRECT_MASK BIT(7)
# define CQSPI_REG_CONFIG_DECODE_MASK BIT(9)
# define CQSPI_REG_CONFIG_XIP_IMM_MASK BIT(18)
# define CQSPI_REG_CONFIG_ENABLE BIT(0)
# define CQSPI_REG_CONFIG_CLK_POL BIT(1)
# define CQSPI_REG_CONFIG_CLK_PHA BIT(2 )
# define CQSPI_REG_CONFIG_DIRECT BIT(7)
# define CQSPI_REG_CONFIG_DECODE BIT(9)
# define CQSPI_REG_CONFIG_XIP_IMM BIT(18)
# define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10
# define CQSPI_REG_CONFIG_BAUD_LSB 19
# define CQSPI_REG_CONFIG_IDLE_LSB 31
@ -94,10 +94,10 @@
# define CQSPI_REG_DELAY_TSD2D_MASK 0xFF
# define CQSPI_REG_DELAY_TSHSL_MASK 0xFF
# define CQSPI_READLCAPTURE 0x10
# define CQSPI_READLCAPTURE_BYPASS_LSB 0
# define CQSPI_READLCAPTURE_DELAY_LSB 1
# define CQSPI_READLCAPTURE_DELAY_MASK 0xF
# define CQSPI_REG_RD_DATA_CAPTURE 0x10
# define CQSPI_REG_RD_DATA_CAPTURE_BYPASS BIT(0)
# define CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB 1
# define CQSPI_REG_RD_DATA_CAPTURE_DELAY_MASK 0xF
# define CQSPI_REG_SIZE 0x14
# define CQSPI_REG_SIZE_ADDRESS_LSB 0
@ -123,18 +123,18 @@
# define CQSPI_REG_IRQMASK 0x44
# define CQSPI_REG_INDIRECTRD 0x60
# define CQSPI_REG_INDIRECTRD_START_MASK BIT(0)
# define CQSPI_REG_INDIRECTRD_CANCEL_MASK BIT(1)
# define CQSPI_REG_INDIRECTRD_INPROGRESS_MASK BIT(2)
# define CQSPI_REG_INDIRECTRD_DONE_MASK BIT(5)
# define CQSPI_REG_INDIRECTRD_START BIT(0)
# define CQSPI_REG_INDIRECTRD_CANCEL BIT(1)
# define CQSPI_REG_INDIRECTRD_INPROGRESS BIT(2)
# define CQSPI_REG_INDIRECTRD_DONE BIT(5)
# define CQSPI_REG_INDIRECTRDWATERMARK 0x64
# define CQSPI_REG_INDIRECTRDSTARTADDR 0x68
# define CQSPI_REG_INDIRECTRDBYTES 0x6C
# define CQSPI_REG_CMDCTRL 0x90
# define CQSPI_REG_CMDCTRL_EXECUTE_MASK BIT(0)
# define CQSPI_REG_CMDCTRL_INPROGRESS_MASK BIT(1)
# define CQSPI_REG_CMDCTRL_EXECUTE BIT(0)
# define CQSPI_REG_CMDCTRL_INPROGRESS BIT(1)
# define CQSPI_REG_CMDCTRL_DUMMY_LSB 7
# define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12
# define CQSPI_REG_CMDCTRL_WR_EN_LSB 15
@ -150,10 +150,10 @@
# define CQSPI_REG_CMDCTRL_OPCODE_MASK 0xFF
# define CQSPI_REG_INDIRECTWR 0x70
# define CQSPI_REG_INDIRECTWR_START_MASK BIT(0)
# define CQSPI_REG_INDIRECTWR_CANCEL_MASK BIT(1)
# define CQSPI_REG_INDIRECTWR_INPROGRESS_MASK BIT(2)
# define CQSPI_REG_INDIRECTWR_DONE_MASK BIT(5)
# define CQSPI_REG_INDIRECTWR_START BIT(0)
# define CQSPI_REG_INDIRECTWR_CANCEL BIT(1)
# define CQSPI_REG_INDIRECTWR_INPROGRESS BIT(2)
# define CQSPI_REG_INDIRECTWR_DONE BIT(5)
# define CQSPI_REG_INDIRECTWRWATERMARK 0x74
# define CQSPI_REG_INDIRECTWRSTARTADDR 0x78
@ -169,9 +169,6 @@
( ( readl ( base + CQSPI_REG_CONFIG ) > > \
CQSPI_REG_CONFIG_IDLE_LSB ) & 0x1 )
# define CQSPI_CAL_DELAY(tdelay_ns, tref_ns, tsclk_ns) \
( ( ( ( tdelay_ns ) - ( tsclk_ns ) ) / ( tref_ns ) ) )
# define CQSPI_GET_RD_SRAM_LEVEL(reg_base) \
( ( ( readl ( reg_base + CQSPI_REG_SDRAMLEVEL ) ) > > \
CQSPI_REG_SDRAMLEVEL_RD_LSB ) & CQSPI_REG_SDRAMLEVEL_RD_MASK )
@ -197,18 +194,16 @@ void cadence_qspi_apb_controller_enable(void *reg_base)
{
unsigned int reg ;
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
reg | = CQSPI_REG_CONFIG_ENABLE_MASK ;
reg | = CQSPI_REG_CONFIG_ENABLE ;
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
return ;
}
void cadence_qspi_apb_controller_disable ( void * reg_base )
{
unsigned int reg ;
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
reg & = ~ CQSPI_REG_CONFIG_ENABLE_MASK ;
reg & = ~ CQSPI_REG_CONFIG_ENABLE ;
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
return ;
}
/* Return 1 if idle, otherwise return 0 (busy). */
@ -244,23 +239,22 @@ void cadence_qspi_apb_readdata_capture(void *reg_base,
unsigned int reg ;
cadence_qspi_apb_controller_disable ( reg_base ) ;
reg = readl ( reg_base + CQSPI_READL CAPTURE ) ;
reg = readl ( reg_base + CQSPI_REG_RD_DATA_ CAPTURE ) ;
if ( bypass )
reg | = ( 1 < < CQSPI_READLCAPTURE_BYPASS_LSB ) ;
reg | = CQSPI_REG_RD_DATA_CAPTURE_BYPASS ;
else
reg & = ~ ( 1 < < CQSPI_READLCAPTURE_BYPASS_LSB ) ;
reg & = ~ CQSPI_REG_RD_DATA_CAPTURE_BYPASS ;
reg & = ~ ( CQSPI_READL CAPTURE_DELAY_MASK
< < CQSPI_READL CAPTURE_DELAY_LSB ) ;
reg & = ~ ( CQSPI_REG_RD_DATA_ CAPTURE_DELAY_MASK
< < CQSPI_REG_RD_DATA_ CAPTURE_DELAY_LSB ) ;
reg | = ( ( delay & CQSPI_READL CAPTURE_DELAY_MASK )
< < CQSPI_READLCAPTURE_DELAY_LSB ) ;
reg | = ( delay & CQSPI_REG_RD_DATA_ CAPTURE_DELAY_MASK )
< < CQSPI_REG_RD_DATA_CAPTURE_DELAY_LSB ;
writel ( reg , reg_base + CQSPI_READL CAPTURE ) ;
writel ( reg , reg_base + CQSPI_REG_RD_DATA_ CAPTURE ) ;
cadence_qspi_apb_controller_enable ( reg_base ) ;
return ;
}
void cadence_qspi_apb_config_baudrate_div ( void * reg_base ,
@ -273,54 +267,42 @@ void cadence_qspi_apb_config_baudrate_div(void *reg_base,
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
reg & = ~ ( CQSPI_REG_CONFIG_BAUD_MASK < < CQSPI_REG_CONFIG_BAUD_LSB ) ;
div = ref_clk_hz / sclk_hz ;
if ( div > 32 )
div = 32 ;
/* Check if even number. */
if ( ( div & 1 ) ) {
div = ( div / 2 ) ;
} else {
if ( ref_clk_hz % sclk_hz )
/* ensure generated SCLK doesn't exceed user
specified sclk_hz */
div = ( div / 2 ) ;
else
div = ( div / 2 ) - 1 ;
}
debug ( " %s: ref_clk %dHz sclk %dHz Div 0x%x \n " , __func__ ,
ref_clk_hz , sclk_hz , div ) ;
/*
* The baud_div field in the config reg is 4 bits , and the ref clock is
* divided by 2 * ( baud_div + 1 ) . Round up the divider to ensure the
* SPI clock rate is less than or equal to the requested clock rate .
*/
div = DIV_ROUND_UP ( ref_clk_hz , sclk_hz * 2 ) - 1 ;
/* ensure the baud rate doesn't exceed the max value */
if ( div > CQSPI_REG_CONFIG_BAUD_MASK )
div = CQSPI_REG_CONFIG_BAUD_MASK ;
debug ( " %s: ref_clk %dHz sclk %dHz Div 0x%x, actual %dHz \n " , __func__ ,
ref_clk_hz , sclk_hz , div , ref_clk_hz / ( 2 * ( div + 1 ) ) ) ;
reg | = ( div < < CQSPI_REG_CONFIG_BAUD_LSB ) ;
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
cadence_qspi_apb_controller_enable ( reg_base ) ;
return ;
}
void cadence_qspi_apb_set_clk_mode ( void * reg_base ,
unsigned int clk_pol , unsigned int clk_pha )
void cadence_qspi_apb_set_clk_mode ( void * reg_base , uint mode )
{
unsigned int reg ;
cadence_qspi_apb_controller_disable ( reg_base ) ;
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
reg & = ~ ( 1 < <
( CQSPI_REG_CONFIG_CLK_POL_LSB | CQSPI_REG_CONFIG_CLK_PHA_LSB ) ) ;
reg & = ~ ( CQSPI_REG_CONFIG_CLK_POL | CQSPI_REG_CONFIG_CLK_PHA ) ;
reg | = ( ( clk_pol & 0x1 ) < < CQSPI_REG_CONFIG_CLK_POL_LSB ) ;
reg | = ( ( clk_pha & 0x1 ) < < CQSPI_REG_CONFIG_CLK_PHA_LSB ) ;
if ( mode & SPI_CPOL )
reg | = CQSPI_REG_CONFIG_CLK_POL ;
if ( mode & SPI_CPHA )
reg | = CQSPI_REG_CONFIG_CLK_PHA ;
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
cadence_qspi_apb_controller_enable ( reg_base ) ;
return ;
}
void cadence_qspi_apb_chipselect ( void * reg_base ,
@ -336,9 +318,9 @@ void cadence_qspi_apb_chipselect(void *reg_base,
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
/* docoder */
if ( decoder_enable ) {
reg | = CQSPI_REG_CONFIG_DECODE_MASK ;
reg | = CQSPI_REG_CONFIG_DECODE ;
} else {
reg & = ~ CQSPI_REG_CONFIG_DECODE_MASK ;
reg & = ~ CQSPI_REG_CONFIG_DECODE ;
/* Convert CS if without decoder.
* CS0 to 4 b ' 1110
* CS1 to 4 b ' 1101
@ -355,7 +337,6 @@ void cadence_qspi_apb_chipselect(void *reg_base,
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
cadence_qspi_apb_controller_enable ( reg_base ) ;
return ;
}
void cadence_qspi_apb_delay ( void * reg_base ,
@ -371,16 +352,20 @@ void cadence_qspi_apb_delay(void *reg_base,
cadence_qspi_apb_controller_disable ( reg_base ) ;
/* Convert to ns. */
ref_clk_ns = ( 1000000000 ) / ref_clk ;
ref_clk_ns = DIV_ROUND_UP ( 1000000000 , ref_clk ) ;
/* Convert to ns. */
sclk_ns = ( 1000000000 ) / sclk_hz ;
/* Plus 1 to round up 1 clock cycle. */
tshsl = CQSPI_CAL_DELAY ( tshsl_ns , ref_clk_ns , sclk_ns ) + 1 ;
tchsh = CQSPI_CAL_DELAY ( tchsh_ns , ref_clk_ns , sclk_ns ) + 1 ;
tslch = CQSPI_CAL_DELAY ( tslch_ns , ref_clk_ns , sclk_ns ) + 1 ;
tsd2d = CQSPI_CAL_DELAY ( tsd2d_ns , ref_clk_ns , sclk_ns ) + 1 ;
sclk_ns = DIV_ROUND_UP ( 1000000000 , sclk_hz ) ;
/* The controller adds additional delay to that programmed in the reg */
if ( tshsl_ns > = sclk_ns + ref_clk_ns )
tshsl_ns - = sclk_ns + ref_clk_ns ;
if ( tchsh_ns > = sclk_ns + 3 * ref_clk_ns )
tchsh_ns - = sclk_ns + 3 * ref_clk_ns ;
tshsl = DIV_ROUND_UP ( tshsl_ns , ref_clk_ns ) ;
tchsh = DIV_ROUND_UP ( tchsh_ns , ref_clk_ns ) ;
tslch = DIV_ROUND_UP ( tslch_ns , ref_clk_ns ) ;
tsd2d = DIV_ROUND_UP ( tsd2d_ns , ref_clk_ns ) ;
reg = ( ( tshsl & CQSPI_REG_DELAY_TSHSL_MASK )
< < CQSPI_REG_DELAY_TSHSL_LSB ) ;
@ -393,7 +378,6 @@ void cadence_qspi_apb_delay(void *reg_base,
writel ( reg , reg_base + CQSPI_REG_DELAY ) ;
cadence_qspi_apb_controller_enable ( reg_base ) ;
return ;
}
void cadence_qspi_apb_controller_init ( struct cadence_spi_platdata * plat )
@ -421,7 +405,6 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat)
writel ( 0 , plat - > regbase + CQSPI_REG_IRQMASK ) ;
cadence_qspi_apb_controller_enable ( plat - > regbase ) ;
return ;
}
static int cadence_qspi_apb_exec_flash_cmd ( void * reg_base ,
@ -432,12 +415,12 @@ static int cadence_qspi_apb_exec_flash_cmd(void *reg_base,
/* Write the CMDCTRL without start execution. */
writel ( reg , reg_base + CQSPI_REG_CMDCTRL ) ;
/* Start execute */
reg | = CQSPI_REG_CMDCTRL_EXECUTE_MASK ;
reg | = CQSPI_REG_CMDCTRL_EXECUTE ;
writel ( reg , reg_base + CQSPI_REG_CMDCTRL ) ;
while ( retry - - ) {
reg = readl ( reg_base + CQSPI_REG_CMDCTRL ) ;
if ( ( reg & CQSPI_REG_CMDCTRL_INPROGRESS_MASK ) = = 0 )
if ( ( reg & CQSPI_REG_CMDCTRL_INPROGRESS ) = = 0 )
break ;
udelay ( 1 ) ;
}
@ -655,7 +638,7 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
writel ( n_rx , plat - > regbase + CQSPI_REG_INDIRECTRDBYTES ) ;
/* Start the indirect read transfer */
writel ( CQSPI_REG_INDIRECTRD_START_MASK ,
writel ( CQSPI_REG_INDIRECTRD_START ,
plat - > regbase + CQSPI_REG_INDIRECTRD ) ;
while ( remaining > 0 ) {
@ -684,21 +667,21 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
/* Check indirect done status */
ret = wait_for_bit ( " QSPI " , plat - > regbase + CQSPI_REG_INDIRECTRD ,
CQSPI_REG_INDIRECTRD_DONE_MASK , 1 , 10 , 0 ) ;
CQSPI_REG_INDIRECTRD_DONE , 1 , 10 , 0 ) ;
if ( ret ) {
printf ( " Indirect read completion error (%i) \n " , ret ) ;
goto failrd ;
}
/* Clear indirect completion status */
writel ( CQSPI_REG_INDIRECTRD_DONE_MASK ,
writel ( CQSPI_REG_INDIRECTRD_DONE ,
plat - > regbase + CQSPI_REG_INDIRECTRD ) ;
return 0 ;
failrd :
/* Cancel the indirect read */
writel ( CQSPI_REG_INDIRECTRD_CANCEL_MASK ,
writel ( CQSPI_REG_INDIRECTRD_CANCEL ,
plat - > regbase + CQSPI_REG_INDIRECTRD ) ;
return ret ;
}
@ -746,7 +729,7 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
writel ( n_tx , plat - > regbase + CQSPI_REG_INDIRECTWRBYTES ) ;
/* Start the indirect write transfer */
writel ( CQSPI_REG_INDIRECTWR_START_MASK ,
writel ( CQSPI_REG_INDIRECTWR_START ,
plat - > regbase + CQSPI_REG_INDIRECTWR ) ;
while ( remaining > 0 ) {
@ -771,20 +754,20 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
/* Check indirect done status */
ret = wait_for_bit ( " QSPI " , plat - > regbase + CQSPI_REG_INDIRECTWR ,
CQSPI_REG_INDIRECTWR_DONE_MASK , 1 , 10 , 0 ) ;
CQSPI_REG_INDIRECTWR_DONE , 1 , 10 , 0 ) ;
if ( ret ) {
printf ( " Indirect write completion error (%i) \n " , ret ) ;
goto failwr ;
}
/* Clear indirect completion status */
writel ( CQSPI_REG_INDIRECTWR_DONE_MASK ,
writel ( CQSPI_REG_INDIRECTWR_DONE ,
plat - > regbase + CQSPI_REG_INDIRECTWR ) ;
return 0 ;
failwr :
/* Cancel the indirect write */
writel ( CQSPI_REG_INDIRECTWR_CANCEL_MASK ,
writel ( CQSPI_REG_INDIRECTWR_CANCEL ,
plat - > regbase + CQSPI_REG_INDIRECTWR ) ;
return ret ;
}
@ -795,9 +778,9 @@ void cadence_qspi_apb_enter_xip(void *reg_base, char xip_dummy)
/* enter XiP mode immediately and enable direct mode */
reg = readl ( reg_base + CQSPI_REG_CONFIG ) ;
reg | = CQSPI_REG_CONFIG_ENABLE_MASK ;
reg | = CQSPI_REG_CONFIG_DIRECT_MASK ;
reg | = CQSPI_REG_CONFIG_XIP_IMM_MASK ;
reg | = CQSPI_REG_CONFIG_ENABLE ;
reg | = CQSPI_REG_CONFIG_DIRECT ;
reg | = CQSPI_REG_CONFIG_XIP_IMM ;
writel ( reg , reg_base + CQSPI_REG_CONFIG ) ;
/* keep the XiP mode */