/* Runtime PM autosuspend timeout: PM is fairly light on this driver */ #define SPI_AUTOSUSPEND_TIMEOUT 200
/* Some SoCs using this driver support up to 8 chip selects. * It is up to the implementer to only use the chip selects * that are available.
*/ #define ORION_NUM_CHIPSELECTS 8
#define ORION_SPI_WAIT_RDY_MAX_LOOP 2000 /* in usec */
struct orion_spi_dev { enum orion_spi_type typ; /* * min_divisor and max_hz should be exclusive, the only we can * have both is for managing the armada-370-spi case with old * device tree
*/ unsignedlong max_hz; unsignedint min_divisor; unsignedint max_divisor;
u32 prescale_mask; bool is_errata_50mhz_ac;
};
if (devdata->typ == ARMADA_SPI) { /* * Given the core_clk (tclk_hz) and the target rate (speed) we * determine the best values for SPR (in [0 .. 15]) and SPPR (in * [0..7]) such that * * core_clk / (SPR * 2 ** SPPR) * * is as big as possible but not bigger than speed.
*/
if (divider < 16) { /* This is the easy case, divider is less than 16 */
spr = divider;
sppr = 0;
} else { unsigned two_pow_sppr; /* * Find the highest bit set in divider. This and the * three next bits define SPR (apart from rounding). * SPPR is then the number of zero bits that must be * appended:
*/
sppr = fls(divider) - 4;
/* * As SPR only has 4 bits, we have to round divider up * to the next multiple of 2 ** sppr.
*/
two_pow_sppr = 1 << sppr;
divider = (divider + two_pow_sppr - 1) & -two_pow_sppr;
/* * recalculate sppr as rounding up divider might have * increased it enough to change the position of the * highest set bit. In this case the bit that now * doesn't make it into SPR is 0, so there is no need to * round again.
*/
sppr = fls(divider) - 4;
spr = divider >> sppr;
/* * Now do range checking. SPR is constructed to have a * width of 4 bits, so this is fine for sure. So we * still need to check for sppr to fit into 3 bits:
*/ if (sppr > 7) return -EINVAL;
}
prescale = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr;
} else { /* * the supported rates are: 4,6,8...30 * round up as we look for equal or less speed
*/
rate = DIV_ROUND_UP(tclk_hz, speed);
rate = roundup(rate, 2);
/* check if requested speed is too small */ if (rate > 30) return -EINVAL;
if (rate < 4)
rate = 4;
/* Convert the rate to SPI clock divisor value. */
prescale = 0x10 + rate/2;
}
/* * Erratum description: (Erratum NO. FE-9144572) The device * SPI interface supports frequencies of up to 50 MHz. * However, due to this erratum, when the device core clock is * 250 MHz and the SPI interfaces is configured for 50MHz SPI * clock and CPOL=CPHA=1 there might occur data corruption on * reads from the SPI device. * Erratum Workaround: * Work in one of the following configurations: * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration * Register". * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1 * Register" before setting the interface.
*/
reg = readl(spi_reg(orion_spi, ORION_SPI_TIMING_PARAMS_REG));
reg &= ~ORION_SPI_TMISO_SAMPLE_MASK;
if (clk_get_rate(orion_spi->clk) == 250000000 &&
speed == 50000000 && spi->mode & SPI_CPOL &&
spi->mode & SPI_CPHA)
reg |= ORION_SPI_TMISO_SAMPLE_2; else
reg |= ORION_SPI_TMISO_SAMPLE_1; /* This is the default value */
/* * called only when no transfer is active on the bus
*/ staticint
orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
{ struct orion_spi *orion_spi; unsignedint speed = spi->max_speed_hz; unsignedint bits_per_word = spi->bits_per_word; int rc;
/* Clear existing chip-select and assertion state */
val &= ~(ORION_SPI_CS_MASK | 0x1);
/* * If this line is using a GPIO to control chip select, this internal * .set_cs() function will still be called, so we clear any previous * chip select. The CS we activate will not have any elecrical effect, * as it is handled by a GPIO, but that doesn't matter. What we need * is to deassert the old chip select and assert some other chip select.
*/
val |= ORION_SPI_CS(spi_get_chipselect(spi, 0));
/* * Chip select logic is inverted from spi_set_cs(). For lines using a * GPIO to do chip select SPI_CS_HIGH is enforced and inversion happens * in the GPIO library, but we don't care about that, because in those * cases we are dealing with an unused native CS anyways so the polarity * doesn't matter.
*/ if (!enable)
val |= 0x1;
/* * To avoid toggling unwanted chip selects update the register * with a single write.
*/
writel(val, ctrl_reg);
}
staticinlineint orion_spi_wait_till_ready(struct orion_spi *orion_spi)
{ int i;
for (i = 0; i < ORION_SPI_WAIT_RDY_MAX_LOOP; i++) { if (readl(spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG))) return 1;
/* * Use SPI direct write mode if base address is available * and SPI_CS_WORD flag is not set. * Otherwise fall back to PIO mode for this transfer.
*/
vaddr = orion_spi->child[cs].direct_access.vaddr;
/* * Send the TX-data to the SPI device via the direct * mapped address window
*/
iowrite32_rep(vaddr, xfer->tx_buf, cnt); if (rem) {
u32 *buf = (u32 *)xfer->tx_buf;
spi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(spi->clk)) {
status = PTR_ERR(spi->clk); goto out;
}
/* The following clock is only used by some SoCs */
spi->axi_clk = devm_clk_get(&pdev->dev, "axi"); if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
status = -EPROBE_DEFER; goto out;
} if (!IS_ERR(spi->axi_clk))
clk_prepare_enable(spi->axi_clk);
tclk_hz = clk_get_rate(spi->clk);
/* * With old device tree, armada-370-spi could be used with * Armada XP, however for this SoC the maximum frequency is * 50MHz instead of tclk/4. On Armada 370, tclk cannot be * higher than 200MHz. So, in order to be able to handle both * SoCs, we can take the minimum of 50MHz and tclk/4.
*/ if (of_device_is_compatible(pdev->dev.of_node, "marvell,armada-370-spi"))
host->max_speed_hz = min(devdata->max_hz,
DIV_ROUND_UP(tclk_hz, devdata->min_divisor)); elseif (devdata->min_divisor)
host->max_speed_hz =
DIV_ROUND_UP(tclk_hz, devdata->min_divisor); else
host->max_speed_hz = devdata->max_hz;
host->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor);
spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(spi->base)) {
status = PTR_ERR(spi->base); goto out_rel_axi_clk;
}
/* Get chip-select number from the "reg" property */
status = of_property_read_u32(np, "reg", &cs); if (status) {
dev_err(&pdev->dev, "%pOF has no valid 'reg' property (%d)\n",
np, status); continue;
}
/* * Check if an address is configured for this SPI device. If * not, the MBus mapping via the 'ranges' property in the 'soc' * node is not configured and this device should not use the * direct mode. In this case, just continue with the next * device.
*/
status = of_address_to_resource(pdev->dev.of_node, cs + 1, r); if (status) continue;
/* * Only map one page for direct access. This is enough for the * simple TX transfer which only writes to the first word. * This needs to get extended for the direct SPI NOR / SPI NAND * support, once this gets implemented.
*/
dir_acc = &spi->child[cs].direct_access;
dir_acc->vaddr = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); if (!dir_acc->vaddr) {
status = -ENOMEM;
of_node_put(np); goto out_rel_axi_clk;
}
dir_acc->size = PAGE_SIZE;
dev_info(&pdev->dev, "CS%d configured for direct access\n", cs);
}
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.