All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
	spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Cc: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: [PATCH 2/2] Blackfin SPI Driver: implement spi_lock_bus(), spi_unlock_bus() in blackfin spi controller driver.
Date: Tue, 18 Nov 2008 15:57:47 +0800	[thread overview]
Message-ID: <1226995067-4484-3-git-send-email-cooloney@kernel.org> (raw)
In-Reply-To: <1226995067-4484-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

From: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>

Signed-off-by: Yi Li <yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Bryan Wu <cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
 drivers/spi/spi_bfin5xx.c |   81 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 0e3102a..28dd0fe 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -45,6 +45,8 @@ MODULE_LICENSE("GPL");
 #define QUEUE_RUNNING	0
 #define QUEUE_STOPPED	1
 
+#define BFIN_SPI_LOCK 1
+
 struct driver_data {
 	/* Driver model hookup */
 	struct platform_device *pdev;
@@ -68,7 +70,10 @@ struct driver_data {
 	struct list_head queue;
 	int busy;
 	int run;
-
+#ifdef BFIN_SPI_LOCK
+	/* SPI bus is lock by a slave for exclusive access */
+	int locked;
+#endif
 	/* Message Transfer pump */
 	struct tasklet_struct pump_transfers;
 
@@ -932,6 +937,10 @@ static void pump_messages(struct work_struct *work)
 {
 	struct driver_data *drv_data;
 	unsigned long flags;
+#ifdef BFIN_SPI_LOCK
+	int locked_cs = -1;
+	struct spi_message *next_msg = NULL, *msg = NULL;
+#endif
 
 	drv_data = container_of(work, struct driver_data, pump_messages);
 
@@ -950,10 +959,35 @@ static void pump_messages(struct work_struct *work)
 		return;
 	}
 
+#ifdef BFIN_SPI_LOCK
+	/* Extract head of queue */
+	next_msg = list_entry(drv_data->queue.next,
+		struct spi_message, queue);
+
+	if (drv_data->locked)
+		locked_cs = drv_data->locked;
+
+	/* Someone has locked the bus */
+	if (drv_data->locked && next_msg->spi->chip_select != locked_cs) {
+		list_for_each_entry(msg, &drv_data->queue, queue) {
+			if (msg->spi->chip_select == locked_cs) {
+				next_msg = msg;
+				break;
+			}
+		}
+		/* Do nothing even if there are messages for other devices */
+		if (next_msg->spi->chip_select != locked_cs) {
+			drv_data->busy = 0;
+			spin_unlock_irqrestore(&drv_data->lock, flags);
+			return;
+		}
+	}
+	drv_data->cur_msg = next_msg;
+#else
 	/* Extract head of queue */
 	drv_data->cur_msg = list_entry(drv_data->queue.next,
-				       struct spi_message, queue);
-
+		struct spi_message, queue);
+#endif
 	/* Setup the SSP using the per chip configuration */
 	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
 	restore_state(drv_data);
@@ -982,6 +1016,39 @@ static void pump_messages(struct work_struct *work)
 }
 
 /*
+ * lock the spi bus for exclusive access
+ */
+static int lock_bus(struct spi_device *spi)
+{
+#ifdef BFIN_SPI_LOCK
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (drv_data->locked) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ENOLCK;
+	}
+	drv_data->locked = spi->chip_select;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+#endif
+	return 0;
+}
+
+static int unlock_bus(struct spi_device *spi)
+{
+#ifdef BFIN_SPI_LOCK
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	drv_data->locked = 0;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+#endif
+	return 0;
+}
+
+/*
  * got a msg to transfer, queue it in drv_data->queue.
  * And kick off message pumper
  */
@@ -1188,6 +1255,9 @@ static inline int init_queue(struct driver_data *drv_data)
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
 
+#ifdef BFIN_SPI_LOCK
+	drv_data->locked = 0;
+#endif
 	drv_data->run = QUEUE_STOPPED;
 	drv_data->busy = 0;
 
@@ -1235,6 +1305,9 @@ static inline int stop_queue(struct driver_data *drv_data)
 
 	spin_lock_irqsave(&drv_data->lock, flags);
 
+#ifdef BFIN_SPI_LOCK
+	drv_data->locked = 0;
+#endif
 	/*
 	 * This is a bit lame, but is optimized for the common execution path.
 	 * A wait_queue on the drv_data->busy could be used, but then the common
@@ -1298,6 +1371,8 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
 	master->cleanup = cleanup;
 	master->setup = setup;
 	master->transfer = transfer;
+	master->lock_bus = lock_bus;
+	master->unlock_bus = unlock_bus;
 
 	/* Find and map our resources */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.5.6.3

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/

WARNING: multiple messages have this Message-ID (diff)
From: Bryan Wu <cooloney@kernel.org>
To: dbrownell@users.sourceforge.net, spi-devel-general@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org, Yi Li <yi.li@analog.com>,
	Bryan Wu <cooloney@kernel.org>
Subject: [PATCH 2/2] Blackfin SPI Driver: implement spi_lock_bus(), spi_unlock_bus() in blackfin spi controller driver.
Date: Tue, 18 Nov 2008 15:57:47 +0800	[thread overview]
Message-ID: <1226995067-4484-3-git-send-email-cooloney@kernel.org> (raw)
In-Reply-To: <1226995067-4484-1-git-send-email-cooloney@kernel.org>

From: Yi Li <yi.li@analog.com>

Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
---
 drivers/spi/spi_bfin5xx.c |   81 +++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 0e3102a..28dd0fe 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -45,6 +45,8 @@ MODULE_LICENSE("GPL");
 #define QUEUE_RUNNING	0
 #define QUEUE_STOPPED	1
 
