// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for Broadcom BRCMSTB, NSP, NS2, Cygnus SPI Controllers
*
* Copyright 2016 Broadcom
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/mtd/spi-nor.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include "spi-bcm-qspi.h"
#define DRIVER_NAME "bcm_qspi"
/* BSPI register offsets */
#define BSPI_REVISION_ID 0x000
#define BSPI_SCRATCH 0x004
#define BSPI_MAST_N_BOOT_CTRL 0x008
#define BSPI_BUSY_STATUS 0x00c
#define BSPI_INTR_STATUS 0x010
#define BSPI_B0_STATUS 0x014
#define BSPI_B0_CTRL 0x018
#define BSPI_B1_STATUS 0x01c
#define BSPI_B1_CTRL 0x020
#define BSPI_STRAP_OVERRIDE_CTRL 0x024
#define BSPI_FLEX_MODE_ENABLE 0x028
#define BSPI_BITS_PER_CYCLE 0x02c
#define BSPI_BITS_PER_PHASE 0x030
#define BSPI_CMD_AND_MODE_BYTE 0x034
#define BSPI_BSPI_FLASH_UPPER_ADDR_BYTE 0x038
#define BSPI_BSPI_XOR_VALUE 0x03c
#define BSPI_BSPI_XOR_ENABLE 0x040
#define BSPI_BSPI_PIO_MODE_ENABLE 0x044
#define BSPI_BSPI_PIO_IODIR 0x048
#define BSPI_BSPI_PIO_DATA 0x04c
/* RAF register offsets */
#define BSPI_RAF_START_ADDR 0x100
#define BSPI_RAF_NUM_WORDS 0x104
#define BSPI_RAF_CTRL 0x108
#define BSPI_RAF_FULLNESS 0x10c
#define BSPI_RAF_WATERMARK 0x110
#define BSPI_RAF_STATUS 0x114
#define BSPI_RAF_READ_DATA 0x118
#define BSPI_RAF_WORD_CNT 0x11c
#define BSPI_RAF_CURR_ADDR 0x120
/* Override mode masks */
#define BSPI_STRAP_OVERRIDE_CTRL_OVERRIDE BIT(0)
#define BSPI_STRAP_OVERRIDE_CTRL_DATA_DUAL BIT(1)
#define BSPI_STRAP_OVERRIDE_CTRL_ADDR_4BYTE BIT(2)
#define BSPI_STRAP_OVERRIDE_CTRL_DATA_QUAD BIT(3)
#define BSPI_STRAP_OVERRIDE_CTRL_ENDAIN_MODE BIT(4)
#define BSPI_ADDRLEN_3BYTES 3
#define BSPI_ADDRLEN_4BYTES 4
#define BSPI_RAF_STATUS_FIFO_EMPTY_MASK BIT(1)
#define BSPI_RAF_CTRL_START_MASK BIT(0)
#define BSPI_RAF_CTRL_CLEAR_MASK BIT(1)
#define BSPI_BPP_MODE_SELECT_MASK BIT(8)
#define BSPI_BPP_ADDR_SELECT_MASK BIT(16)
#define BSPI_READ_LENGTH 256
/* MSPI register offsets */
#define MSPI_SPCR0_LSB 0x000
#define MSPI_SPCR0_MSB 0x004
#define MSPI_SPCR1_LSB 0x008
#define MSPI_SPCR1_MSB 0x00c
#define MSPI_NEWQP 0x010
#define MSPI_ENDQP 0x014
#define MSPI_SPCR2 0x018
#define MSPI_MSPI_STATUS 0x020
#define MSPI_CPTQP 0x024
#define MSPI_SPCR3 0x028
#define MSPI_REV 0x02c
#define MSPI_TXRAM 0x040
#define MSPI_RXRAM 0x0c0
#define MSPI_CDRAM 0x140
#define MSPI_WRITE_LOCK 0x180
#define MSPI_MASTER_BIT BIT(7)
#define MSPI_NUM_CDRAM 16
#define MSPI_CDRAM_CONT_BIT BIT(7)
#define MSPI_CDRAM_BITSE_BIT BIT(6)
#define MSPI_CDRAM_PCS 0xf
#define MSPI_SPCR2_SPE BIT(6)
#define MSPI_SPCR2_CONT_AFTER_CMD BIT(7)
#define MSPI_SPCR3_FASTBR BIT(0)
#define MSPI_SPCR3_FASTDT BIT(1)
#define MSPI_SPCR3_SYSCLKSEL_MASK GENMASK(11, 10)
#define MSPI_SPCR3_SYSCLKSEL_27 (MSPI_SPCR3_SYSCLKSEL_MASK & \
~(BIT(10) | BIT(11)))
#define MSPI_SPCR3_SYSCLKSEL_108 (MSPI_SPCR3_SYSCLKSEL_MASK & \
BIT(11))
#define MSPI_MSPI_STATUS_SPIF BIT(0)
#define INTR_BASE_BIT_SHIFT 0x02
#define INTR_COUNT 0x07
#define NUM_CHIPSELECT 4
#define QSPI_SPBR_MAX 255U
#define MSPI_BASE_FREQ 27000000UL
#define OPCODE_DIOR 0xBB
#define OPCODE_QIOR 0xEB
#define OPCODE_DIOR_4B 0xBC
#define OPCODE_QIOR_4B 0xEC
#define MAX_CMD_SIZE 6
#define ADDR_4MB_MASK GENMASK(22, 0)
/* stop at end of transfer, no other reason */
#define TRANS_STATUS_BREAK_NONE 0
/* stop at end of spi_message */
#define TRANS_STATUS_BREAK_EOM 1
/* stop at end of spi_transfer if delay */
#define TRANS_STATUS_BREAK_DELAY 2
/* stop at end of spi_transfer if cs_change */
#define TRANS_STATUS_BREAK_CS_CHANGE 4
/* stop if we run out of bytes */
#define TRANS_STATUS_BREAK_NO_BYTES 8
/* events that make us stop filling TX slots */
#define TRANS_STATUS_BREAK_TX (TRANS_STATUS_BREAK_EOM | \
TRANS_STATUS_BREAK_DELAY | \
TRANS_STATUS_BREAK_CS_CHANGE)
/* events that make us deassert CS */
#define TRANS_STATUS_BREAK_DESELECT (TRANS_STATUS_BREAK_EOM | \
TRANS_STATUS_BREAK_CS_CHANGE)
struct bcm_qspi_parms {
u32 speed_hz;
u8 mode;
u8 bits_per_word;
};
struct bcm_xfer_mode {
bool flex_mode;
unsigned int width;
unsigned int addrlen;
unsigned int hp;
};
enum base_type {
MSPI,
BSPI,
CHIP_SELECT,
BASEMAX,
};
enum irq_source {
SINGLE_L2,
MUXED_L1,
};
struct bcm_qspi_irq {
const char *irq_name;
const irq_handler_t irq_handler;
int irq_source;
u32 mask;
};
struct bcm_qspi_dev_id {
const struct bcm_qspi_irq *irqp;
void *dev;
};
struct qspi_trans {
struct spi_transfer *trans;
int byte;
bool mspi_last_trans;
};
struct bcm_qspi {
struct platform_device *pdev;
struct spi_master *master;
struct clk *clk;
u32 base_clk;
u32 max_speed_hz;
void __iomem *base[BASEMAX];
/* Some SoCs provide custom interrupt status register(s) */
struct bcm_qspi_soc_intc *soc_intc;
struct bcm_qspi_parms last_parms;
struct qspi_trans trans_pos;
int curr_cs;
int bspi_maj_rev;
int bspi_min_rev;
int bspi_enabled;
const struct spi_mem_op *bspi_rf_op;
u32 bspi_rf_op_idx;
u32 bspi_rf_op_len;
u32 bspi_rf_op_status;
struct bcm_xfer_mode xfer_mode;
u32 s3_strap_override_ctrl;
bool bspi_mode;
bool big_endian;
int num_irqs;
struct bcm_qspi_dev_id *dev_ids;
struct completion mspi_done;
struct completion bspi_done;
u8 mspi_maj_rev;
u8 mspi_min_rev;
bool mspi_spcr3_sysclk;
};
static inline bool has_bspi(struct bcm_qspi *qspi)
{
return qspi->bspi_mode;
}
/* hardware supports spcr3 and fast baud-rate */
static inline bool bcm_qspi_has_fastbr(struct bcm_qspi *qspi)
{
if (!has_bspi(qspi) &&
((qspi->mspi_maj_rev >= 1) &&
(qspi->mspi_min_rev >= 5)))
return true;
return false;
}
/* hardware supports sys clk 108Mhz */
static inline bool bcm_qspi_has_sysclk_108(struct bcm_qspi *qspi)
{
if (!has_bspi(qspi) && (qspi->mspi_spcr3_sysclk ||
((qspi->mspi_maj_rev >= 1) &&
(qspi->mspi_min_rev >= 6))))
return true;
return false;
}
static inline int bcm_qspi_spbr_min(struct bcm_qspi *qspi)
{
if (bcm_qspi_has_fastbr(qspi))
return 1;
else
return 8;
}
/* Read qspi controller register*/
static inline u32 bcm_qspi_read(struct bcm_qspi *qspi, enum base_type type,
u
|