linux/drivers/spi/spi-cadence-xspi.c

// SPDX-License-Identifier: GPL-2.0+
// Cadence XSPI flash controller driver
// Copyright (C) 2020-21 Cadence

#include <linux/acpi.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
#include <linux/bitfield.h>
#include <linux/limits.h>
#include <linux/log2.h>
#include <linux/bitrev.h>

#define CDNS_XSPI_MAGIC_NUM_VALUE
#define CDNS_XSPI_MAX_BANKS
#define CDNS_XSPI_NAME

/*
 * Note: below are additional auxiliary registers to
 * configure XSPI controller pin-strap settings
 */

/* PHY DQ timing register */
#define CDNS_XSPI_CCP_PHY_DQ_TIMING

/* PHY DQS timing register */
#define CDNS_XSPI_CCP_PHY_DQS_TIMING

/* PHY gate loopback control register */
#define CDNS_XSPI_CCP_PHY_GATE_LPBCK_CTRL

/* PHY DLL slave control register */
#define CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL

/* DLL PHY control register */
#define CDNS_XSPI_DLL_PHY_CTRL

/* Command registers */
#define CDNS_XSPI_CMD_REG_0
#define CDNS_XSPI_CMD_REG_1
#define CDNS_XSPI_CMD_REG_2
#define CDNS_XSPI_CMD_REG_3
#define CDNS_XSPI_CMD_REG_4
#define CDNS_XSPI_CMD_REG_5

/* Command status registers */
#define CDNS_XSPI_CMD_STATUS_REG

/* Controller status register */
#define CDNS_XSPI_CTRL_STATUS_REG
#define CDNS_XSPI_INIT_COMPLETED
#define CDNS_XSPI_INIT_LEGACY
#define CDNS_XSPI_INIT_FAIL
#define CDNS_XSPI_CTRL_BUSY

/* Controller interrupt status register */
#define CDNS_XSPI_INTR_STATUS_REG
#define CDNS_XSPI_STIG_DONE
#define CDNS_XSPI_SDMA_ERROR
#define CDNS_XSPI_SDMA_TRIGGER
#define CDNS_XSPI_CMD_IGNRD_EN
#define CDNS_XSPI_DDMA_TERR_EN
#define CDNS_XSPI_CDMA_TREE_EN
#define CDNS_XSPI_CTRL_IDLE_EN

#define CDNS_XSPI_TRD_COMP_INTR_STATUS
#define CDNS_XSPI_TRD_ERR_INTR_STATUS
#define CDNS_XSPI_TRD_ERR_INTR_EN

/* Controller interrupt enable register */
#define CDNS_XSPI_INTR_ENABLE_REG
#define CDNS_XSPI_INTR_EN
#define CDNS_XSPI_STIG_DONE_EN
#define CDNS_XSPI_SDMA_ERROR_EN
#define CDNS_XSPI_SDMA_TRIGGER_EN

#define CDNS_XSPI_INTR_MASK

/* Controller config register */
#define CDNS_XSPI_CTRL_CONFIG_REG
#define CDNS_XSPI_CTRL_WORK_MODE

#define CDNS_XSPI_WORK_MODE_DIRECT
#define CDNS_XSPI_WORK_MODE_STIG
#define CDNS_XSPI_WORK_MODE_ACMD

/* SDMA trigger transaction registers */
#define CDNS_XSPI_SDMA_SIZE_REG
#define CDNS_XSPI_SDMA_TRD_INFO_REG
#define CDNS_XSPI_SDMA_DIR

/* Controller features register */
#define CDNS_XSPI_CTRL_FEATURES_REG
#define CDNS_XSPI_NUM_BANKS
#define CDNS_XSPI_DMA_DATA_WIDTH
#define CDNS_XSPI_NUM_THREADS

/* Controller version register */
#define CDNS_XSPI_CTRL_VERSION_REG
#define CDNS_XSPI_MAGIC_NUM
#define CDNS_XSPI_CTRL_REV

/* STIG Profile 1.0 instruction fields (split into registers) */
#define CDNS_XSPI_CMD_INSTR_TYPE
#define CDNS_XSPI_CMD_P1_R1_ADDR0
#define CDNS_XSPI_CMD_P1_R2_ADDR1
#define CDNS_XSPI_CMD_P1_R2_ADDR2
#define CDNS_XSPI_CMD_P1_R2_ADDR3
#define CDNS_XSPI_CMD_P1_R2_ADDR4
#define CDNS_XSPI_CMD_P1_R3_ADDR5
#define CDNS_XSPI_CMD_P1_R3_CMD
#define CDNS_XSPI_CMD_P1_R3_NUM_ADDR_BYTES
#define CDNS_XSPI_CMD_P1_R4_ADDR_IOS
#define CDNS_XSPI_CMD_P1_R4_CMD_IOS
#define CDNS_XSPI_CMD_P1_R4_BANK

