Lines Matching +full:rtl9301 +full:- +full:snand
1 // SPDX-License-Identifier: GPL-2.0-only
4 #include <linux/dma-mapping.h>
10 #include <linux/spi/spi-mem.h>
29 #define CMR_LEN(len) ((len) - 1)
40 struct rtl_snand *snand = data; in rtl_snand_irq() local
43 regmap_read(snand->regmap, SNAFSR, &val); in rtl_snand_irq()
47 regmap_write(snand->regmap, SNAFDIR, SNAFDIR_DMA_IP); in rtl_snand_irq()
48 complete(&snand->comp); in rtl_snand_irq()
58 if (op->cmd.nbytes != 1 || op->cmd.buswidth != 1) in rtl_snand_supports_op()
63 static void rtl_snand_set_cs(struct rtl_snand *snand, int cs, bool active) in rtl_snand_set_cs() argument
72 regmap_write(snand->regmap, SNAFCCR, val); in rtl_snand_set_cs()
75 static int rtl_snand_wait_ready(struct rtl_snand *snand) in rtl_snand_wait_ready() argument
79 return regmap_read_poll_timeout(snand->regmap, SNAFSR, val, !(val & SNAFSR_NFCOS), in rtl_snand_wait_ready()
83 static int rtl_snand_xfer_head(struct rtl_snand *snand, int cs, const struct spi_mem_op *op) in rtl_snand_xfer_head() argument
88 rtl_snand_set_cs(snand, cs, true); in rtl_snand_xfer_head()
90 val = op->cmd.opcode << 24; in rtl_snand_xfer_head()
92 if (op->addr.nbytes && op->addr.buswidth == 1) { in rtl_snand_xfer_head()
93 val |= op->addr.val << ((3 - op->addr.nbytes) * 8); in rtl_snand_xfer_head()
94 len += op->addr.nbytes; in rtl_snand_xfer_head()
97 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer_head()
101 ret = regmap_write(snand->regmap, SNAFWCMR, CMR_LEN(len)); in rtl_snand_xfer_head()
105 ret = regmap_write(snand->regmap, SNAFWDR, val); in rtl_snand_xfer_head()
109 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer_head()
113 if (op->addr.buswidth > 1) { in rtl_snand_xfer_head()
114 val = op->addr.val << ((3 - op->addr.nbytes) * 8); in rtl_snand_xfer_head()
115 len = op->addr.nbytes; in rtl_snand_xfer_head()
117 ret = regmap_write(snand->regmap, SNAFWCMR, in rtl_snand_xfer_head()
118 CMR_WID(op->addr.buswidth) | CMR_LEN(len)); in rtl_snand_xfer_head()
122 ret = regmap_write(snand->regmap, SNAFWDR, val); in rtl_snand_xfer_head()
126 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer_head()
131 if (op->dummy.nbytes) { in rtl_snand_xfer_head()
134 ret = regmap_write(snand->regmap, SNAFWCMR, in rtl_snand_xfer_head()
135 CMR_WID(op->dummy.buswidth) | CMR_LEN(op->dummy.nbytes)); in rtl_snand_xfer_head()
139 ret = regmap_write(snand->regmap, SNAFWDR, val); in rtl_snand_xfer_head()
143 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer_head()
151 static void rtl_snand_xfer_tail(struct rtl_snand *snand, int cs) in rtl_snand_xfer_tail() argument
153 rtl_snand_set_cs(snand, cs, false); in rtl_snand_xfer_tail()
156 static int rtl_snand_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_op *op) in rtl_snand_xfer() argument
162 ret = rtl_snand_xfer_head(snand, cs, op); in rtl_snand_xfer()
166 if (op->data.dir == SPI_MEM_DATA_IN) { in rtl_snand_xfer()
168 len = op->data.nbytes; in rtl_snand_xfer()
171 nbytes = len - pos; in rtl_snand_xfer()
175 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer()
179 ret = regmap_write(snand->regmap, SNAFRCMR, in rtl_snand_xfer()
180 CMR_WID(op->data.buswidth) | CMR_LEN(nbytes)); in rtl_snand_xfer()
184 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer()
188 ret = regmap_read(snand->regmap, SNAFRDR, &val); in rtl_snand_xfer()
192 memcpy(op->data.buf.in + pos, &val, nbytes); in rtl_snand_xfer()
196 } else if (op->data.dir == SPI_MEM_DATA_OUT) { in rtl_snand_xfer()
198 len = op->data.nbytes; in rtl_snand_xfer()
201 nbytes = len - pos; in rtl_snand_xfer()
205 memcpy(&val, op->data.buf.out + pos, nbytes); in rtl_snand_xfer()
209 ret = regmap_write(snand->regmap, SNAFWCMR, CMR_LEN(nbytes)); in rtl_snand_xfer()
213 ret = regmap_write(snand->regmap, SNAFWDR, val); in rtl_snand_xfer()
217 ret = rtl_snand_wait_ready(snand); in rtl_snand_xfer()
224 rtl_snand_xfer_tail(snand, cs); in rtl_snand_xfer()
227 dev_err(snand->dev, "transfer failed %d\n", ret); in rtl_snand_xfer()
232 static int rtl_snand_dma_xfer(struct rtl_snand *snand, int cs, const struct spi_mem_op *op) in rtl_snand_dma_xfer() argument
240 ret = rtl_snand_xfer_head(snand, cs, op); in rtl_snand_dma_xfer()
244 if (op->data.dir == SPI_MEM_DATA_IN) { in rtl_snand_dma_xfer()
248 } else if (op->data.dir == SPI_MEM_DATA_OUT) { in rtl_snand_dma_xfer()
253 ret = -EOPNOTSUPP; in rtl_snand_dma_xfer()
257 buf_dma = dma_map_single(snand->dev, op->data.buf.in, op->data.nbytes, dir); in rtl_snand_dma_xfer()
258 ret = dma_mapping_error(snand->dev, buf_dma); in rtl_snand_dma_xfer()
262 ret = regmap_write(snand->regmap, SNAFDIR, SNAFDIR_DMA_IP); in rtl_snand_dma_xfer()
266 ret = regmap_update_bits(snand->regmap, SNAFCFR, SNAFCFR_DMA_IE, SNAFCFR_DMA_IE); in rtl_snand_dma_xfer()
271 len = op->data.nbytes; in rtl_snand_dma_xfer()
274 nbytes = len - pos; in rtl_snand_dma_xfer()
278 reinit_completion(&snand->comp); in rtl_snand_dma_xfer()
280 ret = regmap_write(snand->regmap, SNAFDRSAR, buf_dma + pos); in rtl_snand_dma_xfer()
286 ret = regmap_write(snand->regmap, SNAFDLR, in rtl_snand_dma_xfer()
287 CMR_WID(op->data.buswidth) | nbytes); in rtl_snand_dma_xfer()
291 ret = regmap_write(snand->regmap, SNAFDTR, trig); in rtl_snand_dma_xfer()
295 if (!wait_for_completion_timeout(&snand->comp, usecs_to_jiffies(20000))) in rtl_snand_dma_xfer()
296 ret = -ETIMEDOUT; in rtl_snand_dma_xfer()
303 regmap_update_bits(snand->regmap, SNAFCFR, SNAFCFR_DMA_IE, 0); in rtl_snand_dma_xfer()
305 dma_unmap_single(snand->dev, buf_dma, op->data.nbytes, dir); in rtl_snand_dma_xfer()
307 rtl_snand_xfer_tail(snand, cs); in rtl_snand_dma_xfer()
310 dev_err(snand->dev, "transfer failed %d\n", ret); in rtl_snand_dma_xfer()
317 switch (op->data.dir) { in rtl_snand_dma_op()
320 return op->data.nbytes > 32; in rtl_snand_dma_op()
328 struct rtl_snand *snand = spi_controller_get_devdata(mem->spi->controller); in rtl_snand_exec_op() local
329 int cs = spi_get_chipselect(mem->spi, 0); in rtl_snand_exec_op()
331 dev_dbg(snand->dev, "cs %d op cmd %02x %d:%d, dummy %d:%d, addr %08llx@%d:%d, data %d:%d\n", in rtl_snand_exec_op()
332 cs, op->cmd.opcode, in rtl_snand_exec_op()
333 op->cmd.buswidth, op->cmd.nbytes, op->dummy.buswidth, in rtl_snand_exec_op()
334 op->dummy.nbytes, op->addr.val, op->addr.buswidth, in rtl_snand_exec_op()
335 op->addr.nbytes, op->data.buswidth, op->data.nbytes); in rtl_snand_exec_op()
338 return rtl_snand_dma_xfer(snand, cs, op); in rtl_snand_exec_op()
340 return rtl_snand_xfer(snand, cs, op); in rtl_snand_exec_op()
349 { .compatible = "realtek,rtl9301-snand" },
350 { .compatible = "realtek,rtl9302b-snand" },
351 { .compatible = "realtek,rtl9302c-snand" },
352 { .compatible = "realtek,rtl9303-snand" },
359 struct rtl_snand *snand; in rtl_snand_probe() local
360 struct device *dev = &pdev->dev; in rtl_snand_probe()
371 ctrl = devm_spi_alloc_host(dev, sizeof(*snand)); in rtl_snand_probe()
373 return -ENOMEM; in rtl_snand_probe()
375 snand = spi_controller_get_devdata(ctrl); in rtl_snand_probe()
376 snand->dev = dev; in rtl_snand_probe()
382 snand->regmap = devm_regmap_init_mmio(dev, base, &rc); in rtl_snand_probe()
383 if (IS_ERR(snand->regmap)) in rtl_snand_probe()
384 return PTR_ERR(snand->regmap); in rtl_snand_probe()
386 init_completion(&snand->comp); in rtl_snand_probe()
392 ret = dma_set_mask(snand->dev, DMA_BIT_MASK(32)); in rtl_snand_probe()
396 ret = devm_request_irq(dev, irq, rtl_snand_irq, 0, "rtl-snand", snand); in rtl_snand_probe()
400 ctrl->num_chipselect = 2; in rtl_snand_probe()
401 ctrl->mem_ops = &rtl_snand_mem_ops; in rtl_snand_probe()
402 ctrl->bits_per_word_mask = SPI_BPW_MASK(8); in rtl_snand_probe()
403 ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_DUAL | SPI_TX_QUAD; in rtl_snand_probe()
404 device_set_node(&ctrl->dev, dev_fwnode(dev)); in rtl_snand_probe()
411 .name = "realtek-rtl-snand",
418 MODULE_DESCRIPTION("Realtek SPI-NAND Flash Controller Driver");