+#define BFIN_SPI_LOCK 1
+
 struct driver_data {
 	/* Driver model hookup */
 	struct platform_device *pdev;
@@ -68,7 +70,10 @@ struct driver_data {
 	struct list_head queue;
 	int busy;
 	int run;
-
+#ifdef BFIN_SPI_LOCK
+	/* SPI bus is lock by a slave for exclusive access */
+	int locked;
+#endif
 	/* Message Transfer pump */
 	struct tasklet_struct pump_transfers;
 
@@ -932,6 +937,10 @@ static void pump_messages(struct work_struct *work)
 {
 	struct driver_data *drv_data;
 	unsigned long flags;
+#ifdef BFIN_SPI_LOCK
+	int locked_cs = -1;
+	struct spi_message *next_msg = NULL, *msg = NULL;
+#endif
 
 	drv_data = container_of(work, struct driver_data, pump_messages);
 
@@ -950,10 +959,35 @@ static void pump_messages(struct work_struct *work)
 		return;
 	}
 
+#ifdef BFIN_SPI_LOCK
+	/* Extract head of queue */
+	next_msg = list_entry(drv_data->queue.next,
+		struct spi_message, queue);
+
+	if (drv_data->locked)
+		locked_cs = drv_data->locked;
+
+	/* Someone has locked the bus */
+	if (drv_data->locked && next_msg->spi->chip_select != locked_cs) {
+		list_for_each_entry(msg, &drv_data->queue, queue) {
+			if (msg->spi->chip_select == locked_cs) {
+				next_msg = msg;
+				break;
+			}
+		}
+		/* Do nothing even if there are messages for other devices */
+		if (next_msg->spi->chip_select != locked_cs) {
+			drv_data->busy = 0;
+			spin_unlock_irqrestore(&drv_data->lock, flags);
+			return;
+		}
+	}
+	drv_data->cur_msg = next_msg;
+#else
 	/* Extract head of queue */
 	drv_data->cur_msg = list_entry(drv_data->queue.next,
-				       struct spi_message, queue);
-
+		struct spi_message, queue);
+#endif
 	/* Setup the SSP using the per chip configuration */
 	drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi);
 	restore_state(drv_data);
@@ -982,6 +1016,39 @@ static void pump_messages(struct work_struct *work)
 }
 
 /*
+ * lock the spi bus for exclusive access
+ */
+static int lock_bus(struct spi_device *spi)
+{
+#ifdef BFIN_SPI_LOCK
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (drv_data->locked) {
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+		return -ENOLCK;
+	}
+	drv_data->locked = spi->chip_select;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+#endif
+	return 0;
+}
+
+static int unlock_bus(struct spi_device *spi)
+{
+#ifdef BFIN_SPI_LOCK
+	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	drv_data->locked = 0;
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+#endif
+	return 0;
+}
+
+/*
  * got a msg to transfer, queue it in drv_data->queue.
  * And kick off message pumper
  */
@@ -1188,6 +1255,9 @@ static inline int init_queue(struct driver_data *drv_data)
 	INIT_LIST_HEAD(&drv_data->queue);
 	spin_lock_init(&drv_data->lock);
 
+#ifdef BFIN_SPI_LOCK
+	drv_data->locked = 0;
+#endif
 	drv_data->run = QUEUE_STOPPED;
 	drv_data->busy = 0;
 
@@ -1235,6 +1305,9 @@ static inline int stop_queue(struct driver_data *drv_data)
 
 	spin_lock_irqsave(&drv_data->lock, flags);
 
+#ifdef BFIN_SPI_LOCK
+	drv_data->locked = 0;
+#endif
 	/*
 	 * This is a bit lame, but is optimized for the common execution path.
 	 * A wait_queue on the drv_data->busy could be used, but then the common
@@ -1298,6 +1371,8 @@ static int __init bfin5xx_spi_probe(struct platform_device *pdev)
 	master->cleanup = cleanup;
 	master->setup = setup;
 	master->transfer = transfer;
+	master->lock_bus = lock_bus;
+	master->unlock_bus = unlock_bus;
 
 	/* Find and map our resources */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.5.6.3

  parent reply	other threads:[~2008-11-18  7:57 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-18  7:57 [PATCH 0/2] Introduce SPI locking bus interface to SPI framework Bryan Wu
2008-11-18  7:57 ` Bryan Wu
     [not found] ` <1226995067-4484-1-git-send-email-cooloney-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2008-11-18  7:57   ` [PATCH 1/2] spi: Add two new APIs spi_lock_bus() and spi_unlock_bus() to spi framework Bryan Wu
2008-11-18  7:57     ` Bryan Wu
2008-11-18  7:57   ` Bryan Wu [this message]
2008-11-18  7:57     ` [PATCH 2/2] Blackfin SPI Driver: implement spi_lock_bus(), spi_unlock_bus() in blackfin spi controller driver Bryan Wu
2009-02-05 14:34   ` [PATCH 0/2] Introduce SPI locking bus interface to SPI framework Bryan Wu
2009-02-05 14:34     ` [spi-devel-general] " Bryan Wu

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=1226995067-4484-3-git-send-email-cooloney@kernel.org \
    --to=cooloney-dgejt+ai2ygdnm+yrofe0a@public.gmane.org \
    --cc=dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    --cc=yi.li-OyLXuOCK7orQT0dZR+AlfA@public.gmane.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.