Lines Matching +full:op +full:- +full:mode
1 // SPDX-License-Identifier: GPL-2.0-only
18 #include <linux/spi/spi-mem.h>
46 /* IO Mode definition in HISI_SFC_V3XX_CMD_CFG */
56 * The IO modes lookup table. hisi_sfc_v3xx_io_modes[(z - 1) / 2][y / 2][x / 2]
57 * stands for x-y-z mode, as described in SFDP terminology. -EIO indicates
58 * an invalid mode.
63 { HISI_SFC_V3XX_DIO, HISI_SFC_V3XX_FULL_DIO, -EIO },
64 { -EIO, -EIO, -EIO },
68 { -EIO, -EIO, -EIO },
69 { HISI_SFC_V3XX_QIO, -EIO, HISI_SFC_V3XX_FULL_QIO },
83 writel(0, host->regbase + HISI_SFC_V3XX_INT_MASK); in hisi_sfc_v3xx_disable_int()
88 writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_MASK); in hisi_sfc_v3xx_enable_int()
93 writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_CLR); in hisi_sfc_v3xx_clear_int()
105 reg = readl(host->regbase + HISI_SFC_V3XX_RAW_INT_STAT); in hisi_sfc_v3xx_handle_completion()
109 dev_err(host->dev, "fail to access protected address\n"); in hisi_sfc_v3xx_handle_completion()
110 return -EIO; in hisi_sfc_v3xx_handle_completion()
114 dev_err(host->dev, "page program operation failed\n"); in hisi_sfc_v3xx_handle_completion()
115 return -EIO; in hisi_sfc_v3xx_handle_completion()
124 dev_err(host->dev, "unsupported error occurred, status=0x%x\n", reg); in hisi_sfc_v3xx_handle_completion()
125 return -EIO; in hisi_sfc_v3xx_handle_completion()
138 return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg, in hisi_sfc_v3xx_wait_cmd_idle()
145 struct spi_mem_op *op) in hisi_sfc_v3xx_adjust_op_size() argument
147 struct spi_device *spi = mem->spi; in hisi_sfc_v3xx_adjust_op_size()
149 uintptr_t addr = (uintptr_t)op->data.buf.in; in hisi_sfc_v3xx_adjust_op_size()
152 host = spi_controller_get_devdata(spi->master); in hisi_sfc_v3xx_adjust_op_size()
154 max_byte_count = host->max_cmd_dword * 4; in hisi_sfc_v3xx_adjust_op_size()
156 if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4) in hisi_sfc_v3xx_adjust_op_size()
157 op->data.nbytes = 4 - (addr % 4); in hisi_sfc_v3xx_adjust_op_size()
158 else if (op->data.nbytes > max_byte_count) in hisi_sfc_v3xx_adjust_op_size()
159 op->data.nbytes = max_byte_count; in hisi_sfc_v3xx_adjust_op_size()
165 * The controller only supports Standard SPI mode, Duall mode and
166 * Quad mode. Double sanitize the ops here to avoid OOB access.
169 const struct spi_mem_op *op) in hisi_sfc_v3xx_supports_op() argument
171 if (op->data.buswidth > 4 || op->dummy.buswidth > 4 || in hisi_sfc_v3xx_supports_op()
172 op->addr.buswidth > 4 || op->cmd.buswidth > 4) in hisi_sfc_v3xx_supports_op()
175 return spi_mem_default_supports_op(mem, op); in hisi_sfc_v3xx_supports_op()
179 * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the
180 * DATABUF registers -so use __io{read,write}32_copy when possible. For
181 * trailing bytes, copy them byte-by-byte from the DATABUF register, as we
193 from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; in hisi_sfc_v3xx_read_databuf()
200 len -= words * 4; in hisi_sfc_v3xx_read_databuf()
230 to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; in hisi_sfc_v3xx_write_databuf()
237 len -= words * 4; in hisi_sfc_v3xx_write_databuf()
263 const struct spi_mem_op *op, in hisi_sfc_v3xx_start_bus() argument
266 int len = op->data.nbytes, buswidth_mode; in hisi_sfc_v3xx_start_bus()
269 if (op->addr.nbytes) in hisi_sfc_v3xx_start_bus()
272 if (op->data.buswidth == 0 || op->data.buswidth == 1) { in hisi_sfc_v3xx_start_bus()
277 data_idx = (op->data.buswidth - 1) / 2; in hisi_sfc_v3xx_start_bus()
278 addr_idx = op->addr.buswidth / 2; in hisi_sfc_v3xx_start_bus()
279 cmd_idx = op->cmd.buswidth / 2; in hisi_sfc_v3xx_start_bus()
286 if (op->data.dir != SPI_MEM_NO_DATA) { in hisi_sfc_v3xx_start_bus()
287 config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; in hisi_sfc_v3xx_start_bus()
291 if (op->data.dir == SPI_MEM_DATA_IN) in hisi_sfc_v3xx_start_bus()
294 config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | in hisi_sfc_v3xx_start_bus()
298 writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR); in hisi_sfc_v3xx_start_bus()
299 writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS); in hisi_sfc_v3xx_start_bus()
301 writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG); in hisi_sfc_v3xx_start_bus()
307 const struct spi_mem_op *op, in hisi_sfc_v3xx_generic_exec_op() argument
313 if (host->irq) { in hisi_sfc_v3xx_generic_exec_op()
314 host->completion = &done; in hisi_sfc_v3xx_generic_exec_op()
318 if (op->data.dir == SPI_MEM_DATA_OUT) in hisi_sfc_v3xx_generic_exec_op()
319 hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, op->data.nbytes); in hisi_sfc_v3xx_generic_exec_op()
321 ret = hisi_sfc_v3xx_start_bus(host, op, chip_select); in hisi_sfc_v3xx_generic_exec_op()
325 if (host->irq) { in hisi_sfc_v3xx_generic_exec_op()
326 ret = wait_for_completion_timeout(host->completion, in hisi_sfc_v3xx_generic_exec_op()
329 ret = -ETIMEDOUT; in hisi_sfc_v3xx_generic_exec_op()
334 host->completion = NULL; in hisi_sfc_v3xx_generic_exec_op()
339 return -EIO; in hisi_sfc_v3xx_generic_exec_op()
341 if (op->data.dir == SPI_MEM_DATA_IN) in hisi_sfc_v3xx_generic_exec_op()
342 hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, op->data.nbytes); in hisi_sfc_v3xx_generic_exec_op()
348 const struct spi_mem_op *op) in hisi_sfc_v3xx_exec_op() argument
351 struct spi_device *spi = mem->spi; in hisi_sfc_v3xx_exec_op()
352 u8 chip_select = spi->chip_select; in hisi_sfc_v3xx_exec_op()
354 host = spi_controller_get_devdata(spi->master); in hisi_sfc_v3xx_exec_op()
356 return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select); in hisi_sfc_v3xx_exec_op()
371 complete(host->completion); in hisi_sfc_v3xx_isr()
416 struct device *dev = &pdev->dev; in hisi_sfc_v3xx_probe()
422 ctlr = spi_alloc_master(&pdev->dev, sizeof(*host)); in hisi_sfc_v3xx_probe()
424 return -ENOMEM; in hisi_sfc_v3xx_probe()
426 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | in hisi_sfc_v3xx_probe()
429 ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits; in hisi_sfc_v3xx_probe()
432 host->dev = dev; in hisi_sfc_v3xx_probe()
436 host->regbase = devm_platform_ioremap_resource(pdev, 0); in hisi_sfc_v3xx_probe()
437 if (IS_ERR(host->regbase)) { in hisi_sfc_v3xx_probe()
438 ret = PTR_ERR(host->regbase); in hisi_sfc_v3xx_probe()
442 host->irq = platform_get_irq_optional(pdev, 0); in hisi_sfc_v3xx_probe()
443 if (host->irq == -EPROBE_DEFER) { in hisi_sfc_v3xx_probe()
444 ret = -EPROBE_DEFER; in hisi_sfc_v3xx_probe()
450 if (host->irq > 0) { in hisi_sfc_v3xx_probe()
451 ret = devm_request_irq(dev, host->irq, hisi_sfc_v3xx_isr, 0, in hisi_sfc_v3xx_probe()
452 "hisi-sfc-v3xx", host); in hisi_sfc_v3xx_probe()
455 dev_err(dev, "failed to request irq%d, ret = %d\n", host->irq, ret); in hisi_sfc_v3xx_probe()
456 host->irq = 0; in hisi_sfc_v3xx_probe()
459 host->irq = 0; in hisi_sfc_v3xx_probe()
462 ctlr->bus_num = -1; in hisi_sfc_v3xx_probe()
463 ctlr->num_chipselect = 1; in hisi_sfc_v3xx_probe()
464 ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops; in hisi_sfc_v3xx_probe()
466 version = readl(host->regbase + HISI_SFC_V3XX_VERSION); in hisi_sfc_v3xx_probe()
470 host->max_cmd_dword = 64; in hisi_sfc_v3xx_probe()
473 host->max_cmd_dword = 16; in hisi_sfc_v3xx_probe()
481 dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n", in hisi_sfc_v3xx_probe()
482 version, host->irq ? "irq" : "polling"); in hisi_sfc_v3xx_probe()
501 .name = "hisi-sfc-v3xx",