blob: 816916de16d26294b992cd5ee83148dc4b3fb3e6 [file] [log] [blame]
T Karthik Reddy73701e72022-05-12 04:05:32 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2018 Xilinx
4 *
5 * Cadence QSPI controller DMA operations
6 */
7
8#include <clk.h>
T Karthik Reddy73701e72022-05-12 04:05:32 -06009#include <memalign.h>
10#include <wait_bit.h>
11#include <asm/io.h>
12#include <asm/gpio.h>
13#include <asm/cache.h>
14#include <cpu_func.h>
15#include <zynqmp_firmware.h>
16#include <asm/arch/hardware.h>
17#include "cadence_qspi.h"
18#include <dt-bindings/power/xlnx-versal-power.h>
19
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060020int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
T Karthik Reddy73701e72022-05-12 04:05:32 -060021 const struct spi_mem_op *op)
22{
23 u32 reg, ret, rx_rem, n_rx, bytes_to_dma, data;
24 u8 opcode, addr_bytes, *rxbuf, dummy_cycles;
25
26 n_rx = op->data.nbytes;
Padmarao Begarif8e7cef2025-01-06 15:21:20 +053027
28 if (op->addr.dtr && (op->addr.val % 2)) {
29 n_rx += 1;
30 writel(op->addr.val & ~0x1,
31 priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
32 }
33
T Karthik Reddy73701e72022-05-12 04:05:32 -060034 rxbuf = op->data.buf.in;
35 rx_rem = n_rx % 4;
36 bytes_to_dma = n_rx - rx_rem;
37
38 if (bytes_to_dma) {
T Karthik Reddy3b49fbf2022-05-12 04:05:34 -060039 cadence_qspi_apb_enable_linear_mode(false);
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060040 reg = readl(priv->regbase + CQSPI_REG_CONFIG);
T Karthik Reddy73701e72022-05-12 04:05:32 -060041 reg |= CQSPI_REG_CONFIG_ENBL_DMA;
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060042 writel(reg, priv->regbase + CQSPI_REG_CONFIG);
T Karthik Reddy73701e72022-05-12 04:05:32 -060043
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060044 writel(bytes_to_dma, priv->regbase + CQSPI_REG_INDIRECTRDBYTES);
T Karthik Reddy73701e72022-05-12 04:05:32 -060045
46 writel(CQSPI_DFLT_INDIR_TRIG_ADDR_RANGE,
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060047 priv->regbase + CQSPI_REG_INDIR_TRIG_ADDR_RANGE);
T Karthik Reddy73701e72022-05-12 04:05:32 -060048 writel(CQSPI_DFLT_DMA_PERIPH_CFG,
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060049 priv->regbase + CQSPI_REG_DMA_PERIPH_CFG);
Venkatesh Yadav Abbarapucf014982023-10-11 08:45:15 +053050 writel(lower_32_bits((unsigned long)rxbuf), priv->regbase +
T Karthik Reddy73701e72022-05-12 04:05:32 -060051 CQSPI_DMA_DST_ADDR_REG);
Venkatesh Yadav Abbarapucf014982023-10-11 08:45:15 +053052 writel(upper_32_bits((unsigned long)rxbuf), priv->regbase +
53 CQSPI_DMA_DST_ADDR_MSB_REG);
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060054 writel(priv->trigger_address, priv->regbase +
T Karthik Reddy73701e72022-05-12 04:05:32 -060055 CQSPI_DMA_SRC_RD_ADDR_REG);
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060056 writel(bytes_to_dma, priv->regbase +
T Karthik Reddy73701e72022-05-12 04:05:32 -060057 CQSPI_DMA_DST_SIZE_REG);
58 flush_dcache_range((unsigned long)rxbuf,
59 (unsigned long)rxbuf + bytes_to_dma);
60 writel(CQSPI_DFLT_DST_CTRL_REG_VAL,
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060061 priv->regbase + CQSPI_DMA_DST_CTRL_REG);
T Karthik Reddy73701e72022-05-12 04:05:32 -060062
63 /* Start the indirect read transfer */
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060064 writel(CQSPI_REG_INDIRECTRD_START, priv->regbase +
T Karthik Reddy73701e72022-05-12 04:05:32 -060065 CQSPI_REG_INDIRECTRD);
66 /* Wait for dma to complete transfer */
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060067 ret = cadence_qspi_apb_wait_for_dma_cmplt(priv);
T Karthik Reddy73701e72022-05-12 04:05:32 -060068 if (ret)
69 return ret;
70
71 /* Clear indirect completion status */
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060072 writel(CQSPI_REG_INDIRECTRD_DONE, priv->regbase +
T Karthik Reddy73701e72022-05-12 04:05:32 -060073 CQSPI_REG_INDIRECTRD);
74 rxbuf += bytes_to_dma;
75 }
76
77 if (rx_rem) {
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060078 reg = readl(priv->regbase + CQSPI_REG_CONFIG);
T Karthik Reddy73701e72022-05-12 04:05:32 -060079 reg &= ~CQSPI_REG_CONFIG_ENBL_DMA;
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060080 writel(reg, priv->regbase + CQSPI_REG_CONFIG);
T Karthik Reddy73701e72022-05-12 04:05:32 -060081
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060082 reg = readl(priv->regbase + CQSPI_REG_INDIRECTRDSTARTADDR);
T Karthik Reddy73701e72022-05-12 04:05:32 -060083 reg += bytes_to_dma;
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060084 writel(reg, priv->regbase + CQSPI_REG_CMDADDRESS);
T Karthik Reddy73701e72022-05-12 04:05:32 -060085
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060086 addr_bytes = readl(priv->regbase + CQSPI_REG_SIZE) &
T Karthik Reddy73701e72022-05-12 04:05:32 -060087 CQSPI_REG_SIZE_ADDRESS_MASK;
88
89 opcode = CMD_4BYTE_FAST_READ;
90 dummy_cycles = 8;
91 writel((dummy_cycles << CQSPI_REG_RD_INSTR_DUMMY_LSB) | opcode,
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060092 priv->regbase + CQSPI_REG_RD_INSTR);
T Karthik Reddy73701e72022-05-12 04:05:32 -060093
94 reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
95 reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
96 reg |= (addr_bytes & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
97 CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
98 reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
Ashok Reddy Somaf5817652022-08-24 05:38:47 -060099 dummy_cycles = (readl(priv->regbase + CQSPI_REG_RD_INSTR) >>
T Karthik Reddy73701e72022-05-12 04:05:32 -0600100 CQSPI_REG_RD_INSTR_DUMMY_LSB) &
101 CQSPI_REG_RD_INSTR_DUMMY_MASK;
102 reg |= (dummy_cycles & CQSPI_REG_CMDCTRL_DUMMY_MASK) <<
103 CQSPI_REG_CMDCTRL_DUMMY_LSB;
104 reg |= (((rx_rem - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK) <<
105 CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
Ashok Reddy Somaf5817652022-08-24 05:38:47 -0600106 ret = cadence_qspi_apb_exec_flash_cmd(priv->regbase, reg);
T Karthik Reddy73701e72022-05-12 04:05:32 -0600107 if (ret)
108 return ret;
109
Ashok Reddy Somaf5817652022-08-24 05:38:47 -0600110 data = readl(priv->regbase + CQSPI_REG_CMDREADDATALOWER);
T Karthik Reddy73701e72022-05-12 04:05:32 -0600111 memcpy(rxbuf, &data, rx_rem);
112 }
113
Padmarao Begarif8e7cef2025-01-06 15:21:20 +0530114 if (op->addr.dtr && (op->addr.val % 2)) {
115 rxbuf -= bytes_to_dma;
116 memcpy(rxbuf, rxbuf + 1, n_rx - 1);
117 }
118
T Karthik Reddy73701e72022-05-12 04:05:32 -0600119 return 0;
120}
121
Ashok Reddy Somaf5817652022-08-24 05:38:47 -0600122int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv)
T Karthik Reddy73701e72022-05-12 04:05:32 -0600123{
124 u32 timeout = CQSPI_DMA_TIMEOUT;
125
Ashok Reddy Somaf5817652022-08-24 05:38:47 -0600126 while (!(readl(priv->regbase + CQSPI_DMA_DST_I_STS_REG) &
T Karthik Reddy73701e72022-05-12 04:05:32 -0600127 CQSPI_DMA_DST_I_STS_DONE) && timeout--)
128 udelay(1);
129
130 if (!timeout) {
131 printf("DMA timeout\n");
132 return -ETIMEDOUT;
133 }
134
Ashok Reddy Somaf5817652022-08-24 05:38:47 -0600135 writel(readl(priv->regbase + CQSPI_DMA_DST_I_STS_REG),
136 priv->regbase + CQSPI_DMA_DST_I_STS_REG);
T Karthik Reddy73701e72022-05-12 04:05:32 -0600137 return 0;
138}
T Karthik Reddy3d71b2d2022-05-12 04:05:33 -0600139
Venkatesh Yadav Abbarapubbb87a72024-11-08 12:05:37 +0530140#if !CONFIG_IS_ENABLED(DM_GPIO)
141int cadence_qspi_flash_reset(struct udevice *dev)
T Karthik Reddy3d71b2d2022-05-12 04:05:33 -0600142{
143 /* CRP WPROT */
144 writel(0, WPROT_CRP);
145 /* GPIO Reset */
146 writel(0, RST_GPIO);
147
148 /* disable IOU write protection */
149 writel(0, WPROT_LPD_MIO);
150
151 /* set direction as output */
152 writel((readl(BOOT_MODE_DIR) | BIT(FLASH_RESET_GPIO)),
Ashok Reddy Soma8a456eb2022-11-16 07:11:54 -0700153 BOOT_MODE_DIR);
T Karthik Reddy3d71b2d2022-05-12 04:05:33 -0600154
155 /* Data output enable */
156 writel((readl(BOOT_MODE_OUT) | BIT(FLASH_RESET_GPIO)),
Ashok Reddy Soma8a456eb2022-11-16 07:11:54 -0700157 BOOT_MODE_OUT);
T Karthik Reddy3d71b2d2022-05-12 04:05:33 -0600158
159 /* IOU SLCR write enable */
160 writel(0, WPROT_PMC_MIO);
161
162 /* set MIO as GPIO */
163 writel(0x60, MIO_PIN_12);
164
165 /* Set value 1 to pin */
166 writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
167 udelay(10);
168
169 /* Disable Tri-state */
170 writel((readl(BANK0_TRI) & ~BIT(FLASH_RESET_GPIO)), BANK0_TRI);
171 udelay(1);
172
173 /* Set value 0 to pin */
174 writel((readl(BANK0_OUTPUT) & ~BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
175 udelay(10);
176
177 /* Set value 1 to pin */
178 writel((readl(BANK0_OUTPUT) | BIT(FLASH_RESET_GPIO)), BANK0_OUTPUT);
179 udelay(10);
180
181 return 0;
182}
183#endif
T Karthik Reddy3b49fbf2022-05-12 04:05:34 -0600184
185void cadence_qspi_apb_enable_linear_mode(bool enable)
186{
Simon Glassf65db342023-02-05 15:44:33 -0700187 if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE)) {
T Karthik Reddy3b49fbf2022-05-12 04:05:34 -0600188 if (enable)
189 /* ahb read mode */
190 xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI,
191 IOCTL_OSPI_MUX_SELECT,
192 PM_OSPI_MUX_SEL_LINEAR, 0, NULL);
193 else
194 /* DMA mode */
195 xilinx_pm_request(PM_IOCTL, PM_DEV_OSPI,
196 IOCTL_OSPI_MUX_SELECT,
197 PM_OSPI_MUX_SEL_DMA, 0, NULL);
198 } else {
199 if (enable)
200 writel(readl(VERSAL_AXI_MUX_SEL) |
201 VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
202 else
203 writel(readl(VERSAL_AXI_MUX_SEL) &
204 ~VERSAL_OSPI_LINEAR_MODE, VERSAL_AXI_MUX_SEL);
205 }
206}