diff options
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r-- | drivers/spi/spi.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d1d3bdcc41..c627d88954 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1,21 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2008 Sascha Hauer, Pengutronix * * Derived from Linux SPI Framework * * Copyright (C) 2005 David Brownell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * */ #include <common.h> @@ -23,6 +12,7 @@ #include <spi/spi.h> #include <xfuncs.h> #include <malloc.h> +#include <slice.h> #include <errno.h> #include <init.h> #include <of.h> @@ -40,6 +30,7 @@ struct boardinfo { }; static LIST_HEAD(board_list); +static LIST_HEAD(spi_controller_list); /** * spi_new_device - instantiate one new SPI device @@ -82,7 +73,7 @@ struct spi_device *spi_new_device(struct spi_controller *ctrl, /* allocate a free id for this chip */ proxy->dev.id = DEVICE_ID_DYNAMIC; proxy->dev.type_data = proxy; - proxy->dev.device_node = chip->device_node; + proxy->dev.of_node = chip->device_node; proxy->dev.parent = ctrl->dev; proxy->master = proxy->controller = ctrl; @@ -119,9 +110,8 @@ EXPORT_SYMBOL(spi_new_device); static void spi_of_register_slaves(struct spi_controller *ctrl) { struct device_node *n; - struct spi_board_info chip; struct property *reg; - struct device_node *node = ctrl->dev->device_node; + struct device_node *node = ctrl->dev->of_node; if (!IS_ENABLED(CONFIG_OFDEVICE)) return; @@ -130,7 +120,14 @@ static void spi_of_register_slaves(struct spi_controller *ctrl) return; for_each_available_child_of_node(node, n) { - memset(&chip, 0, sizeof(chip)); + struct spi_board_info chip = {}; + + if (n->dev) { + dev_dbg(ctrl->dev, "skipping already registered %s\n", + dev_name(n->dev)); + continue; + } + chip.name = xstrdup(n->name); chip.bus_num = ctrl->bus_num; /* Mode (clock phase/polarity/etc.) */ @@ -149,7 +146,18 @@ static void spi_of_register_slaves(struct spi_controller *ctrl) continue; chip.chip_select = of_read_number(reg->value, 1); chip.device_node = n; - spi_register_board_info(&chip, 1); + spi_new_device(ctrl, &chip); + } +} + +static void spi_controller_rescan(struct device *dev) +{ + struct spi_controller *ctrl; + + list_for_each_entry(ctrl, &spi_controller_list, list) { + if (ctrl->dev != dev) + continue; + spi_of_register_slaves(ctrl); } } @@ -207,8 +215,6 @@ static void scan_boardinfo(struct spi_controller *ctrl) } } -static LIST_HEAD(spi_controller_list); - static int spi_controller_check_ops(struct spi_controller *ctlr) { /* @@ -264,14 +270,16 @@ int spi_register_controller(struct spi_controller *ctrl) if (status) return status; + slice_init(&ctrl->slice, dev_name(ctrl->dev)); + /* even if it's just one always-selected device, there must * be at least one chipselect */ if (ctrl->num_chipselect == 0) return -EINVAL; - if ((ctrl->bus_num < 0) && ctrl->dev->device_node) - ctrl->bus_num = of_alias_get_id(ctrl->dev->device_node, "spi"); + if ((ctrl->bus_num < 0) && ctrl->dev->of_node) + ctrl->bus_num = of_alias_get_id(ctrl->dev->of_node, "spi"); /* convention: dynamically assigned bus IDs count down from the max */ if (ctrl->bus_num < 0) @@ -285,6 +293,9 @@ int spi_register_controller(struct spi_controller *ctrl) scan_boardinfo(ctrl); status = 0; + if (!ctrl->dev->rescan) + ctrl->dev->rescan = spi_controller_rescan; + return status; } EXPORT_SYMBOL(spi_register_controller); @@ -344,12 +355,19 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) int spi_sync(struct spi_device *spi, struct spi_message *message) { int status; + int ret; status = __spi_validate(spi, message); if (status != 0) return status; - return spi->controller->transfer(spi, message); + slice_acquire(&spi->controller->slice); + + ret = spi->controller->transfer(spi, message); + + slice_release(&spi->controller->slice); + + return ret; } /** @@ -394,22 +412,9 @@ int spi_write_then_read(struct spi_device *spi, } EXPORT_SYMBOL(spi_write_then_read); -static int spi_probe(struct device_d *dev) -{ - return dev->driver->probe(dev); -} - -static void spi_remove(struct device_d *dev) -{ - if (dev->driver->remove) - dev->driver->remove(dev); -} - struct bus_type spi_bus = { .name = "spi", .match = device_match_of_modalias, - .probe = spi_probe, - .remove = spi_remove, }; static int spi_bus_init(void) |