/* STIG data sequence instruction fields (split into registers) */
#define CDNS_XSPI_CMD_DSEQ_R2_DCNT_L
#define CDNS_XSPI_CMD_DSEQ_R3_DCNT_H
#define CDNS_XSPI_CMD_DSEQ_R3_NUM_OF_DUMMY
#define CDNS_XSPI_CMD_DSEQ_R4_BANK
#define CDNS_XSPI_CMD_DSEQ_R4_DATA_IOS
#define CDNS_XSPI_CMD_DSEQ_R4_DIR

/* STIG command status fields */
#define CDNS_XSPI_CMD_STATUS_COMPLETED
#define CDNS_XSPI_CMD_STATUS_FAILED
#define CDNS_XSPI_CMD_STATUS_DQS_ERROR
#define CDNS_XSPI_CMD_STATUS_CRC_ERROR
#define CDNS_XSPI_CMD_STATUS_BUS_ERROR
#define CDNS_XSPI_CMD_STATUS_INV_SEQ_ERROR

#define CDNS_XSPI_STIG_DONE_FLAG
#define CDNS_XSPI_TRD_STATUS

#define MODE_NO_OF_BYTES
#define MODEBYTES_COUNT

/* Helper macros for filling command registers */
#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_1(op, data_phase)

#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_2(op)

#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_3(op, modebytes)

#define CDNS_XSPI_CMD_FLD_P1_INSTR_CMD_4(op, chipsel)

#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_1(op)

#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_2(op)

#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_3(op, dummybytes)

#define CDNS_XSPI_CMD_FLD_DSEQ_CMD_4(op, chipsel)

/* Helper macros for GENERIC and GENERIC-DSEQ instruction type */
#define CMD_REG_LEN
#define INSTRUCTION_TYPE_GENERIC
#define CDNS_XSPI_CMD_FLD_P1_GENERIC_CMD

#define GENERIC_NUM_OF_BYTES
#define CDNS_XSPI_CMD_FLD_P3_GENERIC_CMD(len)

#define GENERIC_BANK_NUM
#define GENERIC_GLUE_CMD
#define CDNS_XSPI_CMD_FLD_P4_GENERIC_CMD(cs, glue)

#define CDNS_XSPI_CMD_FLD_GENERIC_DSEQ_CMD_1

#define CDNS_XSPI_CMD_FLD_GENERIC_DSEQ_CMD_2(nbytes)

#define CDNS_XSPI_CMD_FLD_GENERIC_DSEQ_CMD_3(nbytes)

#define CDNS_XSPI_CMD_FLD_GENERIC_DSEQ_CMD_4(dir, chipsel)

/* Marvell PHY default values */
#define MARVELL_REGS_DLL_PHY_CTRL
#define MARVELL_CTB_RFILE_PHY_CTRL
#define MARVELL_RFILE_PHY_TSEL
#define MARVELL_RFILE_PHY_DQ_TIMING
#define MARVELL_RFILE_PHY_DQS_TIMING
#define MARVELL_RFILE_PHY_GATE_LPBK_CTRL
#define MARVELL_RFILE_PHY_DLL_MASTER_CTRL
#define MARVELL_RFILE_PHY_DLL_SLAVE_CTRL

/* PHY config registers */
#define CDNS_XSPI_RF_MINICTRL_REGS_DLL_PHY_CTRL
#define CDNS_XSPI_PHY_CTB_RFILE_PHY_CTRL
#define CDNS_XSPI_PHY_CTB_RFILE_PHY_TSEL
#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQ_TIMING
#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQS_TIMING
#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_GATE_LPBK_CTRL
#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DLL_MASTER_CTRL
#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DLL_SLAVE_CTRL
#define CDNS_XSPI_DATASLICE_RFILE_PHY_DLL_OBS_REG_0

#define CDNS_XSPI_DLL_RST_N
#define CDNS_XSPI_DLL_LOCK

/* Marvell overlay registers - clock */
#define MRVL_XSPI_CLK_CTRL_AUX_REG
#define MRVL_XSPI_CLK_ENABLE
#define MRVL_XSPI_CLK_DIV
#define MRVL_XSPI_IRQ_ENABLE
#define MRVL_XSPI_CLOCK_IO_HZ
#define MRVL_XSPI_CLOCK_DIVIDED(div)
#define MRVL_DEFAULT_CLK

/* Marvell overlay registers - xfer */
#define MRVL_XFER_FUNC_CTRL
#define MRVL_XFER_FUNC_CTRL_READ_DATA(i)
#define MRVL_XFER_SOFT_RESET
#define MRVL_XFER_CS_N_HOLD
#define MRVL_XFER_RECEIVE_ENABLE
#define MRVL_XFER_FUNC_ENABLE
#define MRVL_XFER_CLK_CAPTURE_POL
#define MRVL_XFER_CLK_DRIVE_POL
#define MRVL_XFER_FUNC_START
#define MRVL_XFER_QWORD_COUNT
#define MRVL_XFER_QWORD_BYTECOUNT

