All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wenyou Yang <wenyou.yang@microchip.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 8/8] sf: add driver for Atmel QSPI controller
Date: Tue, 25 Jul 2017 15:01:02 +0800	[thread overview]
Message-ID: <20170725070102.1344-9-wenyou.yang@microchip.com> (raw)
In-Reply-To: <20170725070102.1344-1-wenyou.yang@microchip.com>

From: Cyrille Pitchen <cyrille.pitchen@atmel.com>

This patch adds support to the Atmel Quad SPI controller.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Wenyou Yang <wenyou.yang@microchip.com>
---

Changes in v3: None
Changes in v2:
 - Rebase on the latest u-boot/master(2710d54f5).

 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 8a8e8e480f..b3e8cb941e 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 9f8b86de76..358db2b065 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 0000000000..0af7a4dc0a
--- /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 = dev_of_offset(bus);
+	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 0000000000..ee1a14bd72
--- /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__ */
-- 
2.13.0

  parent reply	other threads:[~2017-07-25  7:01 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-25  7:00 [U-Boot] [PATCH v3 0/8] sf: improve support of (Q)SPI flash memories Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 1/8] spi: add support of SPI flash commands Wenyou Yang
2017-08-30 13:50   ` Jagan Teki
2017-09-01  0:10     ` Wenyou.Yang at microchip.com
2017-07-25  7:00 ` [U-Boot] [PATCH v3 2/8] sf: describe all SPI flash commands with 'struct spi_flash_command' Wenyou Yang
2017-08-30 14:03   ` Jagan Teki
2017-07-25  7:00 ` [U-Boot] [PATCH v3 3/8] sf: select the relevant SPI flash protocol for read and write commands Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 4/8] sf: differentiate Page Program 1-1-4 and 1-4-4 Wenyou Yang
2017-07-25  7:00 ` [U-Boot] [PATCH v3 5/8] sf: add 'addr_len' member to 'struct spi_flash' Wenyou Yang
2017-07-25  7:01 ` [U-Boot] [PATCH v3 6/8] sf: add new option to support SPI flash above 16MiB Wenyou Yang
2017-07-25  7:01 ` [U-Boot] [PATCH v3 7/8] sf: add support to Microchip SST26 QSPI memories Wenyou Yang
2017-07-25  7:01 ` Wenyou Yang [this message]
2017-08-30 13:58   ` [U-Boot] [PATCH v3 8/8] sf: add driver for Atmel QSPI controller Jagan Teki
2017-07-31  7:29 ` [U-Boot] [PATCH v3 0/8] sf: improve support of (Q)SPI flash memories Yang, Wenyou
2017-08-11  1:02 ` Yang, Wenyou
2017-08-11  5:14   ` Jagan Teki
2017-08-25  1:17 ` Yang, Wenyou
2017-08-25 16:07   ` Jagan Teki
2017-08-25 16:13     ` Marek Vasut
2017-08-25 16:28       ` Jagan Teki
2017-08-25 16:45         ` Marek Vasut
2017-08-25 23:05           ` Bin Meng
2017-08-26  6:14             ` Jagan Teki
2017-08-26  8:36               ` Marek Vasut
2017-08-26 19:12                 ` Tom Rini
2017-08-26  6:34 ` Jagan Teki
2017-08-30  1:58   ` Yang, Wenyou
2017-08-30  6:33     ` Jagan Teki
2017-08-30  3:25   ` Yang, Wenyou
2017-08-30  3:43     ` Bin Meng
2017-08-30  5:27       ` Yang, Wenyou
2017-08-30  5:41         ` Bin Meng
2017-08-30  5:51           ` Yang, Wenyou
2017-08-30  6:30           ` Jagan Teki
2017-08-30  7:47             ` Bin Meng
2017-08-30 13:25               ` Jagan Teki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170725070102.1344-9-wenyou.yang@microchip.com \
    --to=wenyou.yang@microchip.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.