Lines Matching +full:jz4780 +full:- +full:dma
1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2017-2021 Artur Rojek <contact@artur-rojek.eu>
5 * Copyright (c) 2017-2021 Paul Cercueil <paul@crapouillou.net>
12 #include <linux/dma-mapping.h>
76 return regmap_read_poll_timeout(priv->map, REG_SSISR, val, in spi_ingenic_wait()
83 struct ingenic_spi *priv = spi_controller_get_devdata(spi->controller); in spi_ingenic_set_cs()
86 regmap_clear_bits(priv->map, REG_SSICR1, REG_SSICR1_UNFIN); in spi_ingenic_set_cs()
87 regmap_clear_bits(priv->map, REG_SSISR, in spi_ingenic_set_cs()
92 regmap_set_bits(priv->map, REG_SSICR1, REG_SSICR1_UNFIN); in spi_ingenic_set_cs()
95 regmap_set_bits(priv->map, REG_SSICR0, in spi_ingenic_set_cs()
103 unsigned long clk_hz = clk_get_rate(priv->clk); in spi_ingenic_prepare_transfer()
104 u32 cdiv, speed_hz = xfer->speed_hz ?: spi->max_speed_hz, in spi_ingenic_prepare_transfer()
105 bits_per_word = xfer->bits_per_word ?: spi->bits_per_word; in spi_ingenic_prepare_transfer()
108 cdiv = clamp(cdiv, 1u, 0x100u) - 1; in spi_ingenic_prepare_transfer()
110 regmap_write(priv->map, REG_SSIGR, cdiv); in spi_ingenic_prepare_transfer()
112 regmap_field_write(priv->flen_field, bits_per_word - 2); in spi_ingenic_prepare_transfer()
128 .src_addr = priv->mem_res->start + REG_SSIDR, in spi_ingenic_prepare_dma()
129 .dst_addr = priv->mem_res->start + REG_SSIDR, in spi_ingenic_prepare_dma()
153 desc = dmaengine_prep_slave_sg(chan, sg->sgl, sg->nents, dir, in spi_ingenic_prepare_dma()
156 return ERR_PTR(-ENOMEM); in spi_ingenic_prepare_dma()
159 desc->callback = spi_ingenic_finalize_transfer; in spi_ingenic_prepare_dma()
160 desc->callback_param = ctlr; in spi_ingenic_prepare_dma()
179 rx_desc = spi_ingenic_prepare_dma(ctlr, ctlr->dma_rx, in spi_ingenic_dma_tx()
180 &xfer->rx_sg, DMA_DEV_TO_MEM, bits); in spi_ingenic_dma_tx()
184 tx_desc = spi_ingenic_prepare_dma(ctlr, ctlr->dma_tx, in spi_ingenic_dma_tx()
185 &xfer->tx_sg, DMA_MEM_TO_DEV, bits); in spi_ingenic_dma_tx()
187 dmaengine_terminate_async(ctlr->dma_rx); in spi_ingenic_dma_tx()
192 dma_async_issue_pending(ctlr->dma_rx); in spi_ingenic_dma_tx()
193 dma_async_issue_pending(ctlr->dma_tx); in spi_ingenic_dma_tx()
202 unsigned int count = xfer->len / (x / 8); \
204 const u##x *tx_buf = xfer->tx_buf; \
205 u##x *rx_buf = xfer->rx_buf; \
213 regmap_write(priv->map, REG_SSIDR, val); \
221 regmap_read(priv->map, REG_SSIDR, &val); \
225 if (i < count - prefill) { \
228 regmap_write(priv->map, REG_SSIDR, val); \
244 unsigned int bits = xfer->bits_per_word ?: spi->bits_per_word; in spi_ingenic_transfer_one()
245 bool can_dma = ctlr->can_dma && ctlr->can_dma(ctlr, spi, xfer); in spi_ingenic_transfer_one()
249 if (ctlr->cur_msg_mapped && can_dma) in spi_ingenic_transfer_one()
265 struct spi_device *spi = message->spi; in spi_ingenic_prepare_message()
271 if (priv->soc_info->has_trendian) { in spi_ingenic_prepare_message()
274 if (spi->mode & SPI_LSB_FIRST) in spi_ingenic_prepare_message()
279 if (spi->mode & SPI_LSB_FIRST) in spi_ingenic_prepare_message()
283 if (spi->mode & SPI_LOOP) in spi_ingenic_prepare_message()
288 if (spi->mode & SPI_CPHA) in spi_ingenic_prepare_message()
290 if (spi->mode & SPI_CPOL) in spi_ingenic_prepare_message()
292 if (spi->mode & SPI_CS_HIGH) in spi_ingenic_prepare_message()
295 regmap_update_bits(priv->map, REG_SSICR0, ssicr0_mask, ssicr0); in spi_ingenic_prepare_message()
296 regmap_update_bits(priv->map, REG_SSICR1, ssicr1_mask, ssicr1); in spi_ingenic_prepare_message()
306 ret = clk_prepare_enable(priv->clk); in spi_ingenic_prepare_hardware()
310 regmap_write(priv->map, REG_SSICR0, REG_SSICR0_EACLRUN); in spi_ingenic_prepare_hardware()
311 regmap_write(priv->map, REG_SSICR1, 0); in spi_ingenic_prepare_hardware()
312 regmap_write(priv->map, REG_SSISR, 0); in spi_ingenic_prepare_hardware()
313 regmap_set_bits(priv->map, REG_SSICR0, REG_SSICR0_SSIE); in spi_ingenic_prepare_hardware()
322 regmap_clear_bits(priv->map, REG_SSICR0, REG_SSICR0_SSIE); in spi_ingenic_unprepare_hardware()
324 clk_disable_unprepare(priv->clk); in spi_ingenic_unprepare_hardware()
336 ret = dma_get_slave_caps(ctlr->dma_tx, &caps); in spi_ingenic_can_dma()
338 dev_err(&spi->dev, "Unable to get slave caps: %d\n", ret); in spi_ingenic_can_dma()
343 xfer->len <= caps.max_sg_burst * SPI_INGENIC_FIFO_SIZE; in spi_ingenic_can_dma()
349 ctlr->dma_tx = dma_request_slave_channel(dev, "tx"); in spi_ingenic_request_dma()
350 if (!ctlr->dma_tx) in spi_ingenic_request_dma()
351 return -ENODEV; in spi_ingenic_request_dma()
353 ctlr->dma_rx = dma_request_slave_channel(dev, "rx"); in spi_ingenic_request_dma()
355 if (!ctlr->dma_rx) in spi_ingenic_request_dma()
356 return -ENODEV; in spi_ingenic_request_dma()
358 ctlr->can_dma = spi_ingenic_can_dma; in spi_ingenic_request_dma()
367 if (ctlr->dma_tx) in spi_ingenic_release_dma()
368 dma_release_channel(ctlr->dma_tx); in spi_ingenic_release_dma()
369 if (ctlr->dma_rx) in spi_ingenic_release_dma()
370 dma_release_channel(ctlr->dma_rx); in spi_ingenic_release_dma()
383 struct device *dev = &pdev->dev; in spi_ingenic_probe()
392 return -EINVAL; in spi_ingenic_probe()
398 return -ENOMEM; in spi_ingenic_probe()
402 priv->soc_info = pdata; in spi_ingenic_probe()
404 priv->clk = devm_clk_get(dev, NULL); in spi_ingenic_probe()
405 if (IS_ERR(priv->clk)) { in spi_ingenic_probe()
406 return dev_err_probe(dev, PTR_ERR(priv->clk), in spi_ingenic_probe()
410 base = devm_platform_get_and_ioremap_resource(pdev, 0, &priv->mem_res); in spi_ingenic_probe()
414 priv->map = devm_regmap_init_mmio(dev, base, &spi_ingenic_regmap_config); in spi_ingenic_probe()
415 if (IS_ERR(priv->map)) in spi_ingenic_probe()
416 return PTR_ERR(priv->map); in spi_ingenic_probe()
418 priv->flen_field = devm_regmap_field_alloc(dev, priv->map, in spi_ingenic_probe()
419 pdata->flen_field); in spi_ingenic_probe()
420 if (IS_ERR(priv->flen_field)) in spi_ingenic_probe()
421 return PTR_ERR(priv->flen_field); in spi_ingenic_probe()
423 if (device_property_read_u32(dev, "num-cs", &num_cs)) in spi_ingenic_probe()
424 num_cs = pdata->max_native_cs; in spi_ingenic_probe()
428 ctlr->prepare_transfer_hardware = spi_ingenic_prepare_hardware; in spi_ingenic_probe()
429 ctlr->unprepare_transfer_hardware = spi_ingenic_unprepare_hardware; in spi_ingenic_probe()
430 ctlr->prepare_message = spi_ingenic_prepare_message; in spi_ingenic_probe()
431 ctlr->set_cs = spi_ingenic_set_cs; in spi_ingenic_probe()
432 ctlr->transfer_one = spi_ingenic_transfer_one; in spi_ingenic_probe()
433 ctlr->mode_bits = SPI_MODE_3 | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH; in spi_ingenic_probe()
434 ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; in spi_ingenic_probe()
435 ctlr->max_dma_len = SPI_INGENIC_FIFO_SIZE; in spi_ingenic_probe()
436 ctlr->bits_per_word_mask = pdata->bits_per_word_mask; in spi_ingenic_probe()
437 ctlr->min_speed_hz = 7200; in spi_ingenic_probe()
438 ctlr->max_speed_hz = pdata->max_speed_hz; in spi_ingenic_probe()
439 ctlr->use_gpio_descriptors = true; in spi_ingenic_probe()
440 ctlr->max_native_cs = pdata->max_native_cs; in spi_ingenic_probe()
441 ctlr->num_chipselect = num_cs; in spi_ingenic_probe()
442 ctlr->dev.of_node = pdev->dev.of_node; in spi_ingenic_probe()
445 dev_warn(dev, "DMA not available.\n"); in spi_ingenic_probe()
497 { .compatible = "ingenic,jz4750-spi", .data = &jz4750_soc_info },
498 { .compatible = "ingenic,jz4775-spi", .data = &jz4780_soc_info },
499 { .compatible = "ingenic,jz4780-spi", .data = &jz4780_soc_info },
500 { .compatible = "ingenic,x1000-spi", .data = &x1000_soc_info },
501 { .compatible = "ingenic,x2000-spi", .data = &x2000_soc_info },
508 .name = "spi-ingenic",
516 MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");