From: Grant Likely <grant.likely@secretlab.ca>
To: linuxppc-dev@ozlabs.org, spi-devel-general@lists.sourceforge.net,
linux-kernel@vger.kernel.org, dbrownell@users.sourceforge.net
Cc: fabrizio.garetto@gmail.com, jonsmirl@gmail.com
Subject: [PATCH 2/4] spi: split up spi_new_device() to allow two stage registration.
Date: Fri, 16 May 2008 13:36:08 -0600 [thread overview]
Message-ID: <20080516193608.28030.34968.stgit@trillian.secretlab.ca> (raw)
In-Reply-To: <20080516193054.28030.35126.stgit@trillian.secretlab.ca>
From: Grant Likely <grant.likely@secretlab.ca>
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 patch splits the allocation and registration portions of code out
of spi_new_device() and creates three new functions; spi_alloc_device(),
spi_register_device(), and spi_device_release(). 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 an 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>
---
drivers/spi/spi.c | 150 +++++++++++++++++++++++++++++++++--------------
include/linux/spi/spi.h | 13 ++++
2 files changed, 119 insertions(+), 44 deletions(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index bdf1b70..9c7a84d 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -178,6 +178,107 @@ struct boardinfo {
static LIST_HEAD(board_list);
static DEFINE_MUTEX(board_lock);
+/**
+ * spi_alloc_device - Allocate a new SPI device
+ * @master: Controller to which device is connected
+ * Context: can sleep
+ *
+ * Allows a driver to allocate and initialize and spi_device without
+ * registering it immediately. This allows a driver to directly
+ * fill the spi_device with device parameters before calling
+ * spi_register_device() on it.
+ *
+ * Caller is responsible to call spi_register_device on the returned
+ * spi_device structure.
+ *
+ * Returns a pointer to the new device, or NULL.
+ */
+struct spi_device *spi_alloc_device(struct spi_master *master)
+{
+ struct spi_device *spi;
+ struct device *dev = master->dev.parent;
+
+ if (!spi_master_get(master))
+ return NULL;
+
+ spi = kzalloc(sizeof *spi, GFP_KERNEL);
+ if (!spi) {
+ dev_err(dev, "cannot alloc spi_device\n");
+ spi_master_put(master);
+ return NULL;
+ }
+
+ spi->master = master;
+ spi->dev.parent = dev;
+ spi->dev.bus = &spi_bus_type;
+ spi->dev.release = spidev_release;
+ return spi;
+}
+EXPORT_SYMBOL_GPL(spi_alloc_device);
+
+/**
+ * spi_register_device - Register an spi_device allocated with spi_alloc_device
+ * @spi: spi_device to register
+ *
+ * Companion function to spi_alloc_device. Devices allocated with
+ * spi_alloc_device can be registerd onto the spi bus with this function.
+ *
+ * Returns 0 on success; non-zero on failure
+ */
+int spi_register_device(struct spi_device *spi)
+{
+ struct device *dev = spi->master->dev.parent;
+ int status;
+
+ /* Chipselects are numbered 0..max; validate. */
+ if (spi->chip_select >= spi->master->num_chipselect) {
+ dev_err(dev, "cs%d > max %d\n",
+ spi->chip_select,
+ spi->master->num_chipselect);
+ return -EINVAL;
+ }
+
+ /* Set the bus ID string */
+ snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
+ "%s.%u", spi->master->dev.bus_id,
+ spi->chip_select);
+
+ /* drivers may modify this initial i/o setup */
+ status = spi->master->setup(spi);
+ if (status < 0) {
+ dev_err(dev, "can't %s %s, status %d\n",
+ "setup", spi->dev.bus_id, status);
+ return status;
+ }
+
+ /* driver core catches callers that misbehave by defining
+ * devices that already exist.
+ */
+ status = device_register(&spi->dev);
+ if (status < 0) {
+ dev_err(dev, "can't %s %s, status %d\n",
+ "add", spi->dev.bus_id, status);
+ return status;
+ }
+
+ dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_register_device);
+
+/**
+ * spi_device_release - Free an allocated spi_device structure
+ * @spi: spi device to free
+ *
+ * Call this to free an spi_device allocated with spi_alloc_device(). Caller
+ * is responsible to ensure that the device has been unregistered first.
+ */
+void spi_device_release(struct spi_device *spi)
+{
+ spi_master_put(spi->master);
+ kfree(spi);
+}
+EXPORT_SYMBOL_GPL(spi_device_release);
/**
* spi_new_device - instantiate one new SPI device
@@ -197,7 +298,6 @@ struct spi_device *spi_new_device(struct spi_master *master,
struct spi_board_info *chip)
{
struct spi_device *proxy;
- struct device *dev = master->dev.parent;
int status;
/* NOTE: caller did any chip->bus_num checks necessary.
@@ -207,64 +307,26 @@ struct spi_device *spi_new_device(struct spi_master *master,
* suggests syslogged diagnostics are best here (ugh).
*/
- /* Chipselects are numbered 0..max; validate. */
- if (chip->chip_select >= master->num_chipselect) {
- dev_err(dev, "cs%d > max %d\n",
- chip->chip_select,
- master->num_chipselect);
- return NULL;
- }
-
- if (!spi_master_get(master))
+ proxy = spi_alloc_device(master);
+ if (!proxy)
return NULL;
- proxy = kzalloc(sizeof *proxy, GFP_KERNEL);
- if (!proxy) {
- dev_err(dev, "can't alloc dev for cs%d\n",
- chip->chip_select);
- goto fail;
- }
- proxy->master = master;
proxy->chip_select = chip->chip_select;
proxy->max_speed_hz = chip->max_speed_hz;
proxy->mode = chip->mode;
proxy->irq = chip->irq;
strncpy(proxy->modalias, chip->modalias, KOBJ_NAME_LEN);
-
- snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
- "%s.%u", master->dev.bus_id,
- chip->chip_select);
- proxy->dev.parent = dev;
- proxy->dev.bus = &spi_bus_type;
proxy->dev.platform_data = (void *) chip->platform_data;
proxy->controller_data = chip->controller_data;
proxy->controller_state = NULL;
- proxy->dev.release = spidev_release;
- /* drivers may modify this initial i/o setup */
- status = master->setup(proxy);
+ status = spi_register_device(proxy);
if (status < 0) {
- dev_err(dev, "can't %s %s, status %d\n",
- "setup", proxy->dev.bus_id, status);
- goto fail;
+ spi_device_release(proxy);
+ return NULL;
}
- /* driver core catches callers that misbehave by defining
- * devices that already exist.
- */
- status = device_register(&proxy->dev);
- if (status < 0) {
- dev_err(dev, "can't %s %s, status %d\n",
- "add", proxy->dev.bus_id, status);
- goto fail;
- }
- dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id);
return proxy;
-
-fail:
- spi_master_put(master);
- kfree(proxy);
- return NULL;
}
EXPORT_SYMBOL_GPL(spi_new_device);
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 38a080b..ca7c933 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -778,8 +778,21 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n)
* use spi_new_device() to describe each device. You can also call
* spi_unregister_device() to start making that device vanish, but
* normally that would be handled by spi_unregister_master().
+ *
+ * You can also use spi_alloc_device() and spi_register_device() to
+ * for a two stage registration of an SPI device. This gives the caller
+ * some more control over the spi_device structure before it is registered
*/
extern struct spi_device *
+spi_alloc_device(struct spi_master *master);
+
+extern int
+spi_register_device(struct spi_device *spi);
+
+extern void
+spi_device_release(struct spi_device *spi);
+
+extern struct spi_device *
spi_new_device(struct spi_master *, struct spi_board_info *);
static inline void
next prev parent reply other threads:[~2008-05-16 19:36 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-16 19:35 [RFC PATCH 0/4] Describe SPI devices in the OF device tree and add mpc5200-spi driver Grant Likely
2008-05-16 19:36 ` [PATCH 1/4] spi: Change modalias from a pointer to a character array Grant Likely
2008-05-16 19:36 ` Grant Likely [this message]
[not found] ` <20080516193608.28030.34968.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-05-22 0:17 ` [PATCH 2/4] spi: split up spi_new_device() to allow two stage registration David Brownell
[not found] ` <200805211717.13206.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 6:43 ` Grant Likely
[not found] ` <fa686aa40805232343x20031560j5659d203e25f494-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 6:54 ` Grant Likely
[not found] ` <fa686aa40805232354g147acfcdx4753fce1a448ceb7-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-06-30 4:08 ` David Brownell
2008-06-17 7:28 ` Grant Likely
[not found] ` <fa686aa40806170028t2ccb679k22d2d3cea793ebc1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-06-30 4:10 ` David Brownell
2008-05-16 19:36 ` [PATCH 3/4] spi: Add OF binding support for SPI busses Grant Likely
[not found] ` <20080516193613.28030.13950.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-05-16 20:47 ` Randy Dunlap
2008-05-16 20:51 ` Grant Likely
2008-05-16 22:03 ` Anton Vorontsov
2008-05-16 22:14 ` Grant Likely
[not found] ` <fa686aa40805161514r513d0eebt380a76f64abe8434-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 22:49 ` Anton Vorontsov
2008-05-17 5:02 ` Grant Likely
[not found] ` <fa686aa40805162202m336aade4qd6cfa5b17d6f3892-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-22 1:16 ` David Brownell
[not found] ` <200805211816.10753.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 6:24 ` Grant Likely
2008-05-19 13:17 ` Guennadi Liakhovetski
2008-05-19 15:57 ` Grant Likely
2008-05-19 16:30 ` Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0805191811510.29559-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-05-20 5:13 ` Grant Likely
2008-05-20 15:26 ` Guennadi Liakhovetski
[not found] ` <Pine.LNX.4.64.0805201650280.5283-0199iw4Nj15frtckUFj5Ag@public.gmane.org>
2008-05-20 15:48 ` Grant Likely
2008-05-21 19:11 ` Segher Boessenkool
[not found] ` <716a0f1b6c9a544b480c06a329072483-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>
2008-05-21 19:33 ` Grant Likely
[not found] ` <fa686aa40805211233h72a258bpf8c945b9f662d6ee-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-23 2:26 ` David Brownell
[not found] ` <200805221926.24112.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 6:25 ` Grant Likely
[not found] ` <fa686aa40805232325w65d4f706i50798121a8cce263-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 7:13 ` David Brownell
2008-05-19 17:09 ` Gary Jennejohn
[not found] ` <20080519190900.01ec3b2a-f7AvneZ2CE0iXleZOAq1AWD2FQJk+8+b@public.gmane.org>
2008-05-19 17:19 ` Anton Vorontsov
2008-05-21 15:19 ` Anton Vorontsov
[not found] ` <20080521151928.GA28857-PHTr8nzUCjejyJ0x5qLZdcN33GVbZNy3@public.gmane.org>
2008-05-23 2:05 ` David Brownell
[not found] ` <200805221905.32288.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 6:26 ` Grant Likely
[not found] ` <fa686aa40805232326w35f455d1s274899160d47eccb-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 16:50 ` Grant Likely
[not found] ` <fa686aa40805240950ocd16b97y308a54c68efa28ef-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 17:14 ` Jochen Friedrich
[not found] ` <48384D13.6010608-NIgtFMG+Po8@public.gmane.org>
2008-05-24 17:33 ` Grant Likely
[not found] ` <fa686aa40805241033x128c30b0v826717cc879a712e-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 17:45 ` David Brownell
[not found] ` <200805241045.47448.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-25 4:56 ` Grant Likely
2008-05-24 17:43 ` David Brownell
[not found] ` <200805221915.59878.david-b@pacbell.net>
[not found] ` <200805221915.59878.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 6:31 ` Grant Likely
[not found] ` <fa686aa40805232331p1bf2c1bcn8c46c21a094ef01e-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-24 16:50 ` David Brownell
[not found] ` <200805240950.43394.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-05-24 16:53 ` Grant Likely
2008-05-16 19:36 ` [PATCH 4/4] [CSB] Add new mpc5200-spi (non-psc) device driver Grant Likely
2008-05-16 19:42 ` Grant Likely
[not found] ` <20080516193054.28030.35126.stgit-8FIgwK2HfyId2tlXD8uQ6/kpB+XfMlBf@public.gmane.org>
2008-05-16 20:27 ` [RFC PATCH 0/4] Describe SPI devices in the OF device tree and add mpc5200-spi driver Jon Smirl
[not found] ` <9e4733910805161327u4c42fd1dg5b09319d89db447c-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 20:48 ` Grant Likely
[not found] ` <fa686aa40805161348t52b94956w112ef6926ff30892-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 21:25 ` Jon Smirl
[not found] ` <9e4733910805161425i2d6cc034y3377af053a4198b5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 21:32 ` Grant Likely
[not found] ` <fa686aa40805161432w6b5243f9nb0d0c32a87d86d02-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-05-16 21:42 ` Jon Smirl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080516193608.28030.34968.stgit@trillian.secretlab.ca \
--to=grant.likely@secretlab.ca \
--cc=dbrownell@users.sourceforge.net \
--cc=fabrizio.garetto@gmail.com \
--cc=jonsmirl@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=spi-devel-general@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).