Lines Matching +full:op +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0-only
18 #include <linux/spi/spi-mem.h>
48 /* IO Mode definition in HISI_SFC_V3XX_CMD_CFG */
58 * The IO modes lookup table. hisi_sfc_v3xx_io_modes[(z - 1) / 2][y / 2][x / 2]
59 * stands for x-y-z mode, as described in SFDP terminology. -EIO indicates
60 * an invalid mode.
65 { HISI_SFC_V3XX_DIO, HISI_SFC_V3XX_FULL_DIO, -EIO },
66 { -EIO, -EIO, -EIO },
70 { -EIO, -EIO, -EIO },
71 { HISI_SFC_V3XX_QIO, -EIO, HISI_SFC_V3XX_FULL_QIO },
86 writel(0, host->regbase + HISI_SFC_V3XX_INT_MASK); in hisi_sfc_v3xx_disable_int()
91 writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_MASK); in hisi_sfc_v3xx_enable_int()
96 writel(HISI_SFC_V3XX_INT_MASK_ALL, host->regbase + HISI_SFC_V3XX_INT_CLR); in hisi_sfc_v3xx_clear_int()
108 reg = readl(host->regbase + HISI_SFC_V3XX_RAW_INT_STAT); in hisi_sfc_v3xx_handle_completion()
112 dev_err(host->dev, "fail to access protected address\n"); in hisi_sfc_v3xx_handle_completion()
113 return -EIO; in hisi_sfc_v3xx_handle_completion()
117 dev_err(host->dev, "page program operation failed\n"); in hisi_sfc_v3xx_handle_completion()
118 return -EIO; in hisi_sfc_v3xx_handle_completion()
127 dev_err(host->dev, "unsupported error occurred, status=0x%x\n", reg); in hisi_sfc_v3xx_handle_completion()
128 return -EIO; in hisi_sfc_v3xx_handle_completion()
141 return readl_poll_timeout(host->regbase + HISI_SFC_V3XX_CMD_CFG, reg, in hisi_sfc_v3xx_wait_cmd_idle()
148 struct spi_mem_op *op) in hisi_sfc_v3xx_adjust_op_size() argument
150 struct spi_device *spi = mem->spi; in hisi_sfc_v3xx_adjust_op_size()
152 uintptr_t addr = (uintptr_t)op->data.buf.in; in hisi_sfc_v3xx_adjust_op_size()
155 host = spi_controller_get_devdata(spi->controller); in hisi_sfc_v3xx_adjust_op_size()
157 max_byte_count = host->max_cmd_dword * 4; in hisi_sfc_v3xx_adjust_op_size()
159 if (!IS_ALIGNED(addr, 4) && op->data.nbytes >= 4) in hisi_sfc_v3xx_adjust_op_size()
160 op->data.nbytes = 4 - (addr % 4); in hisi_sfc_v3xx_adjust_op_size()
161 else if (op->data.nbytes > max_byte_count) in hisi_sfc_v3xx_adjust_op_size()
162 op->data.nbytes = max_byte_count; in hisi_sfc_v3xx_adjust_op_size()
168 * The controller only supports Standard SPI mode, Dual mode and
169 * Quad mode. Double sanitize the ops here to avoid OOB access.
172 const struct spi_mem_op *op) in hisi_sfc_v3xx_supports_op() argument
174 struct spi_device *spi = mem->spi; in hisi_sfc_v3xx_supports_op()
177 host = spi_controller_get_devdata(spi->controller); in hisi_sfc_v3xx_supports_op()
179 if (op->data.buswidth > 4 || op->dummy.buswidth > 4 || in hisi_sfc_v3xx_supports_op()
180 op->addr.buswidth > 4 || op->cmd.buswidth > 4) in hisi_sfc_v3xx_supports_op()
183 if (op->addr.nbytes != host->address_mode && op->addr.nbytes) in hisi_sfc_v3xx_supports_op()
186 return spi_mem_default_supports_op(mem, op); in hisi_sfc_v3xx_supports_op()
190 * memcpy_{to,from}io doesn't gurantee 32b accesses - which we require for the
191 * DATABUF registers -so use __io{read,write}32_copy when possible. For
192 * trailing bytes, copy them byte-by-byte from the DATABUF register, as we
204 from = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; in hisi_sfc_v3xx_read_databuf()
211 len -= words * 4; in hisi_sfc_v3xx_read_databuf()
241 to = host->regbase + HISI_SFC_V3XX_CMD_DATABUF0; in hisi_sfc_v3xx_write_databuf()
248 len -= words * 4; in hisi_sfc_v3xx_write_databuf()
274 const struct spi_mem_op *op, in hisi_sfc_v3xx_start_bus() argument
277 int len = op->data.nbytes, buswidth_mode; in hisi_sfc_v3xx_start_bus()
280 if (op->addr.nbytes) in hisi_sfc_v3xx_start_bus()
283 if (op->data.buswidth == 0 || op->data.buswidth == 1) { in hisi_sfc_v3xx_start_bus()
288 data_idx = (op->data.buswidth - 1) / 2; in hisi_sfc_v3xx_start_bus()
289 addr_idx = op->addr.buswidth / 2; in hisi_sfc_v3xx_start_bus()
290 cmd_idx = op->cmd.buswidth / 2; in hisi_sfc_v3xx_start_bus()
297 if (op->data.dir != SPI_MEM_NO_DATA) { in hisi_sfc_v3xx_start_bus()
298 config |= (len - 1) << HISI_SFC_V3XX_CMD_CFG_DATA_CNT_OFF; in hisi_sfc_v3xx_start_bus()
302 if (op->data.dir == SPI_MEM_DATA_IN) in hisi_sfc_v3xx_start_bus()
305 config |= op->dummy.nbytes << HISI_SFC_V3XX_CMD_CFG_DUMMY_CNT_OFF | in hisi_sfc_v3xx_start_bus()
309 writel(op->addr.val, host->regbase + HISI_SFC_V3XX_CMD_ADDR); in hisi_sfc_v3xx_start_bus()
310 writel(op->cmd.opcode, host->regbase + HISI_SFC_V3XX_CMD_INS); in hisi_sfc_v3xx_start_bus()
312 writel(config, host->regbase + HISI_SFC_V3XX_CMD_CFG); in hisi_sfc_v3xx_start_bus()
318 const struct spi_mem_op *op, in hisi_sfc_v3xx_generic_exec_op() argument
324 if (host->irq) { in hisi_sfc_v3xx_generic_exec_op()
325 host->completion = &done; in hisi_sfc_v3xx_generic_exec_op()
329 if (op->data.dir == SPI_MEM_DATA_OUT) in hisi_sfc_v3xx_generic_exec_op()
330 hisi_sfc_v3xx_write_databuf(host, op->data.buf.out, op->data.nbytes); in hisi_sfc_v3xx_generic_exec_op()
332 ret = hisi_sfc_v3xx_start_bus(host, op, chip_select); in hisi_sfc_v3xx_generic_exec_op()
336 if (host->irq) { in hisi_sfc_v3xx_generic_exec_op()
337 ret = wait_for_completion_timeout(host->completion, in hisi_sfc_v3xx_generic_exec_op()
340 ret = -ETIMEDOUT; in hisi_sfc_v3xx_generic_exec_op()
345 synchronize_irq(host->irq); in hisi_sfc_v3xx_generic_exec_op()
346 host->completion = NULL; in hisi_sfc_v3xx_generic_exec_op()
351 return -EIO; in hisi_sfc_v3xx_generic_exec_op()
353 if (op->data.dir == SPI_MEM_DATA_IN) in hisi_sfc_v3xx_generic_exec_op()
354 hisi_sfc_v3xx_read_databuf(host, op->data.buf.in, op->data.nbytes); in hisi_sfc_v3xx_generic_exec_op()
360 const struct spi_mem_op *op) in hisi_sfc_v3xx_exec_op() argument
363 struct spi_device *spi = mem->spi; in hisi_sfc_v3xx_exec_op()
366 host = spi_controller_get_devdata(spi->controller); in hisi_sfc_v3xx_exec_op()
368 return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select); in hisi_sfc_v3xx_exec_op()
382 reg = readl(host->regbase + HISI_SFC_V3XX_INT_STAT); in hisi_sfc_v3xx_isr()
388 complete(host->completion); in hisi_sfc_v3xx_isr()
433 struct device *dev = &pdev->dev; in hisi_sfc_v3xx_probe()
439 ctlr = spi_alloc_host(&pdev->dev, sizeof(*host)); in hisi_sfc_v3xx_probe()
441 return -ENOMEM; in hisi_sfc_v3xx_probe()
443 ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | in hisi_sfc_v3xx_probe()
446 ctlr->buswidth_override_bits = hisi_sfc_v3xx_buswidth_override_bits; in hisi_sfc_v3xx_probe()
449 host->dev = dev; in hisi_sfc_v3xx_probe()
453 host->regbase = devm_platform_ioremap_resource(pdev, 0); in hisi_sfc_v3xx_probe()
454 if (IS_ERR(host->regbase)) { in hisi_sfc_v3xx_probe()
455 ret = PTR_ERR(host->regbase); in hisi_sfc_v3xx_probe()
459 host->irq = platform_get_irq_optional(pdev, 0); in hisi_sfc_v3xx_probe()
460 if (host->irq == -EPROBE_DEFER) { in hisi_sfc_v3xx_probe()
461 ret = -EPROBE_DEFER; in hisi_sfc_v3xx_probe()
467 if (host->irq > 0) { in hisi_sfc_v3xx_probe()
468 ret = devm_request_irq(dev, host->irq, hisi_sfc_v3xx_isr, 0, in hisi_sfc_v3xx_probe()
469 "hisi-sfc-v3xx", host); in hisi_sfc_v3xx_probe()
472 dev_err(dev, "failed to request irq%d, ret = %d\n", host->irq, ret); in hisi_sfc_v3xx_probe()
473 host->irq = 0; in hisi_sfc_v3xx_probe()
476 host->irq = 0; in hisi_sfc_v3xx_probe()
479 ctlr->bus_num = -1; in hisi_sfc_v3xx_probe()
480 ctlr->num_chipselect = 1; in hisi_sfc_v3xx_probe()
481 ctlr->mem_ops = &hisi_sfc_v3xx_mem_ops; in hisi_sfc_v3xx_probe()
484 * The address mode of the controller is either 3 or 4, in hisi_sfc_v3xx_probe()
485 * which is indicated by the address mode bit in in hisi_sfc_v3xx_probe()
489 glb_config = readl(host->regbase + HISI_SFC_V3XX_GLB_CFG); in hisi_sfc_v3xx_probe()
491 host->address_mode = 4; in hisi_sfc_v3xx_probe()
493 host->address_mode = 3; in hisi_sfc_v3xx_probe()
495 version = readl(host->regbase + HISI_SFC_V3XX_VERSION); in hisi_sfc_v3xx_probe()
498 host->max_cmd_dword = 64; in hisi_sfc_v3xx_probe()
500 host->max_cmd_dword = 16; in hisi_sfc_v3xx_probe()
506 dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n", in hisi_sfc_v3xx_probe()
507 version, host->irq ? "irq" : "polling"); in hisi_sfc_v3xx_probe()
524 .name = "hisi-sfc-v3xx",