linux/drivers/spi/spi-hisi-sfc-v3xx.c

// SPDX-License-Identifier: GPL-2.0-only
//
// HiSilicon SPI NOR V3XX Flash Controller Driver for hi16xx chipsets
//
// Copyright (c) 2019 HiSilicon Technologies Co., Ltd.
// Author: John Garry <[email protected]>

#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/dmi.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>

#define HISI_SFC_V3XX_VERSION

#define HISI_SFC_V3XX_GLB_CFG
#define HISI_SFC_V3XX_GLB_CFG_CS0_ADDR_MODE
#define HISI_SFC_V3XX_RAW_INT_STAT
#define HISI_SFC_V3XX_INT_STAT
#define HISI_SFC_V3XX_INT_MASK
#define HISI_SFC_V3XX_INT_CLR
#define HISI_SFC_V3XX_CMD_CFG
#define HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF
#define HISI_SFC_V3XX_CMD_CFG_RW_MSK
#define HISI_SFC_V3XX_CMD_CFG_DATA_EN_MSK
#define HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF
#define HISI_SFC_V3XX_CMD_CFG_ADDR_EN_MSK
#define HISI_SFC_V3XX_CMD_CFG_CS_SEL_OFF
#define HISI_SFC_V3XX_CMD_CFG_START_MSK
#define HISI_SFC_V3XX_CMD_INS
#define HISI_SFC_V3XX_CMD_ADDR
#define HISI_SFC_V3XX_CMD_DATABUF0

/* Common definition of interrupt bit masks */
#define HISI_SFC_V3XX_INT_MASK_ALL
#define HISI_SFC_V3XX_INT_MASK_CPLT
#define HISI_SFC_V3XX_INT_MASK_PP_ERR
#define HISI_SFC_V3XX_INT_MASK_IACCES

/* IO Mode definition in HISI_SFC_V3XX_CMD_CFG */
#define HISI_SFC_V3XX_STD
#define HISI_SFC_V3XX_DIDO
#define HISI_SFC_V3XX_DIO
#define HISI_SFC_V3XX_FULL_DIO
#define HISI_SFC_V3XX_QIQO
#define HISI_SFC_V3XX_QIO
#define HISI_SFC_V3XX_FULL_QIO

/*
 * The IO modes lookup table. hisi_sfc_v3xx_io_modes[(z - 1) / 2][y / 2][x / 2]
 * stands for x-y-z mode, as described in SFDP terminology. -EIO indicates
 * an invalid mode.
 */
static const int hisi_sfc_v3xx_io_modes[2][3][3] =;

struct hisi_sfc_v3xx_host {};

static void hisi_sfc_v3xx_disable_int(struct hisi_sfc_v3xx_host *host)
{}

static void hisi_sfc_v3xx_enable_int(struct hisi_sfc_v3xx_host *host)
{}

static void hisi_sfc_v3xx_clear_int(struct hisi_sfc_v3xx_host *host)
{}

/*
 * The interrupt status register indicates whether an error occurs
 * after per operation. Check it, and clear the interrupts for
 * next time judgement.
 */
static int hisi_sfc_v3xx_handle_completion(struct hisi_sfc_v3xx_host *host)
{}

#define HISI_SFC_V3XX_WAIT_TIMEOUT_US
#define HISI_SFC_V3XX_WAIT_POLL_INTERVAL_US

static int hisi_sfc_v3xx_wait_cmd_idle(struct hisi_sfc_v3xx_host *host)
{}

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

/*
 * The controller only supports Standard SPI mode, Dual mode and
 * Quad mode. Double sanitize the ops here to avoid OOB access.
 */
static bool hisi_sfc_v3xx_supports_op(struct spi_mem *mem,
				      const struct spi_mem_op *op)
{}

/*
 * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the
 * DATABUF registers -so use __io{read,write}32_copy when possible. For
 * trailing bytes, copy them byte-by-byte from the DATABUF register, as we
 * can't clobber outside the source/dest buffer.
 *
 * For efficient data read/write, we try to put any start 32b unaligned data
 * into a separate transaction in hisi_sfc_v3xx_adjust_op_size().
 */
static void hisi_sfc_v3xx_read_databuf(struct hisi_sfc_v3xx_host *host,
				       u8 *to, unsigned int len)
{}

static void hisi_sfc_v3xx_write_databuf(struct hisi_sfc_v3xx_host *host,
					const u8 *from, unsigned int len)
{}

static int hisi_sfc_v3xx_start_bus(struct hisi_sfc_v3xx_host *host,
				   const struct spi_mem_op *op,
				   u8 chip_select)
{}

static int hisi_sfc_v3xx_generic_exec_op(struct hisi_sfc_v3xx_host *host,
					 const struct spi_mem_op *op,
					 u8 chip_select)
{}

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

static const struct spi_controller_mem_ops hisi_sfc_v3xx_mem_ops =;

static irqreturn_t hisi_sfc_v3xx_isr(int irq, void *data)
{}

static int hisi_sfc_v3xx_buswidth_override_bits;

/*
 * ACPI FW does not allow us to currently set the device buswidth, so quirk it
 * depending on the board.
 */
static int __init hisi_sfc_v3xx_dmi_quirk(const struct dmi_system_id *d)
{}

static const struct dmi_system_id hisi_sfc_v3xx_dmi_quirk_table[]  =;

static int hisi_sfc_v3xx_probe(struct platform_device *pdev)
{}

static const struct acpi_device_id hisi_sfc_v3xx_acpi_ids[] =;
MODULE_DEVICE_TABLE(acpi, hisi_sfc_v3xx_acpi_ids);

static struct platform_driver hisi_sfc_v3xx_spi_driver =;

static int __init hisi_sfc_v3xx_spi_init(void)
{}

static void __exit hisi_sfc_v3xx_spi_exit(void)
{}

module_init();
module_exit(hisi_sfc_v3xx_spi_exit);

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