aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/spi.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 964124b60db2..75e86865234c 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -226,10 +226,11 @@ EXPORT_SYMBOL_GPL(spi_alloc_device);
226 * Companion function to spi_alloc_device. Devices allocated with 226 * Companion function to spi_alloc_device. Devices allocated with
227 * spi_alloc_device can be added onto the spi bus with this function. 227 * spi_alloc_device can be added onto the spi bus with this function.
228 * 228 *
229 * Returns 0 on success; non-zero on failure 229 * Returns 0 on success; negative errno on failure
230 */ 230 */
231int spi_add_device(struct spi_device *spi) 231int spi_add_device(struct spi_device *spi)
232{ 232{
233 static DEFINE_MUTEX(spi_add_lock);
233 struct device *dev = spi->master->dev.parent; 234 struct device *dev = spi->master->dev.parent;
234 int status; 235 int status;
235 236
@@ -246,26 +247,43 @@ int spi_add_device(struct spi_device *spi)
246 "%s.%u", spi->master->dev.bus_id, 247 "%s.%u", spi->master->dev.bus_id,
247 spi->chip_select); 248 spi->chip_select);
248 249
249 /* drivers may modify this initial i/o setup */ 250
251 /* We need to make sure there's no other device with this
252 * chipselect **BEFORE** we call setup(), else we'll trash
253 * its configuration. Lock against concurrent add() calls.
254 */
255 mutex_lock(&spi_add_lock);
256
257 if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id)
258 != NULL) {
259 dev_err(dev, "chipselect %d already in use\n",
260 spi->chip_select);
261 status = -EBUSY;
262 goto done;
263 }
264
265 /* Drivers may modify this initial i/o setup, but will
266 * normally rely on the device being setup. Devices
267 * using SPI_CS_HIGH can't coexist well otherwise...
268 */
250 status = spi->master->setup(spi); 269 status = spi->master->setup(spi);
251 if (status < 0) { 270 if (status < 0) {
252 dev_err(dev, "can't %s %s, status %d\n", 271 dev_err(dev, "can't %s %s, status %d\n",
253 "setup", spi->dev.bus_id, status); 272 "setup", spi->dev.bus_id, status);
254 return status; 273 goto done;
255 } 274 }
256 275
257 /* driver core catches callers that misbehave by defining 276 /* Device may be bound to an active driver when this returns */
258 * devices that already exist.
259 */
260 status = device_add(&spi->dev); 277 status = device_add(&spi->dev);
261 if (status < 0) { 278 if (status < 0)
262 dev_err(dev, "can't %s %s, status %d\n", 279 dev_err(dev, "can't %s %s, status %d\n",
263 "add", spi->dev.bus_id, status); 280 "add", spi->dev.bus_id, status);
264 return status; 281 else
265 } 282 dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
266 283
267 dev_dbg(dev, "registered child %s\n", spi->dev.bus_id); 284done:
268 return 0; 285 mutex_unlock(&spi_add_lock);
286 return status;
269} 287}
270EXPORT_SYMBOL_GPL(spi_add_device); 288EXPORT_SYMBOL_GPL(spi_add_device);
271 289