[U-Boot] [PATCH 8/8] sf: add driver for Atmel QSPI controller

Yang, Wenyou Wenyou.Yang at Microchip.com
Mon May 22 01:21:13 UTC 2017



On 2017/5/19 22:59, Cyrille Pitchen wrote:
> This patch adds support to the Atmel Quad SPI controller.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen at atmel.com>

Acked-by Wenyou Yang <wenyou.yang at atmel.com>


Best Regards,
Wenyou Yang
> ---
>   drivers/spi/Kconfig      |   7 +
>   drivers/spi/Makefile     |   1 +
>   drivers/spi/atmel_qspi.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++
>   drivers/spi/atmel_qspi.h | 169 ++++++++++++++++++++
>   4 files changed, 581 insertions(+)
>   create mode 100644 drivers/spi/atmel_qspi.c
>   create mode 100644 drivers/spi/atmel_qspi.h
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index f3f7dbe0897b..73f2e5c26bfb 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -32,6 +32,13 @@ config ATH79_SPI
>   	  uses driver model and requires a device tree binding to operate.
>   	  please refer to doc/device-tree-bindings/spi/spi-ath79.txt.
>   
> +config ATMEL_QSPI
> +	bool "Atmel QSPI driver"
> +	depends on ARCH_AT91
> +	help
> +	  Enable the Ateml Quad-SPI (QSPI) driver. This driver can only be
> +	  used to access SPI NOR flashes.
> +
>   config ATMEL_SPI
>   	bool "Atmel SPI driver"
>   	depends on ARCH_AT91
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index c090562c7732..af75fa41c82f 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -18,6 +18,7 @@ endif
>   obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
>   obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
>   obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
> +obj-$(CONFIG_ATMEL_QSPI) += atmel_qspi.o
>   obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
>   obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
>   obj-$(CONFIG_CF_SPI) += cf_spi.o
> diff --git a/drivers/spi/atmel_qspi.c b/drivers/spi/atmel_qspi.c
> new file mode 100644
> index 000000000000..6c265d0a4714
> --- /dev/null
> +++ b/drivers/spi/atmel_qspi.c
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright (C) 2017 Atmel Corporation
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +#include <common.h>
> +#include <clk.h>
> +#include <dm.h>
> +#include <fdtdec.h>
> +#include <errno.h>
> +#include <spi.h>
> +#include <asm/io.h>
> +#include <mach/clk.h>
> +#include "atmel_qspi.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static void atmel_qspi_memcpy_fromio(void *dst, unsigned long src, size_t len)
> +{
> +	u8 *d = (u8 *)dst;
> +
> +	while (len--) {
> +		*d++ = readb(src);
> +		src++;
> +	}
> +}
> +
> +static void atmel_qspi_memcpy_toio(unsigned long dst, const void *src,
> +				   size_t len)
> +{
> +	const u8 *s = (const u8 *)src;
> +
> +	while (len--) {
> +		writeb(*s, dst);
> +		dst++;
> +		s++;
> +	}
> +}
> +
> +static int atmel_qspi_set_ifr_tfrtype(u8 flags, u32 *ifr)
> +{
> +	u32 ifr_tfrtype;
> +
> +	switch (flags & SPI_FCMD_TYPE) {
> +	case SPI_FCMD_READ:
> +		ifr_tfrtype = QSPI_IFR_TFRTYPE_READ_MEMORY;
> +		break;
> +
> +	case SPI_FCMD_WRITE:
> +		ifr_tfrtype = QSPI_IFR_TFRTYPE_WRITE_MEMORY;
> +		break;
> +
> +	case SPI_FCMD_ERASE:
> +	case SPI_FCMD_WRITE_REG:
> +		ifr_tfrtype = QSPI_IFR_TFRTYPE_WRITE;
> +		break;
> +
> +	case SPI_FCMD_READ_REG:
> +		ifr_tfrtype = QSPI_IFR_TFRTYPE_READ;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	*ifr = (*ifr & ~QSPI_IFR_TFRTYPE) | ifr_tfrtype;
> +	return 0;
> +}
> +
> +static int atmel_qpsi_set_ifr_width(enum spi_flash_protocol proto, u32 *ifr)
> +{
> +	u32 ifr_width;
> +
> +	switch (proto) {
> +	case SPI_FPROTO_1_1_1:
> +		ifr_width = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;
> +		break;
> +
> +	case SPI_FPROTO_1_1_2:
> +		ifr_width = QSPI_IFR_WIDTH_DUAL_OUTPUT;
> +		break;
> +
> +	case SPI_FPROTO_1_2_2:
> +		ifr_width = QSPI_IFR_WIDTH_DUAL_IO;
> +		break;
> +
> +	case SPI_FPROTO_2_2_2:
> +		ifr_width = QSPI_IFR_WIDTH_DUAL_CMD;
> +		break;
> +
> +	case SPI_FPROTO_1_1_4:
> +		ifr_width = QSPI_IFR_WIDTH_QUAD_OUTPUT;
> +		break;
> +
> +	case SPI_FPROTO_1_4_4:
> +		ifr_width = QSPI_IFR_WIDTH_QUAD_IO;
> +		break;
> +
> +	case SPI_FPROTO_4_4_4:
> +		ifr_width = QSPI_IFR_WIDTH_QUAD_CMD;
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	*ifr = (*ifr & ~QSPI_IFR_WIDTH) | ifr_width;
> +	return 0;
> +}
> +
> +static int atmel_qspi_xfer(struct udevice *dev, unsigned int bitlen,
> +			   const void *dout, void *din, unsigned long flags)
> +{
> +	/* This controller can only be used with SPI NOR flashes. */
> +	return -EINVAL;
> +}
> +
> +static int atmel_qspi_set_speed(struct udevice *bus, uint hz)
> +{
> +	struct atmel_qspi_priv *aq = dev_get_priv(bus);
> +	u32 scr, scbr, mask, new_value;
> +
> +	/* Compute the QSPI baudrate */
> +	scbr = DIV_ROUND_UP(aq->bus_clk_rate, hz);
> +	if (scbr > 0)
> +		scbr--;
> +
> +	new_value = QSPI_SCR_SCBR_(scbr);
> +	mask = QSPI_SCR_SCBR;
> +
> +	scr = qspi_readl(aq, QSPI_SCR);
> +	if ((scr & mask) == new_value)
> +		return 0;
> +
> +	scr = (scr & ~mask) | new_value;
> +	qspi_writel(aq, QSPI_SCR, scr);
> +
> +	return 0;
> +}
> +
> +static int atmel_qspi_set_mode(struct udevice *bus, uint mode)
> +{
> +	struct atmel_qspi_priv *aq = dev_get_priv(bus);
> +	u32 scr, mask, new_value;
> +
> +	new_value = (QSPI_SCR_CPOL_((mode & SPI_CPOL) != 0) |
> +		     QSPI_SCR_CPHA_((mode & SPI_CPHA) != 0));
> +	mask = (QSPI_SCR_CPOL | QSPI_SCR_CPHA);
> +
> +	scr = qspi_readl(aq, QSPI_SCR);
> +	if ((scr & mask) == new_value)
> +		return 0;
> +
> +	scr = (scr & ~mask) | new_value;
> +	qspi_writel(aq, QSPI_SCR, scr);
> +
> +	return 0;
> +}
> +
> +static bool
> +atmel_qspi_is_flash_command_supported(struct udevice *dev,
> +				      const struct spi_flash_command *cmd)
> +{
> +	return true;
> +}
> +
> +static int atmel_qspi_exec_flash_command(struct udevice *dev,
> +					 const struct spi_flash_command *cmd)
> +{
> +	struct udevice *bus = dev_get_parent(dev);
> +	struct atmel_qspi_priv *aq = dev_get_priv(bus);
> +	unsigned int iar, icr, ifr;
> +	unsigned int offset;
> +	unsigned int imr, sr;
> +	unsigned long memaddr;
> +	int err;
> +
> +	iar = 0;
> +	icr = 0;
> +	ifr = 0;
> +
> +	err = atmel_qspi_set_ifr_tfrtype(cmd->flags, &ifr);
> +	if (err)
> +		return err;
> +
> +	err = atmel_qpsi_set_ifr_width(cmd->proto, &ifr);
> +	if (err)
> +		return err;
> +
> +	/* Compute instruction parameters */
> +	icr |= QSPI_ICR_INST_(cmd->inst);
> +	ifr |= QSPI_IFR_INSTEN;
> +
> +	/* Compute address parameters. */
> +	switch (cmd->addr_len) {
> +	case 4:
> +		ifr |= QSPI_IFR_ADDRL_32_BIT;
> +		/*break;*/ /* fall through the 24bit (3 byte) address case */
> +	case 3:
> +		iar = cmd->data_len ? 0 : cmd->addr;
> +		ifr |= QSPI_IFR_ADDREN;
> +		offset = cmd->addr;
> +		break;
> +	case 0:
> +		offset = 0;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/* Compute option parameters. */
> +	if (cmd->num_mode_cycles) {
> +		unsigned int mode_cycle_bits, mode_bits;
> +
> +		icr |= QSPI_ICR_OPT_(cmd->mode);
> +		ifr |= QSPI_IFR_OPTEN;
> +
> +		switch (ifr & QSPI_IFR_WIDTH) {
> +		case QSPI_IFR_WIDTH_SINGLE_BIT_SPI:
> +		case QSPI_IFR_WIDTH_DUAL_OUTPUT:
> +		case QSPI_IFR_WIDTH_QUAD_OUTPUT:
> +			mode_cycle_bits = 1;
> +			break;
> +		case QSPI_IFR_WIDTH_DUAL_IO:
> +		case QSPI_IFR_WIDTH_DUAL_CMD:
> +			mode_cycle_bits = 2;
> +			break;
> +		case QSPI_IFR_WIDTH_QUAD_IO:
> +		case QSPI_IFR_WIDTH_QUAD_CMD:
> +			mode_cycle_bits = 4;
> +			break;
> +		default:
> +			return -EINVAL;
> +		}
> +
> +		mode_bits = cmd->num_mode_cycles * mode_cycle_bits;
> +		switch (mode_bits) {
> +		case 1:
> +			ifr |= QSPI_IFR_OPTL_1BIT;
> +			break;
> +
> +		case 2:
> +			ifr |= QSPI_IFR_OPTL_2BIT;
> +			break;
> +
> +		case 4:
> +			ifr |= QSPI_IFR_OPTL_4BIT;
> +			break;
> +
> +		case 8:
> +			ifr |= QSPI_IFR_OPTL_8BIT;
> +			break;
> +
> +		default:
> +			return -EINVAL;
> +		}
> +	}
> +
> +	/* Set the number of dummy cycles. */
> +	if (cmd->num_wait_states)
> +		ifr |= QSPI_IFR_NBDUM_(cmd->num_wait_states);
> +
> +	/* Set data enable. */
> +	if (cmd->data_len)
> +		ifr |= QSPI_IFR_DATAEN;
> +
> +	/* Clear pending interrupts. */
> +	(void)qspi_readl(aq, QSPI_SR);
> +
> +	/* Set QSPI Instruction Frame registers. */
> +	qspi_writel(aq, QSPI_IAR, iar);
> +	qspi_writel(aq, QSPI_ICR, icr);
> +	qspi_writel(aq, QSPI_IFR, ifr);
> +
> +	/* Skip to the final steps if there is no data. */
> +	if (!cmd->data_len)
> +		goto no_data;
> +
> +	/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses. */
> +	(void)qspi_readl(aq, QSPI_IFR);
> +
> +	/* Stop here for Continuous Read. */
> +	memaddr = (unsigned long)(aq->membase + offset);
> +	if (cmd->tx_data)
> +		/* Write data. */
> +		atmel_qspi_memcpy_toio(memaddr, cmd->tx_data, cmd->data_len);
> +	else if (cmd->rx_data)
> +		/* Read data. */
> +		atmel_qspi_memcpy_fromio(cmd->rx_data, memaddr, cmd->data_len);
> +
> +	/* Release the chip-select. */
> +	qspi_writel(aq, QSPI_CR, QSPI_CR_LASTXFER);
> +
> +no_data:
> +	/* Poll INSTruction End and Chip Select Rise flags. */
> +	imr = QSPI_SR_INSTRE | QSPI_SR_CSR;
> +	sr = 0;
> +	while (sr != (QSPI_SR_INSTRE | QSPI_SR_CSR))
> +		sr |= qspi_readl(aq, QSPI_SR) & imr;
> +
> +	return 0;
> +}
> +
> +
> +static const struct dm_spi_ops atmel_qspi_ops = {
> +	.xfer				= atmel_qspi_xfer,
> +	.set_speed			= atmel_qspi_set_speed,
> +	.set_mode			= atmel_qspi_set_mode,
> +	.is_flash_command_supported	= atmel_qspi_is_flash_command_supported,
> +	.exec_flash_command		= atmel_qspi_exec_flash_command,
> +};
> +
> +static int atmel_qspi_enable_clk(struct udevice *bus)
> +{
> +	struct atmel_qspi_priv *aq = dev_get_priv(bus);
> +	struct clk clk;
> +	ulong clk_rate;
> +	int ret;
> +
> +	ret = clk_get_by_index(bus, 0, &clk);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = clk_enable(&clk);
> +	if (ret)
> +		goto free_clock;
> +
> +	clk_rate = clk_get_rate(&clk);
> +	if (!clk_rate) {
> +		ret = -EINVAL;
> +		goto free_clock;
> +	}
> +
> +	aq->bus_clk_rate = clk_rate;
> +
> +free_clock:
> +	clk_free(&clk);
> +
> +	return ret;
> +}
> +
> +static int atmel_qspi_probe(struct udevice *bus)
> +{
> +	const struct atmel_qspi_platdata *plat = dev_get_platdata(bus);
> +	struct atmel_qspi_priv *aq = dev_get_priv(bus);
> +	u32 mr;
> +	int ret;
> +
> +	ret = atmel_qspi_enable_clk(bus);
> +	if (ret)
> +		return ret;
> +
> +	aq->regbase = plat->regbase;
> +	aq->membase = plat->membase;
> +
> +	/* Reset the QSPI controler */
> +	qspi_writel(aq, QSPI_CR, QSPI_CR_SWRST);
> +
> +	/* Set the QSPI controller in Serial Memory Mode */
> +	mr = (QSPI_MR_NBBITS_8_BIT |
> +	      QSPI_MR_SMM_MEMORY |
> +	      QSPI_MR_CSMODE_LASTXFER);
> +	qspi_writel(aq, QSPI_MR, mr);
> +
> +	/* Enable the QSPI controller */
> +	qspi_writel(aq, QSPI_CR, QSPI_CR_QSPIEN);
> +
> +	return 0;
> +}
> +
> +static int atmel_qspi_ofdata_to_platdata(struct udevice *bus)
> +{
> +	struct atmel_qspi_platdata *plat = dev_get_platdata(bus);
> +	const void *blob = gd->fdt_blob;
> +	int node = bus->of_offset;
> +	u32 data[4];
> +	int ret;
> +
> +	ret = fdtdec_get_int_array(blob, node, "reg", data, ARRAY_SIZE(data));
> +	if (ret) {
> +		printf("Error: Can't get base addresses (ret=%d)!\n", ret);
> +		return -ENODEV;
> +	}
> +	plat->regbase = (void *)data[0];
> +	plat->membase = (void *)data[2];
> +
> +	return 0;
> +}
> +
> +static const struct udevice_id atmel_qspi_ids[] = {
> +	{ .compatible = "atmel,sama5d2-qspi" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(atmel_qspi) = {
> +	.name		= "atmel_qspi",
> +	.id		= UCLASS_SPI,
> +	.of_match	= atmel_qspi_ids,
> +	.ops		= &atmel_qspi_ops,
> +	.ofdata_to_platdata = atmel_qspi_ofdata_to_platdata,
> +	.platdata_auto_alloc_size = sizeof(struct atmel_qspi_platdata),
> +	.priv_auto_alloc_size = sizeof(struct atmel_qspi_priv),
> +	.probe		= atmel_qspi_probe,
> +};
> diff --git a/drivers/spi/atmel_qspi.h b/drivers/spi/atmel_qspi.h
> new file mode 100644
> index 000000000000..ee1a14bd726d
> --- /dev/null
> +++ b/drivers/spi/atmel_qspi.h
> @@ -0,0 +1,169 @@
> +/*
> + * Copyright (C) 2016
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __ATMEL_QSPI_H__
> +#define __ATMEL_QSPI_H__
> +
> +/*
> + * Register Definitions
> + */
> +#define	QSPI_CR		0x00	/* Control Register */
> +#define	QSPI_MR		0x04	/* Mode Register */
> +#define	QSPI_RDR	0x08	/* Receive Data Register */
> +#define	QSPI_TDR	0x0c	/* Transmit Data Register */
> +#define	QSPI_SR		0x10	/* Status Register */
> +#define	QSPI_IER	0x14	/* Interrupt Enable Register */
> +#define	QSPI_IDR	0x18	/* Interrupt Disable Register */
> +#define	QSPI_IMR	0x1c	/* Interrupt Mask Register */
> +#define	QSPI_SCR	0x20	/* Serial Clock Register */
> +#define	QSPI_IAR	0x30	/* Instruction Address Register */
> +#define	QSPI_ICR	0x34	/* Instruction Code Register */
> +#define	QSPI_IFR	0x38	/* Instruction Frame Register */
> +/* 0x3c Reserved */
> +#define	QSPI_SMR	0x40	/* Scrambling Mode Register */
> +#define	QSPI_SKR	0x44	/* Scrambling Key Register */
> +/* 0x48 ~ 0xe0 */
> +#define	QSPI_WPMR	0xe4	/* Write Protection Mode Register */
> +#define	QSPI_WPSR	0xe8	/* Write Protection Status Register */
> +/* 0xec ~ 0xf8 Reserved */
> +/* 0xfc Reserved */
> +
> +/*
> + * Register Field Definitions
> + */
> +/* QSPI_CR */
> +#define	QSPI_CR_QSPIEN		BIT(0)	/* QSPI Enable */
> +#define	QSPI_CR_QSPIDIS		BIT(1)	/* QSPI Disable */
> +#define	QSPI_CR_SWRST		BIT(7)	/* QSPI Software Reset */
> +#define	QSPI_CR_LASTXFER	BIT(24)	/* Last Transfer */
> +
> +/* QSPI_MR */
> +#define	QSPI_MR_SMM		BIT(0)	/* Serial Memort Mode */
> +#define		QSPI_MR_SMM_SPI		0
> +#define		QSPI_MR_SMM_MEMORY	QSPI_MR_SMM
> +#define	QSPI_MR_LLB		BIT(1)	/* Local Localback Enable */
> +#define		QSPI_MR_LLB_DISABLED	0
> +#define		QSPI_MR_LLB_ENABLED	QSPI_MR_LLB
> +#define	QSPI_MR_WDRBT		BIT(2)	/* Wait Data Read Before Transfer */
> +#define		QSPI_MR_WDRBT_DISABLED	0
> +#define		QSPI_MR_WDRBT_ENABLED	QSPI_MR_WDRBT
> +#define	QSPI_MR_SMRM		BIT(3)	/* Serial Memory Register Mode */
> +#define		QSPI_MR_SMRM_AHB	0
> +#define		QSPI_MR_SMRM_APB	QSPI_MR_SMRM
> +#define	QSPI_MR_CSMODE		GENMASK(5, 4)	/* Chip Select Mode */
> +#define		QSPI_MR_CSMODE_NOT_RELOADED	(0x0u << 4)
> +#define		QSPI_MR_CSMODE_LASTXFER		(0x1u << 4)
> +#define		QSPI_MR_CSMODE_SYSTEMATICALLY	(0x2u << 4)
> +#define	QSPI_MR_NBBITS		GENMASK(11, 8)	/*
> +						 * Number of Bits Per
> +						 * Transfer
> +						 */
> +#define		QSPI_MR_NBBITS_8_BIT		(0x0u << 8)
> +#define		QSPI_MR_NBBITS_16_BIT		(0x8u << 8)
> +#define	QSPI_MR_DLYBCT		GENMASK(23, 16)	/*
> +						 * Delay Between Consecutive
> +						 * Transfers
> +						 */
> +#define	QSPI_MR_DLYCS		GENMASK(31, 24)	/* Minimum Inactive QCS Delay */
> +
> +/* QSPI_SR */
> +#define	QSPI_SR_RDRF		BIT(0)	/* Receive Data Register Full */
> +#define	QSPI_SR_TDRE		BIT(1)	/* Transmit Data Register Empty */
> +#define	QSPI_SR_TXEMPTY		BIT(2)	/* Transmission Registers Empty */
> +#define	QSPI_SR_OVRES		BIT(3)	/* Overrun Error Status */
> +#define	QSPI_SR_CSR		BIT(8)	/* Chip Select Rise */
> +#define	QSPI_SR_CSS		BIT(9)	/* Chip Select Status */
> +#define	QSPI_SR_INSTRE		BIT(10)	/* Instruction End Status */
> +#define	QSPI_SR_QSPIENS		BIT(24)	/* QSPI Enable Status */
> +
> +/* QSPI_SCR */
> +#define	QSPI_SCR_CPOL		BIT(0)	/* Clock Polarity */
> +#define	QSPI_SCR_CPOL_(x)	((x) << 0)
> +#define	QSPI_SCR_CPHA		BIT(1)	/* Clock Phase */
> +#define	QSPI_SCR_CPHA_(x)	((x) << 1)
> +#define	QSPI_SCR_SCBR		GENMASK(15, 8)	/* Serial Clock Baud Rate */
> +#define	QSPI_SCR_SCBR_(x)	(((x) << 8) & QSPI_SCR_SCBR)
> +#define QSPI_SCR_DLYBS		GENMASK(23, 16)
> +#define	QSPI_SCR_DLYBS_(x)	(((x) << 16) & QSPI_SCR_DLYBS)	/*
> +								 * Delay Before
> +								 * QSCK
> +								 */
> +
> +/* QSPI_ICR */
> +#define QSPI_ICR_INST		GENMASK(7, 0)
> +#define	QSPI_ICR_INST_(x)	(((x) << 0) & QSPI_ICR_INST)	/*
> +								 * Instruction
> +								 * Code
> +								 */
> +#define QSPI_ICR_OPT		GENMASK(23, 16)
> +#define	QSPI_ICR_OPT_(x)	(((x) << 16) & QSPI_ICR_OPT)	/*
> +								 * Option
> +								 * Code
> +								 */
> +
> +/* QSPI_IFR */
> +#define	QSPI_IFR_WIDTH		GENMASK(2, 0)	/*
> +						 * Width of Instruction Code,
> +						 * Address, Option Code and Data
> +						 */
> +#define		QSPI_IFR_WIDTH_SINGLE_BIT_SPI	(0x0u << 0)
> +#define		QSPI_IFR_WIDTH_DUAL_OUTPUT	(0x1u << 0)
> +#define		QSPI_IFR_WIDTH_QUAD_OUTPUT	(0x2u << 0)
> +#define		QSPI_IFR_WIDTH_DUAL_IO		(0x3u << 0)
> +#define		QSPI_IFR_WIDTH_QUAD_IO		(0x4u << 0)
> +#define		QSPI_IFR_WIDTH_DUAL_CMD		(0x5u << 0)
> +#define		QSPI_IFR_WIDTH_QUAD_CMD		(0x6u << 0)
> +#define QSPI_IFR_WIDTH_(x)	(((x) << 0) & QSPI_IFR_WIDTH)
> +#define	QSPI_IFR_INSTEN		BIT(4)	/* Instruction Enable*/
> +#define	QSPI_IFR_ADDREN		BIT(5)	/* Address Enable*/
> +#define	QSPI_IFR_OPTEN		BIT(6)	/* Option Enable*/
> +#define	QSPI_IFR_DATAEN		BIT(7)	/* Data Enable*/
> +#define	QSPI_IFR_OPTL		GENMASK(9, 8)	/* Option Code Length */
> +#define		QSPI_IFR_OPTL_1BIT		(0x0u << 8)
> +#define		QSPI_IFR_OPTL_2BIT		(0x1u << 8)
> +#define		QSPI_IFR_OPTL_4BIT		(0x2u << 8)
> +#define		QSPI_IFR_OPTL_8BIT		(0x3u << 8)
> +#define	QSPI_IFR_ADDRL		BIT(10)	/* Address Length */
> +#define		QSPI_IFR_ADDRL_24_BIT		0
> +#define		QSPI_IFR_ADDRL_32_BIT		QSPI_IFR_ADDRL
> +#define	QSPI_IFR_TFRTYPE	GENMASK(13, 12)	/* Data Transfer Type */
> +#define		QSPI_IFR_TFRTYPE_READ		(0x0u << 12)
> +#define		QSPI_IFR_TFRTYPE_READ_MEMORY	(0x1u << 12)
> +#define		QSPI_IFR_TFRTYPE_WRITE		(0x2u << 12)
> +#define		QSPI_IFR_TFRTYPE_WRITE_MEMORY	(0x3u << 12)
> +#define QSPI_IFR_TFRTYPE_(x)	(((x) << 12) & QSPI_IFR_TFRTYPE)
> +#define	QSPI_IFR_CRM		BIT(14)	/* Continuous Read Mode */
> +#define QSPI_IFR_NBDUM		GENMASK(20, 16)
> +#define	QSPI_IFR_NBDUM_(x)	(((x) << 16) & QSPI_IFR_NBDUM)	/*
> +								 * Number Of
> +								 * Dummy Cycles
> +								 */
> +
> +
> +struct atmel_qspi_platdata {
> +	void		*regbase;
> +	void		*membase;
> +};
> +
> +struct atmel_qspi_priv {
> +	ulong		bus_clk_rate;
> +	void		*regbase;
> +	void		*membase;
> +};
> +
> +#include <asm/io.h>
> +
> +static inline u32 qspi_readl(struct atmel_qspi_priv *aq, u32 reg)
> +{
> +	return readl(aq->regbase + reg);
> +}
> +
> +static inline void qspi_writel(struct atmel_qspi_priv *aq, u32 reg, u32 value)
> +{
> +	writel(value, aq->regbase + reg);
> +}
> +
> +#endif /* __ATMEL_QSPI_H__ */



More information about the U-Boot mailing list