[U-Boot] [PATCH 2/9] spi: zynq_qspi: Add support of Dual parallel and Dual stacked modes
Siva Durga Prasad Paladugu
siva.durga.paladugu at xilinx.com
Mon Jun 6 11:44:47 CEST 2016
Add Dual parallel and dual stacked supports for zynq
qspi driver. The is-dual property defines the dual
parallel mode and num-cs, numbere of chip selects
defines dual stacked mode if its value is 2
Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
---
drivers/spi/zynq_qspi.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
index e636244..44057ba 100644
--- a/drivers/spi/zynq_qspi.c
+++ b/drivers/spi/zynq_qspi.c
@@ -52,6 +52,10 @@ DECLARE_GLOBAL_DATA_PTR;
#define CONFIG_SYS_ZYNQ_QSPI_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
#endif
+#define ZYNQ_QSPI_LCR_TWO_MEM_MASK BIT(30) /* QSPI Enable Bit Mask */
+#define ZYNQ_QSPI_LCR_SEP_BUS_MASK BIT(29) /* QSPI Enable Bit Mask */
+#define ZYNQ_QSPI_LCR_U_PAGE BIT(28) /* QSPI Upper memory set */
+
/* zynq qspi register set */
struct zynq_qspi_regs {
u32 cr; /* 0x00 */
@@ -96,6 +100,8 @@ struct zynq_qspi_priv {
int bytes_to_transfer;
int bytes_to_receive;
unsigned int is_inst;
+ unsigned int is_dual;
+ unsigned int u_page;
unsigned cs_change:1;
};
@@ -154,6 +160,14 @@ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK;
writel(confr, ®s->lqspicfg);
+ if (priv->is_dual == SF_DUAL_PARALLEL_FLASH)
+ writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK |
+ ZYNQ_QSPI_LCR_SEP_BUS_MASK,
+ ®s->lqspicfg);
+ else if (priv->is_dual == SF_DUAL_STACKED_FLASH)
+ writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK,
+ ®s->lqspicfg);
+
/* Enable SPI */
writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr);
}
@@ -161,7 +175,9 @@ static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
static int zynq_qspi_child_pre_probe(struct udevice *bus)
{
struct spi_slave *slave = dev_get_parent_priv(bus);
+ struct zynq_qspi_priv *priv = dev_get_priv(bus->parent);
+ slave->option = priv->is_dual;
slave->mode_rx = QUAD_OUTPUT_FAST;
slave->mode = SPI_TX_QUAD;
slave->no_all_quad = 1;
@@ -173,10 +189,23 @@ static int zynq_qspi_probe(struct udevice *bus)
{
struct zynq_qspi_platdata *plat = dev_get_platdata(bus);
struct zynq_qspi_priv *priv = dev_get_priv(bus);
+ const void *blob = gd->fdt_blob;
+ int node = bus->of_offset;
+ u8 is_dual = 0;
+ u8 num_cs = 0;
priv->regs = plat->regs;
priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
+ is_dual = fdtdec_get_int(blob, node, "is-dual", 0);
+ if (is_dual) {
+ priv->is_dual = SF_DUAL_PARALLEL_FLASH;
+ } else {
+ num_cs = fdtdec_get_int(blob, node, "num-cs", 1);
+ if (num_cs == 2)
+ priv->is_dual = SF_DUAL_STACKED_FLASH;
+ }
+
/* init the zynq spi hw */
zynq_qspi_init_hw(priv);
@@ -437,6 +466,7 @@ static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
*/
static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
{
+ static u8 current_u_page;
u32 data = 0;
struct zynq_qspi_regs *regs = priv->regs;
@@ -446,6 +476,18 @@ static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
priv->bytes_to_transfer = priv->len;
priv->bytes_to_receive = priv->len;
+ if (priv->is_inst && (priv->is_dual == SF_DUAL_STACKED_FLASH) &&
+ (current_u_page != priv->u_page)) {
+ if (priv->u_page)
+ writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK |
+ ZYNQ_QSPI_LCR_U_PAGE,
+ ®s->lqspicfg);
+ else
+ writel(ZYNQ_QSPI_LCR_TWO_MEM_MASK,
+ ®s->lqspicfg);
+ current_u_page = priv->u_page;
+ }
+
if (priv->len < 4)
zynq_qspi_fill_tx_fifo(priv, priv->len);
else
@@ -555,6 +597,11 @@ static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
else
priv->cs_change = 0;
+ if (flags & SPI_XFER_U_PAGE)
+ priv->u_page = 1;
+ else
+ priv->u_page = 0;
+
zynq_qspi_transfer(priv);
return 0;
--
1.7.1
More information about the U-Boot
mailing list