Lines Matching +full:zynq +full:- +full:qspi +full:- +full:1
1 // SPDX-License-Identifier: GPL-2.0+
6 * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only)
17 /* zynq qspi register bit masks ZYNQ_QSPI_<REG>_<BIT>_MASK */
26 #define ZYNQ_QSPI_CR_CPOL_MASK BIT(1) /* Clock polarity */
32 #define ZYNQ_QSPI_LQSPICFG_LQMODE_MASK BIT(31) /* Linear QSPI Mode */
34 /* zynq qspi Transmit Data Register */
35 #define ZYNQ_QSPI_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst */
36 #define ZYNQ_QSPI_TXD_00_01_OFFSET 0x80 /* Transmit 1-byte inst */
37 #define ZYNQ_QSPI_TXD_00_10_OFFSET 0x84 /* Transmit 2-byte inst */
38 #define ZYNQ_QSPI_TXD_00_11_OFFSET 0x88 /* Transmit 3-byte inst */
40 #define ZYNQ_QSPI_TXFIFO_THRESHOLD 1 /* Tx FIFO threshold level*/
52 /* zynq qspi register set */
76 /* zynq qspi platform data */
83 /* zynq qspi priv */
96 unsigned cs_change:1;
101 struct zynq_qspi_platdata *plat = bus->platdata; in zynq_qspi_ofdata_to_platdata()
102 const void *blob = gd->fdt_blob; in zynq_qspi_ofdata_to_platdata()
105 plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob, in zynq_qspi_ofdata_to_platdata()
109 plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", in zynq_qspi_ofdata_to_platdata()
111 plat->speed_hz = plat->frequency / 2; in zynq_qspi_ofdata_to_platdata()
113 debug("%s: regs=%p max-frequency=%d\n", __func__, in zynq_qspi_ofdata_to_platdata()
114 plat->regs, plat->frequency); in zynq_qspi_ofdata_to_platdata()
121 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_init_hw()
124 /* Disable QSPI */ in zynq_qspi_init_hw()
125 writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); in zynq_qspi_init_hw()
128 writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->idr); in zynq_qspi_init_hw()
131 writel(ZYNQ_QSPI_TXFIFO_THRESHOLD, ®s->txftr); in zynq_qspi_init_hw()
132 writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, ®s->rxftr); in zynq_qspi_init_hw()
135 while (readl(®s->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK) in zynq_qspi_init_hw()
136 readl(®s->drxr); in zynq_qspi_init_hw()
139 writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->isr); in zynq_qspi_init_hw()
142 confr = readl(®s->cr); in zynq_qspi_init_hw()
147 writel(confr, ®s->cr); in zynq_qspi_init_hw()
150 confr = readl(®s->lqspicfg); in zynq_qspi_init_hw()
152 writel(confr, ®s->lqspicfg); in zynq_qspi_init_hw()
155 writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); in zynq_qspi_init_hw()
163 priv->regs = plat->regs; in zynq_qspi_probe()
164 priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH; in zynq_qspi_probe()
166 /* init the zynq spi hw */ in zynq_qspi_probe()
173 * zynq_qspi_read_data - Copy data to RX buffer
183 data, (unsigned)(priv->rx_buf), size); in zynq_qspi_read_data()
185 if (priv->rx_buf) { in zynq_qspi_read_data()
187 case 1: in zynq_qspi_read_data()
188 *((u8 *)priv->rx_buf) = data; in zynq_qspi_read_data()
189 priv->rx_buf += 1; in zynq_qspi_read_data()
192 *((u16 *)priv->rx_buf) = data; in zynq_qspi_read_data()
193 priv->rx_buf += 2; in zynq_qspi_read_data()
196 *((u16 *)priv->rx_buf) = data; in zynq_qspi_read_data()
197 priv->rx_buf += 2; in zynq_qspi_read_data()
199 *((u8 *)priv->rx_buf) = byte3; in zynq_qspi_read_data()
200 priv->rx_buf += 1; in zynq_qspi_read_data()
204 memcpy(priv->rx_buf, &data, size); in zynq_qspi_read_data()
205 priv->rx_buf += 4; in zynq_qspi_read_data()
212 priv->bytes_to_receive -= size; in zynq_qspi_read_data()
213 if (priv->bytes_to_receive < 0) in zynq_qspi_read_data()
214 priv->bytes_to_receive = 0; in zynq_qspi_read_data()
218 * zynq_qspi_write_data - Copy data from TX buffer
226 if (priv->tx_buf) { in zynq_qspi_write_data()
228 case 1: in zynq_qspi_write_data()
229 *data = *((u8 *)priv->tx_buf); in zynq_qspi_write_data()
230 priv->tx_buf += 1; in zynq_qspi_write_data()
234 *data = *((u16 *)priv->tx_buf); in zynq_qspi_write_data()
235 priv->tx_buf += 2; in zynq_qspi_write_data()
239 *data = *((u16 *)priv->tx_buf); in zynq_qspi_write_data()
240 priv->tx_buf += 2; in zynq_qspi_write_data()
241 *data |= (*((u8 *)priv->tx_buf) << 16); in zynq_qspi_write_data()
242 priv->tx_buf += 1; in zynq_qspi_write_data()
247 memcpy(data, priv->tx_buf, size); in zynq_qspi_write_data()
248 priv->tx_buf += 4; in zynq_qspi_write_data()
259 *data, (u32)priv->tx_buf, size); in zynq_qspi_write_data()
261 priv->bytes_to_transfer -= size; in zynq_qspi_write_data()
262 if (priv->bytes_to_transfer < 0) in zynq_qspi_write_data()
263 priv->bytes_to_transfer = 0; in zynq_qspi_write_data()
269 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_chipselect()
271 confr = readl(®s->cr); in zynq_qspi_chipselect()
276 confr |= (~(1 << priv->cs) << ZYNQ_QSPI_CR_SS_SHIFT) & in zynq_qspi_chipselect()
282 writel(confr, ®s->cr); in zynq_qspi_chipselect()
286 * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
294 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_fill_tx_fifo()
300 (priv->bytes_to_transfer > 0)) { in zynq_qspi_fill_tx_fifo()
301 if (priv->bytes_to_transfer >= 4) { in zynq_qspi_fill_tx_fifo()
302 if (priv->tx_buf) { in zynq_qspi_fill_tx_fifo()
303 memcpy(&data, priv->tx_buf, 4); in zynq_qspi_fill_tx_fifo()
304 priv->tx_buf += 4; in zynq_qspi_fill_tx_fifo()
308 writel(data, ®s->txd0r); in zynq_qspi_fill_tx_fifo()
309 priv->bytes_to_transfer -= 4; in zynq_qspi_fill_tx_fifo()
313 if (!(readl(®s->isr) in zynq_qspi_fill_tx_fifo()
315 !priv->rx_buf) in zynq_qspi_fill_tx_fifo()
317 len = priv->bytes_to_transfer; in zynq_qspi_fill_tx_fifo()
319 offset = (priv->rx_buf) ? offsets[0] : offsets[len]; in zynq_qspi_fill_tx_fifo()
320 writel(data, ®s->cr + (offset / 4)); in zynq_qspi_fill_tx_fifo()
326 * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
334 * transferred is non-zero.
337 * 1 transfer operation complete
341 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_irq_poll()
349 status = readl(®s->isr); in zynq_qspi_irq_poll()
355 return -ETIMEDOUT; in zynq_qspi_irq_poll()
358 writel(status, ®s->isr); in zynq_qspi_irq_poll()
361 writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->idr); in zynq_qspi_irq_poll()
366 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO in zynq_qspi_irq_poll()
369 rxcount = priv->bytes_to_receive - priv->bytes_to_transfer; in zynq_qspi_irq_poll()
370 rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4); in zynq_qspi_irq_poll()
375 data = readl(®s->drxr); in zynq_qspi_irq_poll()
377 if (priv->bytes_to_receive >= 4) { in zynq_qspi_irq_poll()
378 if (priv->rx_buf) { in zynq_qspi_irq_poll()
379 memcpy(priv->rx_buf, &data, 4); in zynq_qspi_irq_poll()
380 priv->rx_buf += 4; in zynq_qspi_irq_poll()
382 priv->bytes_to_receive -= 4; in zynq_qspi_irq_poll()
385 priv->bytes_to_receive); in zynq_qspi_irq_poll()
390 if (priv->bytes_to_transfer) { in zynq_qspi_irq_poll()
395 writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->ier); in zynq_qspi_irq_poll()
401 if (!priv->bytes_to_receive) { in zynq_qspi_irq_poll()
404 ®s->idr); in zynq_qspi_irq_poll()
405 return 1; in zynq_qspi_irq_poll()
414 * zynq_qspi_start_transfer - Initiates the QSPI transfer
415 * @qspi: Pointer to the spi_device structure
419 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
427 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_start_transfer()
429 debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__, in zynq_qspi_start_transfer()
430 (u32)priv, (u32)priv, priv->len); in zynq_qspi_start_transfer()
432 priv->bytes_to_transfer = priv->len; in zynq_qspi_start_transfer()
433 priv->bytes_to_receive = priv->len; in zynq_qspi_start_transfer()
435 if (priv->len < 4) in zynq_qspi_start_transfer()
436 zynq_qspi_fill_tx_fifo(priv, priv->len); in zynq_qspi_start_transfer()
438 zynq_qspi_fill_tx_fifo(priv, priv->fifo_depth); in zynq_qspi_start_transfer()
440 writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->ier); in zynq_qspi_start_transfer()
447 return (priv->len) - (priv->bytes_to_transfer); in zynq_qspi_start_transfer()
452 unsigned cs_change = 1; in zynq_qspi_transfer()
455 while (1) { in zynq_qspi_transfer()
458 zynq_qspi_chipselect(priv, 1); in zynq_qspi_transfer()
460 cs_change = priv->cs_change; in zynq_qspi_transfer()
462 if (!priv->tx_buf && !priv->rx_buf && priv->len) { in zynq_qspi_transfer()
463 status = -1; in zynq_qspi_transfer()
468 if (priv->len) { in zynq_qspi_transfer()
470 priv->is_inst = 0; in zynq_qspi_transfer()
473 if (status != priv->len) { in zynq_qspi_transfer()
475 status = -EMSGSIZE; in zynq_qspi_transfer()
477 status, priv->len); in zynq_qspi_transfer()
494 struct udevice *bus = dev->parent; in zynq_qspi_claim_bus()
496 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_claim_bus()
498 writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); in zynq_qspi_claim_bus()
505 struct udevice *bus = dev->parent; in zynq_qspi_release_bus()
507 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_release_bus()
509 writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); in zynq_qspi_release_bus()
517 struct udevice *bus = dev->parent; in zynq_qspi_xfer()
521 priv->cs = slave_plat->cs; in zynq_qspi_xfer()
522 priv->tx_buf = dout; in zynq_qspi_xfer()
523 priv->rx_buf = din; in zynq_qspi_xfer()
524 priv->len = bitlen / 8; in zynq_qspi_xfer()
527 bus->seq, slave_plat->cs, bitlen, priv->len, flags); in zynq_qspi_xfer()
535 priv->is_inst = 1; in zynq_qspi_xfer()
537 priv->is_inst = 0; in zynq_qspi_xfer()
540 priv->cs_change = 1; in zynq_qspi_xfer()
542 priv->cs_change = 0; in zynq_qspi_xfer()
551 struct zynq_qspi_platdata *plat = bus->platdata; in zynq_qspi_set_speed()
553 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_set_speed()
557 if (speed > plat->frequency) in zynq_qspi_set_speed()
558 speed = plat->frequency; in zynq_qspi_set_speed()
561 confr = readl(®s->cr); in zynq_qspi_set_speed()
565 } else if (plat->speed_hz != speed) { in zynq_qspi_set_speed()
567 ((plat->frequency / in zynq_qspi_set_speed()
571 plat->speed_hz = speed / (2 << baud_rate_val); in zynq_qspi_set_speed()
576 writel(confr, ®s->cr); in zynq_qspi_set_speed()
577 priv->freq = speed; in zynq_qspi_set_speed()
579 debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq); in zynq_qspi_set_speed()
587 struct zynq_qspi_regs *regs = priv->regs; in zynq_qspi_set_mode()
591 confr = readl(®s->cr); in zynq_qspi_set_mode()
599 writel(confr, ®s->cr); in zynq_qspi_set_mode()
600 priv->mode = mode; in zynq_qspi_set_mode()
602 debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode); in zynq_qspi_set_mode()
616 { .compatible = "xlnx,zynq-qspi-1.0" },