From aea672d054a21782ed8450c75febb6ba3c208ca4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 20 Oct 2022 22:54:21 +0300 Subject: spi: Introduce spi_get_device_match_data() helper The proposed spi_get_device_match_data() helper is for retrieving a driver data associated with the ID in an ID table. First, it tries to get driver data of the device enumerated by firmware interface (usually Device Tree or ACPI). If none is found it falls back to the SPI ID table matching. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20221020195421.10482-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 5f9aedd1f0b6..aaf07052fd01 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -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); -- cgit v1.2.3 From 93cc2559d3fdcd28b1a7972ab519a6cd8ba20f9d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 26 Oct 2022 14:29:51 +0200 Subject: spi: Remove the obsolte u64_stats_fetch_*_irq() users. Now that the 32bit UP oddity is gone and 32bit uses always a sequence count, there is no need for the fetch_irq() variants anymore. Convert to the regular interface. Cc: Mark Brown Cc: linux-spi@vger.kernel.org Signed-off-by: Thomas Gleixner Signed-off-by: Sebastian Andrzej Siewior Acked-by: Peter Zijlstra (Intel) Link: https://lore.kernel.org/r/20221026122951.331638-1-bigeasy@linutronix.de Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index aaf07052fd01..8df8b93df1c3 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; \ } \ -- cgit v1.2.3 From b8d3b056a78dcc941fd1a117697ab2b956c2953f Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 11 Oct 2022 17:22:04 +0800 Subject: spi: introduce new helpers with using modern naming For using modern names host/target to instead of all the legacy names, I think it takes 3 steps: - step1: introduce new helpers with modern naming. - step2: switch to use these new helpers in all drivers. - step3: remove all legacy helpers and update all legacy names. This patch is for step1, it introduces new helpers with host/target naming for drivers using. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20221011092204.950288-1-yangyingliang@huawei.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 11 +++++++++++ include/linux/spi/spi.h | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 8df8b93df1c3..4ddd250481f5 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2771,6 +2771,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) { diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 8fe3d0a9d2c9..798c30229e07 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -356,6 +356,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * @max_speed_hz: Highest supported transfer speed * @flags: other constraints relevant to this driver * @slave: indicates that this is an SPI slave controller + * @target: indicates that this is an SPI target controller * @devm_allocated: whether the allocation of this struct is devres-managed * @max_transfer_size: function that returns the max transfer size for * a &spi_device; may be %NULL, so the default %SIZE_MAX will be used. @@ -440,6 +441,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * @mem_caps: controller capabilities for the handling of memory operations. * @unprepare_message: undo any work done by prepare_message(). * @slave_abort: abort the ongoing transfer request on an SPI slave controller + * @target_abort: abort the ongoing transfer request on an SPI target controller * @cs_gpiods: Array of GPIO descs to use as chip select lines; one per CS * number. Any individual value may be NULL for CS lines that * are not GPIOs (driven by the SPI controller itself). @@ -535,8 +537,12 @@ struct spi_controller { /* Flag indicating if the allocation of this struct is devres-managed */ bool devm_allocated; - /* Flag indicating this is an SPI slave controller */ - bool slave; + union { + /* Flag indicating this is an SPI slave controller */ + bool slave; + /* Flag indicating this is an SPI target controller */ + bool target; + }; /* * on some hardware transfer / message size may be constrained @@ -650,6 +656,7 @@ struct spi_controller { int (*unprepare_message)(struct spi_controller *ctlr, struct spi_message *message); int (*slave_abort)(struct spi_controller *ctlr); + int (*target_abort)(struct spi_controller *ctlr); /* * These hooks are for drivers that use a generic implementation @@ -727,6 +734,11 @@ static inline bool spi_controller_is_slave(struct spi_controller *ctlr) return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->slave; } +static inline bool spi_controller_is_target(struct spi_controller *ctlr) +{ + return IS_ENABLED(CONFIG_SPI_SLAVE) && ctlr->target; +} + /* PM calls that need to be issued by the driver */ extern int spi_controller_suspend(struct spi_controller *ctlr); extern int spi_controller_resume(struct spi_controller *ctlr); @@ -763,6 +775,21 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host, return __spi_alloc_controller(host, size, true); } +static inline struct spi_controller *spi_alloc_host(struct device *dev, + unsigned int size) +{ + return __spi_alloc_controller(dev, size, false); +} + +static inline struct spi_controller *spi_alloc_target(struct device *dev, + unsigned int size) +{ + if (!IS_ENABLED(CONFIG_SPI_SLAVE)) + return NULL; + + return __spi_alloc_controller(dev, size, true); +} + struct spi_controller *__devm_spi_alloc_controller(struct device *dev, unsigned int size, bool slave); @@ -782,6 +809,21 @@ static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev, return __devm_spi_alloc_controller(dev, size, true); } +static inline struct spi_controller *devm_spi_alloc_host(struct device *dev, + unsigned int size) +{ + return __devm_spi_alloc_controller(dev, size, false); +} + +static inline struct spi_controller *devm_spi_alloc_target(struct device *dev, + unsigned int size) +{ + if (!IS_ENABLED(CONFIG_SPI_SLAVE)) + return NULL; + + return __devm_spi_alloc_controller(dev, size, true); +} + extern int spi_register_controller(struct spi_controller *ctlr); extern int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr); @@ -1141,6 +1183,7 @@ static inline void spi_message_free(struct spi_message *m) extern int spi_setup(struct spi_device *spi); extern int spi_async(struct spi_device *spi, struct spi_message *message); extern int spi_slave_abort(struct spi_device *spi); +extern int spi_target_abort(struct spi_device *spi); static inline size_t spi_max_message_size(struct spi_device *spi) -- cgit v1.2.3 From 33a2fde5f77bd744b8bd0c694bc173cc968e55a5 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 17 Nov 2022 12:52:43 +0200 Subject: spi: Introduce spi-cs-setup-ns property SPI NOR flashes have specific cs-setup time requirements without which they can't work at frequencies close to their maximum supported frequency, as they miss the first bits of the instruction command. Unrecognized commands are ignored, thus the flash will be unresponsive. Introduce the spi-cs-setup-ns property to allow spi devices to specify their cs setup time. Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20221117105249.115649-3-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 4ddd250481f5..b93a6085d9a0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2224,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.) */ @@ -2309,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; } -- cgit v1.2.3 From 684a47847ae639689e7b823251975348a8e5434f Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Thu, 17 Nov 2022 12:52:44 +0200 Subject: spi: Reintroduce spi_set_cs_timing() commit 4ccf359849ce ("spi: remove spi_set_cs_timing()"), removed the method as noboby used it. Nobody used it probably because some SPI controllers use some default large cs-setup time that covers the usual cs-setup time required by the spi devices. There are though SPI controllers that have a smaller granularity for the cs-setup time and their default value can't fulfill the spi device requirements. That's the case for the at91 QSPI IPs where the default cs-setup time is half of the QSPI clock period. This was observed when using an sst26vf064b SPI NOR flash which needs a spi-cs-setup-ns = <7>; in order to be operated close to its maximum 104 MHz frequency. Call spi_set_cs_timing() in spi_setup() just before calling spi_set_cs(), as the latter needs the CS timings already set. If spi->controller->set_cs_timing is not set, the method will return 0. There's no functional impact expected for the existing drivers. Even if the spi-mt65xx.c and spi-tegra114.c drivers set the set_cs_timing method, there's no user for them as of now. The only tested user of this support will be a SPI NOR flash that comunicates with the Atmel QSPI controller for which the support follows in the next patches. One will notice that this support is a bit different from the one that was removed in commit 4ccf359849ce ("spi: remove spi_set_cs_timing()"), because this patch adapts to the changes done after the removal: the move of the cs delays to the spi device, the retirement of the lelgacy GPIO handling. The mutex handling was removed from spi_set_cs_timing() because we now always call spi_set_cs_timing() in spi_setup(), which already handles the spi->controller->io_mutex, so use the mutex handling from spi_setup(). Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20221117105249.115649-4-tudor.ambarus@microchip.com Signed-off-by: Mark Brown --- drivers/spi/spi.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers/spi/spi.c') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b93a6085d9a0..3cc7bb4d03de 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -3621,6 +3621,37 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr, return 0; } +/** + * 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 @@ -3717,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) { -- cgit v1.2.3