diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 12:54:31 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-13 12:54:31 -0800 |
commit | d0f3ad23cf4f4046e88eef92c608d43cad9e4f7e (patch) | |
tree | f22a64cac48017fab350b4a954652f687a952a5d /drivers/spi/spi.c | |
parent | c5589c436d4646e0dc23f64264db8e04cf67c88f (diff) | |
parent | 3cf241c3d56ff19f5192cb42a025bc6582b6e8fa (diff) |
Merge tag 'spi-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"A busy enough release, but not for the core which has only seen very
small updates. The biggest addition is the readdition of support for
detailed configuration of the timings around chip selects. That had
been removed for lack of use but there's been applications found for
it on Atmel systems. Otherwise the updates are mostly feature
additions and cleanups to existing drivers.
Summary:
- Provide a helper for getting device match data in a way that
abstracts away which firmware interface is being used.
- Re-add the spi_set_cs_timing() API for detailed configuration of
the timing around chip select and support it on Atmel.
- Support for MediaTek MT7986, Microchip PCI1xxxx, Nuvoton WPCM450
FIU and Socionext F_OSPI"
* tag 'spi-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (66 commits)
spi: dt-bindings: Convert Synquacer SPI to DT schema
spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
spi: spi-mtk-nor: Add recovery mechanism for dma read timeout
spi: spi-fsl-lpspi: add num-cs binding for lpspi
spi: spi-fsl-lpspi: support multiple cs for lpspi
spi: mtk-snfi: Add snfi support for MT7986 IC
spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
spi: cadence-quadspi: Add minimum operable clock rate warning to baudrate divisor calculation
spi: microchip: pci1xxxx: Add suspend and resume support for PCI1XXXX SPI driver
spi: dt-bindings: nuvoton,wpcm450-fiu: Fix warning in example (missing reg property)
spi: dt-bindings: nuvoton,wpcm450-fiu: Fix error in example (bogus include)
spi: mediatek: Enable irq when pdata is ready
spi: spi-mtk-nor: Unify write buffer on/off
spi: intel: Add support for SFDP opcode
spi: intel: Take possible chip address into account in intel_spi_read/write_reg()
spi: intel: Implement adjust_op_size()
spi: intel: Use ->replacement_op in intel_spi_hw_cycle()
spi: cadence: Drop obsolete dependency on COMPILE_TEST
spi: Add Nuvoton WPCM450 Flash Interface Unit (FIU) bindings
spi: wpcm-fiu: Add direct map support
...
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5f9aedd1f0b6..3cc7bb4d03de 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -127,10 +127,10 @@ do { \ unsigned int start; \ pcpu_stats = per_cpu_ptr(in, i); \ do { \ - start = u64_stats_fetch_begin_irq( \ + start = u64_stats_fetch_begin( \ &pcpu_stats->syncp); \ inc = u64_stats_read(&pcpu_stats->field); \ - } while (u64_stats_fetch_retry_irq( \ + } while (u64_stats_fetch_retry( \ &pcpu_stats->syncp, start)); \ ret += inc; \ } \ @@ -360,6 +360,18 @@ const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev) } EXPORT_SYMBOL_GPL(spi_get_device_id); +const void *spi_get_device_match_data(const struct spi_device *sdev) +{ + const void *match; + + match = device_get_match_data(&sdev->dev); + if (match) + return match; + + return (const void *)spi_get_device_id(sdev)->driver_data; +} +EXPORT_SYMBOL_GPL(spi_get_device_match_data); + static int spi_match_device(struct device *dev, struct device_driver *drv) { const struct spi_device *spi = to_spi_device(dev); @@ -2212,6 +2224,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, struct device_node *nc) { u32 value; + u16 cs_setup; int rc; /* Mode (clock phase/polarity/etc.) */ @@ -2297,6 +2310,11 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, if (!of_property_read_u32(nc, "spi-max-frequency", &value)) spi->max_speed_hz = value; + if (!of_property_read_u16(nc, "spi-cs-setup-ns", &cs_setup)) { + spi->cs_setup.value = cs_setup; + spi->cs_setup.unit = SPI_DELAY_UNIT_NSECS; + } + return 0; } @@ -2759,6 +2777,17 @@ int spi_slave_abort(struct spi_device *spi) } EXPORT_SYMBOL_GPL(spi_slave_abort); +int spi_target_abort(struct spi_device *spi) +{ + struct spi_controller *ctlr = spi->controller; + + if (spi_controller_is_target(ctlr) && ctlr->target_abort) + return ctlr->target_abort(ctlr); + + return -ENOTSUPP; +} +EXPORT_SYMBOL_GPL(spi_target_abort); + static ssize_t slave_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -3593,6 +3622,37 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr, } /** + * spi_set_cs_timing - configure CS setup, hold, and inactive delays + * @spi: the device that requires specific CS timing configuration + * + * Return: zero on success, else a negative error code. + */ +static int spi_set_cs_timing(struct spi_device *spi) +{ + struct device *parent = spi->controller->dev.parent; + int status = 0; + + if (spi->controller->set_cs_timing && !spi->cs_gpiod) { + if (spi->controller->auto_runtime_pm) { + status = pm_runtime_get_sync(parent); + if (status < 0) { + pm_runtime_put_noidle(parent); + dev_err(&spi->controller->dev, "Failed to power device: %d\n", + status); + return status; + } + + status = spi->controller->set_cs_timing(spi); + pm_runtime_mark_last_busy(parent); + pm_runtime_put_autosuspend(parent); + } else { + status = spi->controller->set_cs_timing(spi); + } + } + return status; +} + +/** * spi_setup - setup SPI mode and clock rate * @spi: the device whose settings are being modified * Context: can sleep, and no requests are queued to the device @@ -3688,6 +3748,12 @@ int spi_setup(struct spi_device *spi) } } + status = spi_set_cs_timing(spi); + if (status) { + mutex_unlock(&spi->controller->io_mutex); + return status; + } + if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { status = pm_runtime_resume_and_get(spi->controller->dev.parent); if (status < 0) { |