// SPDX-License-Identifier: GPL-2.0-only /* * SPI_PPC4XX SPI controller driver. * * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de> * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering * Copyright 2009 Harris Corporation, Steven A. Falco <sfalco@harris.com> * * Based in part on drivers/spi/spi_s3c24xx.c * * Copyright (c) 2006 Ben Dooks * Copyright (c) 2006 Simtec Electronics * Ben Dooks <ben@simtec.co.uk>
*/
/* * The PPC4xx SPI controller has no FIFO so each sent/received byte will * generate an interrupt to the CPU. This can cause high CPU utilization. * This driver allows platforms to reduce the interrupt load on the CPU * during SPI transfers by setting max_speed_hz via the device tree.
*/
/* * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock" * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock" * Note: This is the inverse of CPHA.
*/ #define SPI_PPC4XX_MODE_SCP (0x80 >> 3)
/* * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode * Note: This is identical to SPI_LSB_FIRST.
*/ #define SPI_PPC4XX_MODE_RD (0x80 >> 5)
/* * SPI_PPC4XX_MODE_CI = 0 means "clock idles low" * SPI_PPC4XX_MODE_CI = 1 means "clock idles high" * Note: This is identical to CPOL.
*/ #define SPI_PPC4XX_MODE_CI (0x80 >> 6)
/* bits in control register */ /* starts a transfer when set */ #define SPI_PPC4XX_CR_STR (0x80 >> 7)
/* bits in status register */ /* port is busy with a transfer */ #define SPI_PPC4XX_SR_BSY (0x80 >> 6) /* RxD ready */ #define SPI_PPC4XX_SR_RBR (0x80 >> 7)
/* Start with the generic configuration for this device. */
speed = spi->max_speed_hz;
/* * Modify the configuration if the transfer overrides it. Do not allow * the transfer to overwrite the generic configuration with zeros.
*/ if (t) { if (t->speed_hz)
speed = min(t->speed_hz, spi->max_speed_hz);
}
/* Write new configuration */
out_8(&hw->regs->mode, cs->mode);
/* Set the clock */ /* opb_freq was already divided by 4 */
scr = (hw->opb_freq / speed) - 1; if (scr > 0)
cdm = min(scr, 0xff);
dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed);
if (in_8(&hw->regs->cdm) != cdm)
out_8(&hw->regs->cdm, cdm);
mutex_lock(&hw->bitbang.lock); if (!hw->bitbang.busy) {
hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); /* Need to ndelay here? */
}
mutex_unlock(&hw->bitbang.lock);
status = in_8(&hw->regs->sr); if (!status) return IRQ_NONE;
/* * BSY de-asserts one cycle after the transfer is complete. The * interrupt is asserted after the transfer is complete. The exact * relationship is not documented, hence this code.
*/
if (unlikely(status & SPI_PPC4XX_SR_BSY)) {
u8 lstatus; int cnt = 0;
dev_dbg(hw->dev, "got interrupt but spi still busy?\n"); do {
ndelay(10);
lstatus = in_8(&hw->regs->sr);
} while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY);
if (cnt >= 100) {
dev_err(hw->dev, "busywait: too many loops!\n");
complete(&hw->done); return IRQ_HANDLED;
} else { /* status is always 1 (RBR) here */
status = in_8(&hw->regs->sr);
dev_dbg(hw->dev, "loops %d status %x\n", cnt, status);
}
}
count = hw->count;
hw->count++;
/* RBR triggered this interrupt. Therefore, data must be ready. */
data = in_8(&hw->regs->rxd); if (hw->rx)
hw->rx[count] = data;
staticvoid spi_ppc4xx_enable(struct ppc4xx_spi *hw)
{ /* * On all 4xx PPC's the SPI bus is shared/multiplexed with * the 2nd I2C bus. We need to enable the SPI bus before * using it.
*/
/* need to clear bit 14 to enable SPC */
dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0);
}
/* Setup the state for the bitbang driver */
bbp = &hw->bitbang;
bbp->ctlr = hw->host;
bbp->setup_transfer = spi_ppc4xx_setupxfer;
bbp->txrx_bufs = spi_ppc4xx_txrx;
bbp->use_dma = 0;
bbp->ctlr->setup = spi_ppc4xx_setup;
bbp->ctlr->cleanup = spi_ppc4xx_cleanup;
bbp->ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
bbp->ctlr->use_gpio_descriptors = true; /* * The SPI core will count the number of GPIO descriptors to figure * out the number of chip selects available on the platform.
*/
bbp->ctlr->num_chipselect = 0;
/* the spi->mode bits understood by this driver: */
bbp->ctlr->mode_bits =
SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST;
/* Get the clock for the OPB */
opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); if (opbnp == NULL) {
dev_err(dev, "OPB: cannot find node\n");
ret = -ENODEV; goto free_host;
} /* Get the clock (Hz) for the OPB */
clk = of_get_property(opbnp, "clock-frequency", NULL); if (clk == NULL) {
dev_err(dev, "OPB: no clock-frequency property set\n");
of_node_put(opbnp);
ret = -ENODEV; goto free_host;
}
hw->opb_freq = *clk;
hw->opb_freq >>= 2;
of_node_put(opbnp);
ret = of_address_to_resource(np, 0, &resource); if (ret) {
dev_err(dev, "error while parsing device node resource\n"); goto free_host;
}
hw->mapbase = resource.start;
hw->mapsize = resource_size(&resource);
/* Sanity check */ if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) {
dev_err(dev, "too small to map registers\n");
ret = -EINVAL; goto free_host;
}
/* Request IRQ */
ret = platform_get_irq(op, 0); if (ret < 0) goto free_host;
hw->irqnum = ret;
ret = request_irq(hw->irqnum, spi_ppc4xx_int,
0, "spi_ppc4xx_of", (void *)hw); if (ret) {
dev_err(dev, "unable to allocate interrupt\n"); goto free_host;
}
if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) {
dev_err(dev, "resource unavailable\n");
ret = -EBUSY; goto request_mem_error;
}
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.