aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2008-05-15 18:50:22 -0400
committerGrant Likely <grant.likely@secretlab.ca>2008-07-25 22:34:29 -0400
commitdc87c98e8f635a718f1abb2c3e15fc77c0001651 (patch)
tree283a50fb43f798fe9871fe3ba038221f78c3fd6b
parent3f07af494dfa6de43137dae430431c9fbf929c0c (diff)
spi: split up spi_new_device() to allow two stage registration.
spi_new_device() allocates and registers an spi device all in one swoop. If the driver needs to add extra data to the spi_device before it is registered, then this causes problems. This is needed for OF device tree support so that the SPI device tree helper can add a pointer to the device node after the device is allocated, but before the device is registered. OF aware SPI devices can then retrieve data out of the device node to populate a platform data structure. This patch splits the allocation and registration portions of code out of spi_new_device() and creates two new functions; spi_alloc_device() and spi_register_device(). spi_new_device() is modified to use the new functions for allocation and registration. None of the existing users of spi_new_device() should be affected by this change. Drivers using the new API can forego the use of spi_board_info structure to describe the device layout and populate data into the spi_device structure directly. This change is in preparation for adding an OF device tree parser to generate spi_devices based on data in the device tree. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Acked-by: David Brownell <dbrownell@users.sourceforge.net>
-rw-r--r--drivers/spi/spi.c139
-rw-r--r--include/linux/spi/spi.h12
2 files changed, 107 insertions, 44 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ecca4a6a6f94..964124b60db2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -178,6 +178,96 @@ struct boardinfo {
178static LIST_HEAD(board_list); 178static LIST_HEAD(board_list);
179static DEFINE_MUTEX(board_lock); 179static DEFINE_MUTEX(board_lock);
180 180
181/**
182 * spi_alloc_device - Allocate a new SPI device
183 * @master: Controller to which device is connected
184 * Context: can sleep
185 *
186 * Allows a driver to allocate and initialize a spi_device without
187 * registering it immediately. This allows a driver to directly
188 * fill the spi_device with device parameters before calling
189 * spi_add_device() on it.
190 *
191 * Caller is responsible to call spi_add_device() on the returned
192 * spi_device structure to add it to the SPI master. If the caller
193 * needs to discard the spi_device without adding it, then it should
194 * call spi_dev_put() on it.
195 *
196 * Returns a pointer to the new device, or NULL.
197 */
198struct spi_device *spi_alloc_device(struct spi_master *master)
199{
200 struct spi_device *spi;
201 struct device *dev = master->dev.parent;
202
203 if (!spi_master_get(master))
204 return NULL;
205
206 spi = kzalloc(sizeof *spi, GFP_KERNEL);
207 if (!spi) {
208 dev_err(dev, "cannot alloc spi_device\n");
209 spi_master_put(master);
210 return NULL;
211 }
212
213 spi->master = master;
214 spi->dev.parent = dev;
215 spi->dev.bus = &spi_bus_type;
216 spi->dev.release = spidev_release;
217 device_initialize(&spi->dev);
218 return spi;
219}
220EXPORT_SYMBOL_GPL(spi_alloc_device);
221
222/**
223 * spi_add_device - Add spi_device allocated with spi_alloc_device
224 * @spi: spi_device to register
225 *
226 * Companion function to spi_alloc_device. Devices allocated with
227 * spi_alloc_device can be added onto the spi bus with this function.
228 *
229 * Returns 0 on success; non-zero on failure
230 */
231int spi_add_device(struct spi_device *spi)
232{
233 struct device *dev = spi->master->dev.parent;
234 int status;
235
236 /* Chipselects are numbered 0..max; validate. */
237 if (spi->chip_select >= spi->master->num_chipselect) {
238 dev_err(dev, "cs%d >= max %d\n",
239 spi->chip_select,
240 spi->master->num_chipselect);
241 return -EINVAL;
242 }
243
244 /* Set the bus ID string */
245 snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
246 "%s.%u", spi->master->dev.bus_id,
247 spi->chip_select);
248
249 /* drivers may modify this initial i/o setup */
250 status = spi->master->setup(spi);
251 if (status < 0) {
252 dev_err(dev, "can't %s %s, status %d\n",
253 "setup", spi->dev.bus_id, status);
254 return status;
255 }
256
257 /* driver core catches callers that misbehave by defining
258 * devices that already exist.
259 */
260 status = device_add(&spi->dev);
261 if (status < 0) {
262 dev_err(dev, "can't %s %s, status %d\n",
263 "add", spi->dev.bus_id, status);
264 return status;
265 }
266
267 dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
268 return 0;
269}
270EXPORT_SYMBOL_GPL(spi_add_device);
181 271
182/** 272/**
183 * spi_new_device - instantiate one new SPI device 273 * spi_new_device - instantiate one new SPI device
@@ -197,7 +287,6 @@ struct spi_device *spi_new_device(struct spi_master *master,
197 struct spi_board_info *chip) 287 struct spi_board_info *chip)
198{ 288{
199 struct spi_device *proxy; 289 struct spi_device *proxy;
200 struct device *dev = master->dev.parent;
201 int status; 290 int status;
202 291
203 /* NOTE: caller did any chip->bus_num checks necessary. 292 /* NOTE: caller did any chip->bus_num checks necessary.
@@ -207,66 +296,28 @@ struct spi_device *spi_new_device(struct spi_master *master,
207 * suggests syslogged diagnostics are best here (ugh). 296 * suggests syslogged diagnostics are best here (ugh).
208 */ 297 */
209 298
210 /* Chipselects are numbered 0..max; validate. */ 299 proxy = spi_alloc_device(master);
211 if (chip->chip_select >= master->num_chipselect) { 300 if (!proxy)
212 dev_err(dev, "cs%d > max %d\n",
213 chip->chip_select,
214 master->num_chipselect);
215 return NULL;
216 }
217
218 if (!spi_master_get(master))
219 return NULL; 301 return NULL;
220 302
221 WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias)); 303 WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
222 304
223 proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
224 if (!proxy) {
225 dev_err(dev, "can't alloc dev for cs%d\n",
226 chip->chip_select);
227 goto fail;
228 }
229 proxy->master = master;
230 proxy->chip_select = chip->chip_select; 305 proxy->chip_select = chip->chip_select;
231 proxy->max_speed_hz = chip->max_speed_hz; 306 proxy->max_speed_hz = chip->max_speed_hz;
232 proxy->mode = chip->mode; 307 proxy->mode = chip->mode;
233 proxy->irq = chip->irq; 308 proxy->irq = chip->irq;
234 strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias)); 309 strlcpy(proxy->modalias, chip->modalias, sizeof(proxy->modalias));
235
236 snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
237 "%s.%u", master->dev.bus_id,
238 chip->chip_select);
239 proxy->dev.parent = dev;
240 proxy->dev.bus = &spi_bus_type;
241 proxy->dev.platform_data = (void *) chip->platform_data; 310 proxy->dev.platform_data = (void *) chip->platform_data;
242 proxy->controller_data = chip->controller_data; 311 proxy->controller_data = chip->controller_data;
243 proxy->controller_state = NULL; 312 proxy->controller_state = NULL;
244 proxy->dev.release = spidev_release;
245 313
246 /* drivers may modify this initial i/o setup */ 314 status = spi_add_device(proxy);
247 status = master->setup(proxy);
248 if (status < 0) { 315 if (status < 0) {
249 dev_err(dev, "can't %s %s, status %d\n", 316 spi_dev_put(proxy);
250 "setup", proxy->dev.bus_id, status); 317 return NULL;
251 goto fail;
252 } 318 }
253 319
254 /* driver core catches callers that misbehave by defining
255 * devices that already exist.
256 */
257 status = device_register(&proxy->dev);
258 if (status < 0) {
259 dev_err(dev, "can't %s %s, status %d\n",
260 "add", proxy->dev.bus_id, status);
261 goto fail;
262 }
263 dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
264 return proxy; 320 return proxy;
265
266fail:
267 spi_master_put(master);
268 kfree(proxy);
269 return NULL;
270} 321}
271EXPORT_SYMBOL_GPL(spi_new_device); 322EXPORT_SYMBOL_GPL(spi_new_device);
272 323
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index a9cc29d46653..4be01bb44377 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -778,8 +778,20 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
778 * use spi_new_device() to describe each device. You can also call 778 * use spi_new_device() to describe each device. You can also call
779 * spi_unregister_device() to start making that device vanish, but 779 * spi_unregister_device() to start making that device vanish, but
780 * normally that would be handled by spi_unregister_master(). 780 * normally that would be handled by spi_unregister_master().
781 *
782 * You can also use spi_alloc_device() and spi_add_device() to use a two
783 * stage registration sequence for each spi_device. This gives the caller
784 * some more control over the spi_device structure before it is registered,
785 * but requires that caller to initialize fields that would otherwise
786 * be defined using the board info.
781 */ 787 */
782extern struct spi_device * 788extern struct spi_device *
789spi_alloc_device(struct spi_master *master);
790
791extern int
792spi_add_device(struct spi_device *spi);
793
794extern struct spi_device *
783spi_new_device(struct spi_master *, struct spi_board_info *); 795spi_new_device(struct spi_master *, struct spi_board_info *);
784 796
785static inline void 797static inline void