2022-08-08 09:46:02 +03:00
// SPDX-License-Identifier: (GPL-2.0)
/*
* Microchip coreQSPI QSPI controller driver
*
* Copyright ( C ) 2018 - 2022 Microchip Technology Inc . and its subsidiaries
*
* Author : Naga Sureshkumar Relli < nagasuresh . relli @ microchip . com >
*
*/
# include <linux/clk.h>
# include <linux/err.h>
# include <linux/init.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/iopoll.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/of_irq.h>
# include <linux/platform_device.h>
# include <linux/spi/spi.h>
# include <linux/spi/spi-mem.h>
/*
* QSPI Control register mask defines
*/
# define CONTROL_ENABLE BIT(0)
# define CONTROL_MASTER BIT(1)
# define CONTROL_XIP BIT(2)
# define CONTROL_XIPADDR BIT(3)
# define CONTROL_CLKIDLE BIT(10)
# define CONTROL_SAMPLE_MASK GENMASK(12, 11)
# define CONTROL_MODE0 BIT(13)
# define CONTROL_MODE12_MASK GENMASK(15, 14)
# define CONTROL_MODE12_EX_RO BIT(14)
# define CONTROL_MODE12_EX_RW BIT(15)
# define CONTROL_MODE12_FULL GENMASK(15, 14)
# define CONTROL_FLAGSX4 BIT(16)
# define CONTROL_CLKRATE_MASK GENMASK(27, 24)
# define CONTROL_CLKRATE_SHIFT 24
/*
* QSPI Frames register mask defines
*/
# define FRAMES_TOTALBYTES_MASK GENMASK(15, 0)
# define FRAMES_CMDBYTES_MASK GENMASK(24, 16)
# define FRAMES_CMDBYTES_SHIFT 16
# define FRAMES_SHIFT 25
# define FRAMES_IDLE_MASK GENMASK(29, 26)
# define FRAMES_IDLE_SHIFT 26
# define FRAMES_FLAGBYTE BIT(30)
# define FRAMES_FLAGWORD BIT(31)
/*
* QSPI Interrupt Enable register mask defines
*/
# define IEN_TXDONE BIT(0)
# define IEN_RXDONE BIT(1)
# define IEN_RXAVAILABLE BIT(2)
# define IEN_TXAVAILABLE BIT(3)
# define IEN_RXFIFOEMPTY BIT(4)
# define IEN_TXFIFOFULL BIT(5)
/*
* QSPI Status register mask defines
*/
# define STATUS_TXDONE BIT(0)
# define STATUS_RXDONE BIT(1)
# define STATUS_RXAVAILABLE BIT(2)
# define STATUS_TXAVAILABLE BIT(3)
# define STATUS_RXFIFOEMPTY BIT(4)
# define STATUS_TXFIFOFULL BIT(5)
# define STATUS_READY BIT(7)
# define STATUS_FLAGSX4 BIT(8)
# define STATUS_MASK GENMASK(8, 0)
# define BYTESUPPER_MASK GENMASK(31, 16)
# define BYTESLOWER_MASK GENMASK(15, 0)
# define MAX_DIVIDER 16
# define MIN_DIVIDER 0
# define MAX_DATA_CMD_LEN 256
/* QSPI ready time out value */
# define TIMEOUT_MS 500
/*
* QSPI Register offsets .
*/
# define REG_CONTROL (0x00)
# define REG_FRAMES (0x04)
# define REG_IEN (0x0c)
# define REG_STATUS (0x10)
# define REG_DIRECT_ACCESS (0x14)
# define REG_UPPER_ACCESS (0x18)
# define REG_RX_DATA (0x40)
# define REG_TX_DATA (0x44)
# define REG_X4_RX_DATA (0x48)
# define REG_X4_TX_DATA (0x4c)
# define REG_FRAMESUP (0x50)
/**
* struct mchp_coreqspi - Defines qspi driver instance
* @ regs : Virtual address of the QSPI controller registers
* @ clk : QSPI Operating clock
* @ data_completion : completion structure
* @ op_lock : lock access to the device
* @ txbuf : TX buffer
* @ rxbuf : RX buffer
* @ irq : IRQ number
* @ tx_len : Number of bytes left to transfer
* @ rx_len : Number of bytes left to receive
*/
struct mchp_coreqspi {
void __iomem * regs ;
struct clk * clk ;
struct completion data_completion ;
struct mutex op_lock ; /* lock access to the device */
u8 * txbuf ;
u8 * rxbuf ;
int irq ;
int tx_len ;
int rx_len ;
} ;
static int mchp_coreqspi_set_mode ( struct mchp_coreqspi * qspi , const struct spi_mem_op * op )
{
u32 control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
/*
* The operating mode can be configured based on the command that needs to be send .
* bits [ 15 : 14 ] : Sets whether multiple bit SPI operates in normal , extended or full modes .
* 00 : Normal ( single DQ0 TX and single DQ1 RX lines )
* 01 : Extended RO ( command and address bytes on DQ0 only )
* 10 : Extended RW ( command byte on DQ0 only )
* 11 : Full . ( command and address are on all DQ lines )
* bit [ 13 ] : Sets whether multiple bit SPI uses 2 or 4 bits of data
* 0 : 2 - bits ( BSPI )
* 1 : 4 - bits ( QSPI )
*/
if ( op - > data . buswidth = = 4 | | op - > data . buswidth = = 2 ) {
control & = ~ CONTROL_MODE12_MASK ;
if ( op - > cmd . buswidth = = 1 & & ( op - > addr . buswidth = = 1 | | op - > addr . buswidth = = 0 ) )
control | = CONTROL_MODE12_EX_RO ;
else if ( op - > cmd . buswidth = = 1 )
control | = CONTROL_MODE12_EX_RW ;
else
control | = CONTROL_MODE12_FULL ;
control | = CONTROL_MODE0 ;
} else {
control & = ~ ( CONTROL_MODE12_MASK |
CONTROL_MODE0 ) ;
}
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
return 0 ;
}
static inline void mchp_coreqspi_read_op ( struct mchp_coreqspi * qspi )
{
u32 control , data ;
if ( ! qspi - > rx_len )
return ;
control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
/*
* Read 4 - bytes from the SPI FIFO in single transaction and then read
* the reamaining data byte wise .
*/
control | = CONTROL_FLAGSX4 ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
while ( qspi - > rx_len > = 4 ) {
while ( readl_relaxed ( qspi - > regs + REG_STATUS ) & STATUS_RXFIFOEMPTY )
;
data = readl_relaxed ( qspi - > regs + REG_X4_RX_DATA ) ;
* ( u32 * ) qspi - > rxbuf = data ;
qspi - > rxbuf + = 4 ;
qspi - > rx_len - = 4 ;
}
control & = ~ CONTROL_FLAGSX4 ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
while ( qspi - > rx_len - - ) {
while ( readl_relaxed ( qspi - > regs + REG_STATUS ) & STATUS_RXFIFOEMPTY )
;
data = readl_relaxed ( qspi - > regs + REG_RX_DATA ) ;
* qspi - > rxbuf + + = ( data & 0xFF ) ;
}
}
static inline void mchp_coreqspi_write_op ( struct mchp_coreqspi * qspi , bool word )
{
u32 control , data ;
control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
control | = CONTROL_FLAGSX4 ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
while ( qspi - > tx_len > = 4 ) {
while ( readl_relaxed ( qspi - > regs + REG_STATUS ) & STATUS_TXFIFOFULL )
;
data = * ( u32 * ) qspi - > txbuf ;
qspi - > txbuf + = 4 ;
qspi - > tx_len - = 4 ;
writel_relaxed ( data , qspi - > regs + REG_X4_TX_DATA ) ;
}
control & = ~ CONTROL_FLAGSX4 ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
while ( qspi - > tx_len - - ) {
while ( readl_relaxed ( qspi - > regs + REG_STATUS ) & STATUS_TXFIFOFULL )
;
data = * qspi - > txbuf + + ;
writel_relaxed ( data , qspi - > regs + REG_TX_DATA ) ;
}
}
static void mchp_coreqspi_enable_ints ( struct mchp_coreqspi * qspi )
{
u32 mask = IEN_TXDONE |
IEN_RXDONE |
IEN_RXAVAILABLE ;
writel_relaxed ( mask , qspi - > regs + REG_IEN ) ;
}
static void mchp_coreqspi_disable_ints ( struct mchp_coreqspi * qspi )
{
writel_relaxed ( 0 , qspi - > regs + REG_IEN ) ;
}
static irqreturn_t mchp_coreqspi_isr ( int irq , void * dev_id )
{
struct mchp_coreqspi * qspi = ( struct mchp_coreqspi * ) dev_id ;
irqreturn_t ret = IRQ_NONE ;
int intfield = readl_relaxed ( qspi - > regs + REG_STATUS ) & STATUS_MASK ;
if ( intfield = = 0 )
return ret ;
if ( intfield & IEN_TXDONE ) {
writel_relaxed ( IEN_TXDONE , qspi - > regs + REG_STATUS ) ;
ret = IRQ_HANDLED ;
}
if ( intfield & IEN_RXAVAILABLE ) {
writel_relaxed ( IEN_RXAVAILABLE , qspi - > regs + REG_STATUS ) ;
mchp_coreqspi_read_op ( qspi ) ;
ret = IRQ_HANDLED ;
}
if ( intfield & IEN_RXDONE ) {
writel_relaxed ( IEN_RXDONE , qspi - > regs + REG_STATUS ) ;
complete ( & qspi - > data_completion ) ;
ret = IRQ_HANDLED ;
}
return ret ;
}
static int mchp_coreqspi_setup_clock ( struct mchp_coreqspi * qspi , struct spi_device * spi )
{
unsigned long clk_hz ;
u32 control , baud_rate_val = 0 ;
clk_hz = clk_get_rate ( qspi - > clk ) ;
if ( ! clk_hz )
return - EINVAL ;
baud_rate_val = DIV_ROUND_UP ( clk_hz , 2 * spi - > max_speed_hz ) ;
if ( baud_rate_val > MAX_DIVIDER | | baud_rate_val < MIN_DIVIDER ) {
dev_err ( & spi - > dev ,
" could not configure the clock for spi clock %d Hz & system clock %ld Hz \n " ,
spi - > max_speed_hz , clk_hz ) ;
return - EINVAL ;
}
control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
control | = baud_rate_val < < CONTROL_CLKRATE_SHIFT ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
if ( ( spi - > mode & SPI_CPOL ) & & ( spi - > mode & SPI_CPHA ) )
control | = CONTROL_CLKIDLE ;
else
control & = ~ CONTROL_CLKIDLE ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
return 0 ;
}
static int mchp_coreqspi_setup_op ( struct spi_device * spi_dev )
{
struct spi_controller * ctlr = spi_dev - > master ;
struct mchp_coreqspi * qspi = spi_controller_get_devdata ( ctlr ) ;
u32 control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
control | = ( CONTROL_MASTER | CONTROL_ENABLE ) ;
control & = ~ CONTROL_CLKIDLE ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
return 0 ;
}
static inline void mchp_coreqspi_config_op ( struct mchp_coreqspi * qspi , const struct spi_mem_op * op )
{
u32 idle_cycles = 0 ;
int total_bytes , cmd_bytes , frames , ctrl ;
cmd_bytes = op - > cmd . nbytes + op - > addr . nbytes ;
total_bytes = cmd_bytes + op - > data . nbytes ;
/*
* As per the coreQSPI IP spec , the number of command and data bytes are
* controlled by the frames register for each SPI sequence . This supports
* the SPI flash memory read and writes sequences as below . so configure
* the cmd and total bytes accordingly .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* TOTAL BYTES | CMD BYTES | What happens |
* ______________________________________________________________________
* | | |
* 1 | 1 | The SPI core will transmit a single byte |
* | | and receive data is discarded |
* | | |
* 1 | 0 | The SPI core will transmit a single byte |
* | | and return a single byte |
* | | |
* 10 | 4 | The SPI core will transmit 4 command |
* | | bytes discarding the receive data and |
* | | transmits 6 dummy bytes returning the 6 |
* | | received bytes and return a single byte |
* | | |
* 10 | 10 | The SPI core will transmit 10 command |
* | | |
* 10 | 0 | The SPI core will transmit 10 command |
* | | bytes and returning 10 received bytes |
* ______________________________________________________________________
*/
if ( ! ( op - > data . dir = = SPI_MEM_DATA_IN ) )
cmd_bytes = total_bytes ;
frames = total_bytes & BYTESUPPER_MASK ;
writel_relaxed ( frames , qspi - > regs + REG_FRAMESUP ) ;
frames = total_bytes & BYTESLOWER_MASK ;
frames | = cmd_bytes < < FRAMES_CMDBYTES_SHIFT ;
if ( op - > dummy . buswidth )
idle_cycles = op - > dummy . nbytes * 8 / op - > dummy . buswidth ;
frames | = idle_cycles < < FRAMES_IDLE_SHIFT ;
ctrl = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
if ( ctrl & CONTROL_MODE12_MASK )
frames | = ( 1 < < FRAMES_SHIFT ) ;
frames | = FRAMES_FLAGWORD ;
writel_relaxed ( frames , qspi - > regs + REG_FRAMES ) ;
}
static int mchp_qspi_wait_for_ready ( struct spi_mem * mem )
{
struct mchp_coreqspi * qspi = spi_controller_get_devdata
( mem - > spi - > master ) ;
u32 status ;
int ret ;
ret = readl_poll_timeout ( qspi - > regs + REG_STATUS , status ,
( status & STATUS_READY ) , 0 ,
TIMEOUT_MS ) ;
if ( ret ) {
dev_err ( & mem - > spi - > dev ,
" Timeout waiting on QSPI ready. \n " ) ;
return - ETIMEDOUT ;
}
return ret ;
}
static int mchp_coreqspi_exec_op ( struct spi_mem * mem , const struct spi_mem_op * op )
{
struct mchp_coreqspi * qspi = spi_controller_get_devdata
( mem - > spi - > master ) ;
u32 address = op - > addr . val ;
u8 opcode = op - > cmd . opcode ;
u8 opaddr [ 5 ] ;
int err , i ;
mutex_lock ( & qspi - > op_lock ) ;
err = mchp_qspi_wait_for_ready ( mem ) ;
if ( err )
goto error ;
err = mchp_coreqspi_setup_clock ( qspi , mem - > spi ) ;
if ( err )
goto error ;
err = mchp_coreqspi_set_mode ( qspi , op ) ;
if ( err )
goto error ;
reinit_completion ( & qspi - > data_completion ) ;
mchp_coreqspi_config_op ( qspi , op ) ;
if ( op - > cmd . opcode ) {
qspi - > txbuf = & opcode ;
qspi - > rxbuf = NULL ;
qspi - > tx_len = op - > cmd . nbytes ;
qspi - > rx_len = 0 ;
mchp_coreqspi_write_op ( qspi , false ) ;
}
qspi - > txbuf = & opaddr [ 0 ] ;
if ( op - > addr . nbytes ) {
for ( i = 0 ; i < op - > addr . nbytes ; i + + )
qspi - > txbuf [ i ] = address > > ( 8 * ( op - > addr . nbytes - i - 1 ) ) ;
qspi - > rxbuf = NULL ;
qspi - > tx_len = op - > addr . nbytes ;
qspi - > rx_len = 0 ;
mchp_coreqspi_write_op ( qspi , false ) ;
}
if ( op - > data . nbytes ) {
if ( op - > data . dir = = SPI_MEM_DATA_OUT ) {
qspi - > txbuf = ( u8 * ) op - > data . buf . out ;
qspi - > rxbuf = NULL ;
qspi - > rx_len = 0 ;
qspi - > tx_len = op - > data . nbytes ;
mchp_coreqspi_write_op ( qspi , true ) ;
} else {
qspi - > txbuf = NULL ;
qspi - > rxbuf = ( u8 * ) op - > data . buf . in ;
qspi - > rx_len = op - > data . nbytes ;
qspi - > tx_len = 0 ;
}
}
mchp_coreqspi_enable_ints ( qspi ) ;
if ( ! wait_for_completion_timeout ( & qspi - > data_completion , msecs_to_jiffies ( 1000 ) ) )
err = - ETIMEDOUT ;
error :
mutex_unlock ( & qspi - > op_lock ) ;
mchp_coreqspi_disable_ints ( qspi ) ;
return err ;
}
static bool mchp_coreqspi_supports_op ( struct spi_mem * mem , const struct spi_mem_op * op )
{
if ( ! spi_mem_default_supports_op ( mem , op ) )
return false ;
if ( ( op - > data . buswidth = = 4 | | op - > data . buswidth = = 2 ) & &
( op - > cmd . buswidth = = 1 & & ( op - > addr . buswidth = = 1 | | op - > addr . buswidth = = 0 ) ) ) {
/*
* If the command and address are on DQ0 only , then this
* controller doesn ' t support sending data on dual and
* quad lines . but it supports reading data on dual and
* quad lines with same configuration as command and
* address on DQ0 .
* i . e . The control register [ 15 : 13 ] : EX_RO ( read only ) is
* meant only for the command and address are on DQ0 but
* not to write data , it is just to read .
* Ex : 0x34 h is Quad Load Program Data which is not
* supported . Then the spi - mem layer will iterate over
* each command and it will chose the supported one .
*/
if ( op - > data . dir = = SPI_MEM_DATA_OUT )
return false ;
}
return true ;
}
static int mchp_coreqspi_adjust_op_size ( struct spi_mem * mem , struct spi_mem_op * op )
{
if ( op - > data . dir = = SPI_MEM_DATA_OUT | | op - > data . dir = = SPI_MEM_DATA_IN ) {
if ( op - > data . nbytes > MAX_DATA_CMD_LEN )
op - > data . nbytes = MAX_DATA_CMD_LEN ;
}
return 0 ;
}
static const struct spi_controller_mem_ops mchp_coreqspi_mem_ops = {
. adjust_op_size = mchp_coreqspi_adjust_op_size ,
. supports_op = mchp_coreqspi_supports_op ,
. exec_op = mchp_coreqspi_exec_op ,
} ;
static int mchp_coreqspi_probe ( struct platform_device * pdev )
{
struct spi_controller * ctlr ;
struct mchp_coreqspi * qspi ;
struct device * dev = & pdev - > dev ;
struct device_node * np = dev - > of_node ;
int ret ;
ctlr = devm_spi_alloc_master ( & pdev - > dev , sizeof ( * qspi ) ) ;
if ( ! ctlr )
return dev_err_probe ( & pdev - > dev , - ENOMEM ,
" unable to allocate master for QSPI controller \n " ) ;
qspi = spi_controller_get_devdata ( ctlr ) ;
platform_set_drvdata ( pdev , qspi ) ;
qspi - > regs = devm_platform_ioremap_resource ( pdev , 0 ) ;
if ( IS_ERR ( qspi - > regs ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( qspi - > regs ) ,
" failed to map registers \n " ) ;
qspi - > clk = devm_clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( qspi - > clk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( qspi - > clk ) ,
" could not get clock \n " ) ;
ret = clk_prepare_enable ( qspi - > clk ) ;
if ( ret )
return dev_err_probe ( & pdev - > dev , ret ,
" failed to enable clock \n " ) ;
init_completion ( & qspi - > data_completion ) ;
mutex_init ( & qspi - > op_lock ) ;
qspi - > irq = platform_get_irq ( pdev , 0 ) ;
if ( qspi - > irq < 0 ) {
ret = qspi - > irq ;
goto out ;
}
ret = devm_request_irq ( & pdev - > dev , qspi - > irq , mchp_coreqspi_isr ,
IRQF_SHARED , pdev - > name , qspi ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " request_irq failed %d \n " , ret ) ;
goto out ;
}
ctlr - > bits_per_word_mask = SPI_BPW_MASK ( 8 ) ;
ctlr - > mem_ops = & mchp_coreqspi_mem_ops ;
ctlr - > setup = mchp_coreqspi_setup_op ;
ctlr - > mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD |
SPI_TX_DUAL | SPI_TX_QUAD ;
ctlr - > dev . of_node = np ;
ret = devm_spi_register_controller ( & pdev - > dev , ctlr ) ;
if ( ret ) {
dev_err_probe ( & pdev - > dev , ret ,
" spi_register_controller failed \n " ) ;
goto out ;
}
return 0 ;
out :
clk_disable_unprepare ( qspi - > clk ) ;
return ret ;
}
2023-03-03 20:19:50 +03:00
static void mchp_coreqspi_remove ( struct platform_device * pdev )
2022-08-08 09:46:02 +03:00
{
struct mchp_coreqspi * qspi = platform_get_drvdata ( pdev ) ;
u32 control = readl_relaxed ( qspi - > regs + REG_CONTROL ) ;
mchp_coreqspi_disable_ints ( qspi ) ;
control & = ~ CONTROL_ENABLE ;
writel_relaxed ( control , qspi - > regs + REG_CONTROL ) ;
clk_disable_unprepare ( qspi - > clk ) ;
}
static const struct of_device_id mchp_coreqspi_of_match [ ] = {
{ . compatible = " microchip,coreqspi-rtl-v2 " } ,
{ /* sentinel */ }
} ;
MODULE_DEVICE_TABLE ( of , mchp_coreqspi_of_match ) ;
static struct platform_driver mchp_coreqspi_driver = {
. probe = mchp_coreqspi_probe ,
. driver = {
. name = " microchip,coreqspi " ,
. of_match_table = mchp_coreqspi_of_match ,
} ,
2023-03-03 20:19:50 +03:00
. remove_new = mchp_coreqspi_remove ,
2022-08-08 09:46:02 +03:00
} ;
module_platform_driver ( mchp_coreqspi_driver ) ;
MODULE_AUTHOR ( " Naga Sureshkumar Relli <nagasuresh.relli@microchip.com " ) ;
MODULE_DESCRIPTION ( " Microchip coreQSPI QSPI controller driver " ) ;
MODULE_LICENSE ( " GPL " ) ;