diff options
author | Linus Torvalds | 2021-11-01 19:09:04 -0700 |
---|---|---|
committer | Linus Torvalds | 2021-11-01 19:09:04 -0700 |
commit | 2019295c9ea3137364682046bb6afc0eb364e591 (patch) | |
tree | 0f905528cd55cce6e1cd0db952f70f0531b06ff6 /drivers/spi/spi.c | |
parent | 1260d242d94ae423c585050bbaabe9064741f419 (diff) | |
parent | 28b5eaf9712bbed90c2b5a5608d70a16b7950856 (diff) |
Merge tag 'spi-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
Pull spi updates from Mark Brown:
"This is quite a quiet release for SPI, there's been a bit of cleanup
to the core from Uwe but nothing functionality wise.
We have added several new drivers, Cadence XSPI, Ingenic JZ47xx,
Qualcomm SC7280 and SC7180 and Xilinx Versal OSPI"
* tag 'spi-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi: (41 commits)
spi: Convert NXP flexspi to json schema
spi: spi-geni-qcom: Add support for GPI dma
spi: fsi: Fix contention in the FSI2SPI engine
spi: spi-rpc-if: Check return value of rpcif_sw_init()
spi: tegra210-quad: Put device into suspend on driver removal
spi: tegra20-slink: Put device into suspend on driver removal
spi: bcm-qspi: Fix missing clk_disable_unprepare() on error in bcm_qspi_probe()
spi: at91-usart: replacing legacy gpio interface for gpiod
spi: replace snprintf in show functions with sysfs_emit
spi: cadence: Add of_node_put() before return
spi: orion: Add of_node_put() before goto
spi: cadence-quadspi: fix dma_unmap_single() call
spi: tegra20: fix build with CONFIG_PM_SLEEP=n
spi: bcm-qspi: add support for 3-wire mode for half duplex transfer
spi: bcm-qspi: Add mspi spcr3 32/64-bits xfer mode
spi: Make several public functions private to spi.c
spi: Reorder functions to simplify the next commit
spi: Remove unused function spi_busnum_to_master()
spi: Move comment about chipselect check to the right place
spi: fsi: Print status on error
...
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 237 |
1 files changed, 95 insertions, 142 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 2a2f41b6df68..b23e675953e1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -285,9 +285,9 @@ static const struct attribute_group *spi_master_groups[] = { NULL, }; -void spi_statistics_add_transfer_stats(struct spi_statistics *stats, - struct spi_transfer *xfer, - struct spi_controller *ctlr) +static void spi_statistics_add_transfer_stats(struct spi_statistics *stats, + struct spi_transfer *xfer, + struct spi_controller *ctlr) { unsigned long flags; int l2len = min(fls(xfer->len), SPI_STATISTICS_HISTO_SIZE) - 1; @@ -310,7 +310,6 @@ void spi_statistics_add_transfer_stats(struct spi_statistics *stats, spin_unlock_irqrestore(&stats->lock, flags); } -EXPORT_SYMBOL_GPL(spi_statistics_add_transfer_stats); /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, * and the sysfs version makes coldplug work too. @@ -536,7 +535,7 @@ static DEFINE_MUTEX(board_lock); * * Return: a pointer to the new device, or NULL. */ -struct spi_device *spi_alloc_device(struct spi_controller *ctlr) +static struct spi_device *spi_alloc_device(struct spi_controller *ctlr) { struct spi_device *spi; @@ -561,7 +560,6 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr) device_initialize(&spi->dev); return spi; } -EXPORT_SYMBOL_GPL(spi_alloc_device); static void spi_dev_set_name(struct spi_device *spi) { @@ -599,6 +597,11 @@ static int __spi_add_device(struct spi_device *spi) struct device *dev = ctlr->dev.parent; int status; + /* + * We need to make sure there's no other device with this + * chipselect **BEFORE** we call setup(), else we'll trash + * its configuration. + */ status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); if (status) { dev_err(dev, "chipselect %d already in use\n", @@ -651,7 +654,7 @@ static int __spi_add_device(struct spi_device *spi) * * Return: 0 on success; negative errno on failure */ -int spi_add_device(struct spi_device *spi) +static int spi_add_device(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; struct device *dev = ctlr->dev.parent; @@ -667,16 +670,11 @@ int spi_add_device(struct spi_device *spi) /* Set the bus ID string */ spi_dev_set_name(spi); - /* We need to make sure there's no other device with this - * chipselect **BEFORE** we call setup(), else we'll trash - * its configuration. Lock against concurrent add() calls. - */ mutex_lock(&ctlr->add_lock); status = __spi_add_device(spi); mutex_unlock(&ctlr->add_lock); return status; } -EXPORT_SYMBOL_GPL(spi_add_device); static int spi_add_device_locked(struct spi_device *spi) { @@ -851,6 +849,87 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) /*-------------------------------------------------------------------------*/ +/* Core methods for SPI resource management */ + +/** + * spi_res_alloc - allocate a spi resource that is life-cycle managed + * during the processing of a spi_message while using + * spi_transfer_one + * @spi: the spi device for which we allocate memory + * @release: the release code to execute for this resource + * @size: size to alloc and return + * @gfp: GFP allocation flags + * + * Return: the pointer to the allocated data + * + * This may get enhanced in the future to allocate from a memory pool + * of the @spi_device or @spi_controller to avoid repeated allocations. + */ +static void *spi_res_alloc(struct spi_device *spi, spi_res_release_t release, + size_t size, gfp_t gfp) +{ + struct spi_res *sres; + + sres = kzalloc(sizeof(*sres) + size, gfp); + if (!sres) + return NULL; + + INIT_LIST_HEAD(&sres->entry); + sres->release = release; + + return sres->data; +} + +/** + * spi_res_free - free an spi resource + * @res: pointer to the custom data of a resource + * + */ +static void spi_res_free(void *res) +{ + struct spi_res *sres = container_of(res, struct spi_res, data); + + if (!res) + return; + + WARN_ON(!list_empty(&sres->entry)); + kfree(sres); +} + +/** + * spi_res_add - add a spi_res to the spi_message + * @message: the spi message + * @res: the spi_resource + */ +static void spi_res_add(struct spi_message *message, void *res) +{ + struct spi_res *sres = container_of(res, struct spi_res, data); + + WARN_ON(!list_empty(&sres->entry)); + list_add_tail(&sres->entry, &message->resources); +} + +/** + * spi_res_release - release all spi resources for this message + * @ctlr: the @spi_controller + * @message: the @spi_message + */ +static void spi_res_release(struct spi_controller *ctlr, struct spi_message *message) +{ + struct spi_res *res, *tmp; + + list_for_each_entry_safe_reverse(res, tmp, &message->resources, entry) { + if (res->release) + res->release(ctlr, message, res->data); + + list_del(&res->entry); + + kfree(res); + } +} + +/*-------------------------------------------------------------------------*/ + static void spi_set_cs(struct spi_device *spi, bool enable, bool force) { bool activate = enable; @@ -3068,127 +3147,6 @@ int spi_controller_resume(struct spi_controller *ctlr) } EXPORT_SYMBOL_GPL(spi_controller_resume); -static int __spi_controller_match(struct device *dev, const void *data) -{ - struct spi_controller *ctlr; - const u16 *bus_num = data; - - ctlr = container_of(dev, struct spi_controller, dev); - return ctlr->bus_num == *bus_num; -} - -/** - * spi_busnum_to_master - look up master associated with bus_num - * @bus_num: the master's bus number - * Context: can sleep - * - * This call may be used with devices that are registered after - * arch init time. It returns a refcounted pointer to the relevant - * spi_controller (which the caller must release), or NULL if there is - * no such master registered. - * - * Return: the SPI master structure on success, else NULL. - */ -struct spi_controller *spi_busnum_to_master(u16 bus_num) -{ - struct device *dev; - struct spi_controller *ctlr = NULL; - - dev = class_find_device(&spi_master_class, NULL, &bus_num, - __spi_controller_match); - if (dev) - ctlr = container_of(dev, struct spi_controller, dev); - /* reference got in class_find_device */ - return ctlr; -} -EXPORT_SYMBOL_GPL(spi_busnum_to_master); - -/*-------------------------------------------------------------------------*/ - -/* Core methods for SPI resource management */ - -/** - * spi_res_alloc - allocate a spi resource that is life-cycle managed - * during the processing of a spi_message while using - * spi_transfer_one - * @spi: the spi device for which we allocate memory - * @release: the release code to execute for this resource - * @size: size to alloc and return - * @gfp: GFP allocation flags - * - * Return: the pointer to the allocated data - * - * This may get enhanced in the future to allocate from a memory pool - * of the @spi_device or @spi_controller to avoid repeated allocations. - */ -void *spi_res_alloc(struct spi_device *spi, - spi_res_release_t release, - size_t size, gfp_t gfp) -{ - struct spi_res *sres; - - sres = kzalloc(sizeof(*sres) + size, gfp); - if (!sres) - return NULL; - - INIT_LIST_HEAD(&sres->entry); - sres->release = release; - - return sres->data; -} -EXPORT_SYMBOL_GPL(spi_res_alloc); - -/** - * spi_res_free - free an spi resource - * @res: pointer to the custom data of a resource - * - */ -void spi_res_free(void *res) -{ - struct spi_res *sres = container_of(res, struct spi_res, data); - - if (!res) - return; - - WARN_ON(!list_empty(&sres->entry)); - kfree(sres); -} -EXPORT_SYMBOL_GPL(spi_res_free); - -/** - * spi_res_add - add a spi_res to the spi_message - * @message: the spi message - * @res: the spi_resource - */ -void spi_res_add(struct spi_message *message, void *res) -{ - struct spi_res *sres = container_of(res, struct spi_res, data); - - WARN_ON(!list_empty(&sres->entry)); - list_add_tail(&sres->entry, &message->resources); -} -EXPORT_SYMBOL_GPL(spi_res_add); - -/** - * spi_res_release - release all spi resources for this message - * @ctlr: the @spi_controller - * @message: the @spi_message - */ -void spi_res_release(struct spi_controller *ctlr, struct spi_message *message) -{ - struct spi_res *res, *tmp; - - list_for_each_entry_safe_reverse(res, tmp, &message->resources, entry) { - if (res->release) - res->release(ctlr, message, res->data); - - list_del(&res->entry); - - kfree(res); - } -} -EXPORT_SYMBOL_GPL(spi_res_release); - /*-------------------------------------------------------------------------*/ /* Core methods for spi_message alterations */ @@ -3227,7 +3185,7 @@ static void __spi_replace_transfers_release(struct spi_controller *ctlr, * Returns: pointer to @spi_replaced_transfers, * PTR_ERR(...) in case of errors. */ -struct spi_replaced_transfers *spi_replace_transfers( +static struct spi_replaced_transfers *spi_replace_transfers( struct spi_message *msg, struct spi_transfer *xfer_first, size_t remove, @@ -3319,7 +3277,6 @@ struct spi_replaced_transfers *spi_replace_transfers( return rxfer; } -EXPORT_SYMBOL_GPL(spi_replace_transfers); static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, struct spi_message *msg, @@ -3869,7 +3826,7 @@ EXPORT_SYMBOL_GPL(spi_async); * * Return: zero on success, else a negative error code. */ -int spi_async_locked(struct spi_device *spi, struct spi_message *message) +static int spi_async_locked(struct spi_device *spi, struct spi_message *message) { struct spi_controller *ctlr = spi->controller; int ret; @@ -3888,7 +3845,6 @@ int spi_async_locked(struct spi_device *spi, struct spi_message *message) return ret; } -EXPORT_SYMBOL_GPL(spi_async_locked); /*-------------------------------------------------------------------------*/ @@ -4146,18 +4102,15 @@ EXPORT_SYMBOL_GPL(spi_write_then_read); /*-------------------------------------------------------------------------*/ -#if IS_ENABLED(CONFIG_OF) +#if IS_ENABLED(CONFIG_OF_DYNAMIC) /* must call put_device() when done with returned spi_device device */ -struct spi_device *of_find_spi_device_by_node(struct device_node *node) +static struct spi_device *of_find_spi_device_by_node(struct device_node *node) { struct device *dev = bus_find_device_by_of_node(&spi_bus_type, node); return dev ? to_spi_device(dev) : NULL; } -EXPORT_SYMBOL_GPL(of_find_spi_device_by_node); -#endif /* IS_ENABLED(CONFIG_OF) */ -#if IS_ENABLED(CONFIG_OF_DYNAMIC) /* the spi controllers are not using spi_bus, so we find it with another way */ static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) { |