/* * Elba SoC does not use ssi, pin override is used for cs 0,1 and * gpios for cs 2,3 as defined in the device tree. * * cs: | 1 0 * bit: |---3-------2-------1-------0 * | cs1 cs1_ovr cs0 cs0_ovr
*/ #define ELBA_SPICS_REG 0x2468 #define ELBA_SPICS_OFFSET(cs) ((cs) << 1) #define ELBA_SPICS_MASK(cs) (GENMASK(1, 0) << ELBA_SPICS_OFFSET(cs)) #define ELBA_SPICS_SET(cs, val) \
((((val) << 1) | BIT(0)) << ELBA_SPICS_OFFSET(cs))
/* * The Designware SPI controller (referred to as master in the documentation) * automatically deasserts chip select when the tx fifo is empty. The chip * selects then needs to be either driven as GPIOs or, for the first 4 using * the SPI boot controller registers. the final chip select is an OR gate * between the Designware SPI controller and the SPI boot controller.
*/ staticvoid dw_spi_mscc_set_cs(struct spi_device *spi, bool enable)
{ struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws); struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
u32 cs = spi_get_chipselect(spi, 0);
if (cs < 4) {
u32 sw_mode = MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE;
if (!enable)
sw_mode |= MSCC_SPI_MST_SW_MODE_SW_SPI_CS(BIT(cs));
dwsmscc = devm_kzalloc(&pdev->dev, sizeof(*dwsmscc), GFP_KERNEL); if (!dwsmscc) return -ENOMEM;
dwsmscc->spi_mst = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(dwsmscc->spi_mst)) {
dev_err(&pdev->dev, "SPI_MST region map failed\n"); return PTR_ERR(dwsmscc->spi_mst);
}
dwsmscc->syscon = syscon_regmap_lookup_by_compatible(cpu_syscon); if (IS_ERR(dwsmscc->syscon)) return PTR_ERR(dwsmscc->syscon);
/* Deassert all CS */
writel(0, dwsmscc->spi_mst + MSCC_SPI_MST_SW_MODE);
/* Select the owner of the SI interface */
regmap_update_bits(dwsmscc->syscon, MSCC_CPU_SYSTEM_CTRL_GENERAL_CTRL,
MSCC_IF_SI_OWNER_MASK << if_si_owner_offset,
MSCC_IF_SI_OWNER_SIMC << if_si_owner_offset);
/* * The Designware SPI controller (referred to as master in the * documentation) automatically deasserts chip select when the tx fifo * is empty. The chip selects then needs to be driven by a CS override * register. enable is an active low signal.
*/ staticvoid dw_spi_sparx5_set_cs(struct spi_device *spi, bool enable)
{ struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws); struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
u8 cs = spi_get_chipselect(spi, 0);
/* * DMA-based mem ops are not configured for this device and are not tested.
*/ staticint dw_spi_mountevans_imc_init(struct platform_device *pdev, struct dw_spi_mmio *dwsmmio)
{ /* * The Intel Mount Evans SoC's Integrated Management Complex DW * apb_ssi_v4.02a controller has an errata where a full TX FIFO can * result in data corruption. The suggested workaround is to never * completely fill the FIFO. The TX FIFO has a size of 32 so the * fifo_len is set to 31.
*/
dwsmmio->dws.fifo_len = 31;
return 0;
}
staticint dw_spi_canaan_k210_init(struct platform_device *pdev, struct dw_spi_mmio *dwsmmio)
{ /* * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is * documented to have a 32 word deep TX and RX FIFO, which * spi_hw_init() detects. However, when the RX FIFO is filled up to * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this * problem by force setting fifo_len to 31.
*/
dwsmmio->dws.fifo_len = 31;
return 0;
}
staticvoid dw_spi_elba_override_cs(struct regmap *syscon, int cs, int enable)
{
regmap_update_bits(syscon, ELBA_SPICS_REG, ELBA_SPICS_MASK(cs),
ELBA_SPICS_SET(cs, enable));
}
/* * The DW SPI controller needs a native CS bit selected to start * the serial engine.
*/
spi_set_chipselect(spi, 0, 0);
dw_spi_set_cs(spi, enable);
spi_set_chipselect(spi, 0, cs);
}
if (device_property_read_bool(&pdev->dev, "spi-slave")) {
dev_warn(&pdev->dev, "spi-slave is not yet supported\n"); return -ENODEV;
}
dwsmmio = devm_kzalloc(&pdev->dev, sizeof(struct dw_spi_mmio),
GFP_KERNEL); if (!dwsmmio) return -ENOMEM;
dws = &dwsmmio->dws;
/* Get basic io resource and map it */
dws->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); if (IS_ERR(dws->regs)) return PTR_ERR(dws->regs);
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.