// SPDX-License-Identifier: GPL-2.0+ // // Freescale MXS SPI host driver // // Copyright 2012 DENX Software Engineering, GmbH. // Copyright 2012 Freescale Semiconductor, Inc. // Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. // // Rework and transition to new API by: // Marek Vasut <marex@denx.de> // // Based on previous attempt by: // Fabio Estevam <fabio.estevam@freescale.com> // // Based on code from U-Boot bootloader by: // Marek Vasut <marex@denx.de> // // Based on spi-stmp.c, which is: // Author: Dmitry Pervushin <dimka@embeddedalley.com>
/* Use 10S timeout for very long transfers, it should suffice. */ #define SSP_TIMEOUT 10000
#define SG_MAXLEN 0xff00
/* * Flags for txrx functions. More efficient that using an argument register for * each one.
*/ #define TXRX_WRITE (1<<0) /* This is a write */ #define TXRX_DEASSERT_CS (1<<1) /* De-assert CS at end of txrx */
if (hz == 0) {
dev_err(&dev->dev, "SPI clock rate of zero not allowed\n"); return -EINVAL;
}
if (hz != spi->sck) {
mxs_ssp_set_clk_rate(ssp, hz); /* * Save requested rate, hz, rather than the actual rate, * ssp->clk_rate. Otherwise we would set the rate every transfer * when the actual rate is not quite the same as requested rate.
*/
spi->sck = hz; /* * Perhaps we should return an error if the actual clock is * nowhere close to what was requested?
*/
}
/* * i.MX28 Datasheet: 17.10.1: HW_SSP_CTRL0 * * The bits BM_SSP_CTRL0_WAIT_FOR_CMD and BM_SSP_CTRL0_WAIT_FOR_IRQ * in HW_SSP_CTRL0 register do have multiple usage, please refer to * the datasheet for further details. In SPI mode, they are used to * toggle the chip-select lines (nCS pins).
*/ if (cs & 1)
select |= BM_SSP_CTRL0_WAIT_FOR_CMD; if (cs & 2)
select |= BM_SSP_CTRL0_WAIT_FOR_IRQ;
if (!(flags & TXRX_WRITE))
ctrl0 |= BM_SSP_CTRL0_READ;
/* Queue the DMA data transfer. */ for (sg_count = 0; sg_count < sgs; sg_count++) { /* Prepare the transfer descriptor. */
min = min(len, desc_len);
/* * De-assert CS on last segment if flag is set (i.e., no more * transfers will follow)
*/ if ((sg_count + 1 == sgs) && (flags & TXRX_DEASSERT_CS))
ctrl0 |= BM_SSP_CTRL0_IGNORE_CRC;
if (!desc) {
dev_err(ssp->dev, "Failed to get DMA data write descriptor.\n");
ret = -EINVAL; goto err_mapped;
}
}
/* * The last descriptor must have this callback, * to finish the DMA transaction.
*/
desc->callback = mxs_ssp_dma_irq_callback;
desc->callback_param = spi;
/* Start the transfer. */
dmaengine_submit(desc);
dma_async_issue_pending(ssp->dmach);
if (!wait_for_completion_timeout(&spi->c,
msecs_to_jiffies(SSP_TIMEOUT))) {
dev_err(ssp->dev, "DMA transfer timeout\n");
ret = -ETIMEDOUT;
dmaengine_terminate_all(ssp->dmach); goto err_vmalloc;
}
/* Program CS register bits here, it will be used for all transfers. */
writel(BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ,
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
writel(mxs_spi_cs_to_reg(spi_get_chipselect(m->spi, 0)),
ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
status = mxs_spi_setup_transfer(m->spi, t); if (status) break;
t->effective_speed_hz = ssp->clk_rate;
/* De-assert on last transfer, inverted by cs_change flag */
flag = (&t->transfer_list == m->transfers.prev) ^ t->cs_change ?
TXRX_DEASSERT_CS : 0;
/* * Small blocks can be transfered via PIO. * Measured by empiric means: * * dd if=/dev/mtdblock0 of=/dev/null bs=1024k count=1 * * DMA only: 2.164808 seconds, 473.0KB/s * Combined: 1.676276 seconds, 610.9KB/s
*/ if (t->len < 32) {
writel(BM_SSP_CTRL1_DMA_ENABLE,
ssp->base + HW_SSP_CTRL1(ssp) +
STMP_OFFSET_REG_CLR);
if (t->tx_buf)
status = mxs_spi_txrx_pio(spi,
(void *)t->tx_buf,
t->len, flag | TXRX_WRITE); if (t->rx_buf)
status = mxs_spi_txrx_pio(spi,
t->rx_buf, t->len,
flag);
} else {
writel(BM_SSP_CTRL1_DMA_ENABLE,
ssp->base + HW_SSP_CTRL1(ssp) +
STMP_OFFSET_REG_SET);
if (t->tx_buf)
status = mxs_spi_txrx_dma(spi,
(void *)t->tx_buf, t->len,
flag | TXRX_WRITE); if (t->rx_buf)
status = mxs_spi_txrx_dma(spi,
t->rx_buf, t->len,
flag);
}
trace_spi_transfer_stop(m, t);
if (status) {
stmp_reset_block(ssp->base); break;
}
/* * Default clock speed for the SPI core. 160MHz seems to * work reasonably well with most SPI flashes, so use this * as a default. Override with "clock-frequency" DT prop.
*/ constint clk_freq_default = 160000000;
irq_err = platform_get_irq(pdev, 0); if (irq_err < 0) return irq_err;
base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base);
clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk);
devid = (enum mxs_ssp_id) of_id->data;
ret = of_property_read_u32(np, "clock-frequency",
&clk_freq); if (ret)
clk_freq = clk_freq_default;
host = spi_alloc_host(&pdev->dev, sizeof(*spi)); if (!host) return -ENOMEM;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.