Lines Matching +full:mem +full:- +full:base
1 // SPDX-License-Identifier: GPL-2.0-only
16 #include <linux/spi/spi-mem.h>
111 void __iomem *base; member
119 return (op->dummy.nbytes * 8) / op->dummy.buswidth; in f_ospi_get_dummy_cycle()
125 ospi->base + OSPI_IRQ); in f_ospi_clear_irq()
132 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
134 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_enable_irq_status()
141 val = readl(ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
143 writel(val, ospi->base + OSPI_IRQ_STAT_EN); in f_ospi_disable_irq_status()
150 val = readl(ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
152 writel(val, ospi->base + OSPI_IRQ_SIG_EN); in f_ospi_disable_irq_output()
160 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
162 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_prepare_config()
168 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_prepare_config()
178 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
180 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_unprepare_config()
183 return readl_poll_timeout(ospi->base + OSPI_STAT, in f_ospi_unprepare_config()
190 long rate_hz = clk_get_rate(ospi->clk); in f_ospi_config_clk()
196 dev_warn(ospi->dev, "Device frequency too large: %d\n", in f_ospi_config_clk()
209 dev_warn(ospi->dev, "Device frequency too small: %d\n", in f_ospi_config_clk()
220 val = readl(ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
226 writel(val, ospi->base + OSPI_CLK_CTL); in f_ospi_config_clk()
253 dev_err(ospi->dev, "Invalid buswidth: %d\n", width); in f_ospi_get_mode()
261 struct spi_mem *mem, in f_ospi_config_indir_protocol() argument
264 struct spi_device *spi = mem->spi; in f_ospi_config_indir_protocol()
270 writel(BIT(spi_get_chipselect(spi, 0)), ospi->base + OSPI_SSEL); in f_ospi_config_indir_protocol()
272 mode = f_ospi_get_mode(ospi, op->cmd.buswidth, 1); in f_ospi_config_indir_protocol()
275 mode = f_ospi_get_mode(ospi, op->addr.buswidth, op->addr.nbytes); in f_ospi_config_indir_protocol()
278 mode = f_ospi_get_mode(ospi, op->data.buswidth, op->data.nbytes); in f_ospi_config_indir_protocol()
286 if (spi->mode & SPI_LSB_FIRST) in f_ospi_config_indir_protocol()
290 if (spi->mode & SPI_CPHA) in f_ospi_config_indir_protocol()
294 switch (op->data.nbytes & 0x3) { in f_ospi_config_indir_protocol()
301 val = OSPI_DAT_SIZE_EN | (op->data.nbytes - 1); in f_ospi_config_indir_protocol()
305 val = OSPI_DAT_SIZE_EN | (op->data.nbytes - 1); in f_ospi_config_indir_protocol()
310 switch (op->data.dir) { in f_ospi_config_indir_protocol()
324 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_config_indir_protocol()
328 prot |= FIELD_PREP(OSPI_PROT_ADDR_SIZE_MASK, op->addr.nbytes); in f_ospi_config_indir_protocol()
331 writel(prot, ospi->base + OSPI_PROT_CTL_INDIR); in f_ospi_config_indir_protocol()
332 writel(val, ospi->base + OSPI_DAT_SIZE_INDIR); in f_ospi_config_indir_protocol()
335 static int f_ospi_indir_prepare_op(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_prepare_op() argument
338 struct spi_device *spi = mem->spi; in f_ospi_indir_prepare_op()
346 f_ospi_config_clk(ospi, spi->max_speed_hz); in f_ospi_indir_prepare_op()
348 f_ospi_config_indir_protocol(ospi, mem, op); in f_ospi_indir_prepare_op()
350 writel(f_ospi_get_dummy_cycle(op), ospi->base + OSPI_DMY_INDIR); in f_ospi_indir_prepare_op()
351 writel(op->addr.val, ospi->base + OSPI_ADDR); in f_ospi_indir_prepare_op()
352 writel(op->cmd.opcode, ospi->base + OSPI_CMD_IDX_INDIR); in f_ospi_indir_prepare_op()
356 switch (op->data.dir) { in f_ospi_indir_prepare_op()
370 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_indir_prepare_op()
383 writel(OSPI_TRANS_CTL_START_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_start_xfer()
389 writel(OSPI_TRANS_CTL_STOP_REQ, ospi->base + OSPI_TRANS_CTL); in f_ospi_indir_stop_xfer()
396 return readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_wait_xfer_complete()
401 static int f_ospi_indir_read(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_read() argument
404 u8 *buf = op->data.buf.in; in f_ospi_indir_read()
408 mutex_lock(&ospi->mlock); in f_ospi_indir_read()
410 /* E1-2: Prepare transfer operation */ in f_ospi_indir_read()
411 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_read()
417 /* E3-4: Wait for ready and read data */ in f_ospi_indir_read()
418 for (i = 0; i < op->data.nbytes; i++) { in f_ospi_indir_read()
419 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_read()
425 buf[i] = readl(ospi->base + OSPI_DAT) & 0xFF; in f_ospi_indir_read()
428 /* E5-6: Stop transfer if data size is nothing */ in f_ospi_indir_read()
429 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_read()
432 /* E7-8: Wait for completion and clear */ in f_ospi_indir_read()
437 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_read()
440 if (readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN) in f_ospi_indir_read()
443 /* E10-11: Reset and check read fifo */ in f_ospi_indir_read()
444 writel(OSPI_SWRST_INDIR_READ_FIFO, ospi->base + OSPI_SWRST); in f_ospi_indir_read()
446 ret = readl_poll_timeout(ospi->base + OSPI_SWRST, val, in f_ospi_indir_read()
450 mutex_unlock(&ospi->mlock); in f_ospi_indir_read()
455 static int f_ospi_indir_write(struct f_ospi *ospi, struct spi_mem *mem, in f_ospi_indir_write() argument
458 u8 *buf = (u8 *)op->data.buf.out; in f_ospi_indir_write()
462 mutex_lock(&ospi->mlock); in f_ospi_indir_write()
464 /* F1-3: Prepare transfer operation */ in f_ospi_indir_write()
465 ret = f_ospi_indir_prepare_op(ospi, mem, op); in f_ospi_indir_write()
471 if (!(readl(ospi->base + OSPI_PROT_CTL_INDIR) & OSPI_PROT_DATA_EN)) in f_ospi_indir_write()
474 /* F4-5: Wait for buffer ready and write data */ in f_ospi_indir_write()
475 for (i = 0; i < op->data.nbytes; i++) { in f_ospi_indir_write()
476 ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val, in f_ospi_indir_write()
482 writel(buf[i], ospi->base + OSPI_DAT); in f_ospi_indir_write()
485 /* F6-7: Stop transfer if data size is nothing */ in f_ospi_indir_write()
486 if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)) in f_ospi_indir_write()
490 /* F8-9: Wait for completion and clear */ in f_ospi_indir_write()
495 writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ); in f_ospi_indir_write()
497 mutex_unlock(&ospi->mlock); in f_ospi_indir_write()
502 static int f_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) in f_ospi_exec_op() argument
504 struct f_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); in f_ospi_exec_op()
507 switch (op->data.dir) { in f_ospi_exec_op()
509 err = f_ospi_indir_read(ospi, mem, op); in f_ospi_exec_op()
515 err = f_ospi_indir_write(ospi, mem, op); in f_ospi_exec_op()
519 dev_warn(ospi->dev, "Unsupported direction"); in f_ospi_exec_op()
520 err = -EOPNOTSUPP; in f_ospi_exec_op()
526 static bool f_ospi_supports_op_width(struct spi_mem *mem, in f_ospi_supports_op_width() argument
530 u8 width_op[] = { op->cmd.buswidth, op->addr.buswidth, in f_ospi_supports_op_width()
531 op->dummy.buswidth, op->data.buswidth }; in f_ospi_supports_op_width()
552 static bool f_ospi_supports_op(struct spi_mem *mem, in f_ospi_supports_op() argument
558 if (op->addr.nbytes > 4) in f_ospi_supports_op()
561 if (!f_ospi_supports_op_width(mem, op)) in f_ospi_supports_op()
564 return spi_mem_default_supports_op(mem, op); in f_ospi_supports_op()
567 static int f_ospi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) in f_ospi_adjust_op_size() argument
569 op->data.nbytes = min_t(int, op->data.nbytes, OSPI_DAT_SIZE_MAX); in f_ospi_adjust_op_size()
589 writel(OSPI_ACC_MODE_BOOT_DISABLE, ospi->base + OSPI_ACC_MODE); in f_ospi_init()
604 struct device *dev = &pdev->dev; in f_ospi_probe()
611 return -ENOMEM; in f_ospi_probe()
613 ctlr->mode_bits = SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL in f_ospi_probe()
616 ctlr->mem_ops = &f_ospi_mem_ops; in f_ospi_probe()
617 ctlr->bus_num = -1; in f_ospi_probe()
618 of_property_read_u32(dev->of_node, "num-cs", &num_cs); in f_ospi_probe()
620 dev_err(dev, "num-cs too large: %d\n", num_cs); in f_ospi_probe()
621 return -ENOMEM; in f_ospi_probe()
623 ctlr->num_chipselect = num_cs; in f_ospi_probe()
624 ctlr->dev.of_node = dev->of_node; in f_ospi_probe()
627 ospi->dev = dev; in f_ospi_probe()
631 ospi->base = devm_platform_ioremap_resource(pdev, 0); in f_ospi_probe()
632 if (IS_ERR(ospi->base)) { in f_ospi_probe()
633 ret = PTR_ERR(ospi->base); in f_ospi_probe()
637 ospi->clk = devm_clk_get_enabled(dev, NULL); in f_ospi_probe()
638 if (IS_ERR(ospi->clk)) { in f_ospi_probe()
639 ret = PTR_ERR(ospi->clk); in f_ospi_probe()
643 mutex_init(&ospi->mlock); in f_ospi_probe()
656 mutex_destroy(&ospi->mlock); in f_ospi_probe()
668 mutex_destroy(&ospi->mlock); in f_ospi_remove()
672 { .compatible = "socionext,f-ospi" },
679 .name = "socionext,f-ospi",