#define MRVL_XSPI_POLL_TIMEOUT_US
#define MRVL_XSPI_POLL_DELAY_US

/* Macros for calculating data bits in generic command
 * Up to 10 bytes can be fit into cmd_registers
 * least significant is placed in cmd_reg[1]
 * Other bits are inserted after it in cmd_reg[1,2,3] register
 */
#define GENERIC_CMD_DATA_REG_3_COUNT(len)
#define GENERIC_CMD_DATA_REG_2_COUNT(len)
#define GENERIC_CMD_DATA_REG_1_COUNT(len)
#define GENERIC_CMD_DATA_3_OFFSET(position)
#define GENERIC_CMD_DATA_2_OFFSET(position)
#define GENERIC_CMD_DATA_1_OFFSET(position)
#define GENERIC_CMD_DATA_INSERT(data, pos)
#define GENERIC_CMD_REG_3_NEEDED(len)
#define GENERIC_CMD_REG_2_NEEDED(len)

enum cdns_xspi_stig_instr_type {};

enum cdns_xspi_sdma_dir {};

enum cdns_xspi_stig_cmd_dir {};

struct cdns_xspi_driver_data {};

static struct cdns_xspi_driver_data marvell_driver_data =;

static struct cdns_xspi_driver_data cdns_driver_data =;

static const int cdns_mrvl_xspi_clk_div_list[] =;

struct cdns_xspi_dev {};

static void cdns_xspi_reset_dll(struct cdns_xspi_dev *cdns_xspi)
{}

static bool cdns_xspi_is_dll_locked(struct cdns_xspi_dev *cdns_xspi)
{}

/* Static configuration of PHY */
static bool cdns_xspi_configure_phy(struct cdns_xspi_dev *cdns_xspi)
{}

static bool cdns_mrvl_xspi_setup_clock(struct cdns_xspi_dev *cdns_xspi,
				       int requested_clk)
{}

static int cdns_xspi_wait_for_controller_idle(struct cdns_xspi_dev *cdns_xspi)
{}

static void cdns_xspi_trigger_command(struct cdns_xspi_dev *cdns_xspi,
				      u32 cmd_regs[6])
{}

static int cdns_xspi_check_command_status(struct cdns_xspi_dev *cdns_xspi)
{}

static void cdns_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
				     bool enabled)
{}

static void marvell_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
				     bool enabled)
{}

static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
{}

static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
{}

static void m_ioreadq(void __iomem  *addr, void *buf, int len)
{}

static void m_iowriteq(void __iomem *addr, const void *buf, int len)
{}

static void marvell_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
{}

static int cdns_xspi_send_stig_command(struct cdns_xspi_dev *cdns_xspi,
				       const struct spi_mem_op *op,
				       bool data_phase)
{}

static int cdns_xspi_mem_op(struct cdns_xspi_dev *cdns_xspi,
			    struct spi_mem *mem,
			    const struct spi_mem_op *op)
{}

static int cdns_xspi_mem_op_execute(struct spi_mem *mem,
				    const struct spi_mem_op *op)
{}

static int marvell_xspi_mem_op_execute(struct spi_mem *mem,
				    const struct spi_mem_op *op)
{}

#ifdef CONFIG_ACPI
static bool cdns_xspi_supports_op(struct spi_mem *mem,
				  const struct spi_mem_op *op)
{}
#endif

static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op)
{}

static const struct spi_controller_mem_ops cadence_xspi_mem_ops =;

static const struct spi_controller_mem_ops marvell_xspi_mem_ops =;

static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev)
{}

static int cdns_xspi_of_get_plat_data(struct platform_device *pdev)
{}

static void cdns_xspi_print_phy_config(struct cdns_xspi_dev *cdns_xspi)
{}

static int cdns_xspi_prepare_generic(int cs, const void *dout, int len, int glue, u32 *cmd_regs)
{}

static void marvell_xspi_read_single_qword(struct cdns_xspi_dev *cdns_xspi, u8 **buffer)
{}

static void cdns_xspi_finish_read(struct cdns_xspi_dev *cdns_xspi, u8 **buffer, u32 data_count)
{}

static int cdns_xspi_prepare_transfer(int cs, int dir, int len, u32 *cmd_regs)
{}

static bool cdns_xspi_is_stig_ready(struct cdns_xspi_dev *cdns_xspi, bool sleep)
{}

static bool cdns_xspi_is_sdma_ready(struct cdns_xspi_dev *cdns_xspi, bool sleep)
{}

static int cdns_xspi_transfer_one_message_b0(struct spi_controller *controller,
					   struct spi_message *m)
{}

static int cdns_xspi_probe(struct platform_device *pdev)
{}

static const struct of_device_id cdns_xspi_of_match[] =;
MODULE_DEVICE_TABLE(of, cdns_xspi_of_match);

static struct platform_driver cdns_xspi_platform_driver =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();