linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Add SPI driver for MPC5121 PSC SPI
@ 2010-04-30 13:21 Anatolij Gustschin
  2010-04-30 13:21 ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Anatolij Gustschin
  0 siblings, 1 reply; 4+ messages in thread
From: Anatolij Gustschin @ 2010-04-30 13:21 UTC (permalink / raw)
  To: spi-devel-general, linuxppc-dev
  Cc: David Brownell, Wolfgang Denk, Detelv Zundel

Anatolij Gustschin (2):
  powerpc/mpc5121: move PSC FIFO memory init to platform code
  spi: Add SPI master driver for MPC5121 PSC

 arch/powerpc/include/asm/mpc52xx_psc.h       |    1 +
 arch/powerpc/platforms/512x/mpc512x_shared.c |   78 ++++
 drivers/serial/mpc52xx_uart.c                |   69 ---
 drivers/spi/Kconfig                          |    7 +
 drivers/spi/Makefile                         |    1 +
 drivers/spi/mpc512x_psc_spi.c                |  576 ++++++++++++++++++++++++++
 6 files changed, 663 insertions(+), 69 deletions(-)
 create mode 100644 drivers/spi/mpc512x_psc_spi.c

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code
  2010-04-30 13:21 [PATCH 0/2] Add SPI driver for MPC5121 PSC SPI Anatolij Gustschin
@ 2010-04-30 13:21 ` Anatolij Gustschin
  2010-04-30 13:21   ` [PATCH 2/2] spi: Add SPI master driver for MPC5121 PSC Anatolij Gustschin
  2010-04-30 13:42   ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Grant Likely
  0 siblings, 2 replies; 4+ messages in thread
From: Anatolij Gustschin @ 2010-04-30 13:21 UTC (permalink / raw)
  To: spi-devel-general, linuxppc-dev
  Cc: David Brownell, Wolfgang Denk, Detelv Zundel

Since PSC could also be used in other modes than UART mode
we move PSC FIFO memory initialization from serial driver to
common platform code. The initialized FIFO memory slices may
not overlap, so the most easy way would be to configure them
all at once at init time for all PSC devices. This is now done
by this patch.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 arch/powerpc/platforms/512x/mpc512x_shared.c |   78 ++++++++++++++++++++++++++
 drivers/serial/mpc52xx_uart.c                |   69 -----------------------
 2 files changed, 78 insertions(+), 69 deletions(-)

diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index 796080c..a717466 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -26,6 +26,7 @@
 #include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/mpc5121.h>
+#include <asm/mpc52xx_psc.h>
 
 #include "mpc512x.h"
 
@@ -369,9 +370,86 @@ void __init mpc512x_declare_of_platform_devices(void)
 	}
 }
 
+#define DEFAULT_FIFO_SIZE 16
+
+static unsigned int __init get_fifo_size(struct device_node *np,
+					 char *prop_name)
+{
+	const unsigned int *fp;
+
+	fp = of_get_property(np, prop_name, NULL);
+	if (fp)
+		return *fp;
+
+	pr_warning("no %s property in %s node, defaulting to %d\n",
+		   prop_name, np->full_name, DEFAULT_FIFO_SIZE);
+
+	return DEFAULT_FIFO_SIZE;
+}
+
+#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
+		    ((u32)(_base) + sizeof(struct mpc52xx_psc)))
+
+/* Init PSC FIFO space for TX and RX slices */
+void __init mpc512x_psc_fifo_init(void)
+{
+	struct device_node *np;
+	void __iomem *psc;
+	unsigned int tx_fifo_size;
+	unsigned int rx_fifo_size;
+	int fifobase = 0; /* current fifo address in 32 bit words */
+
+	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+		tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
+		rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");
+
+		/* size in register is in 4 byte units */
+		tx_fifo_size /= 4;
+		rx_fifo_size /= 4;
+		if (!tx_fifo_size)
+			tx_fifo_size = 1;
+		if (!rx_fifo_size)
+			rx_fifo_size = 1;
+
+		psc = of_iomap(np, 0);
+		if (!psc) {
+			pr_err("%s: Can't map %s device\n",
+				__func__, np->full_name);
+			continue;
+		}
+
+		/* FIFO space is 4KiB, check if requested size is available */
+		if ((fifobase + tx_fifo_size + rx_fifo_size) > 0x1000) {
+			pr_err("%s: no fifo space available for %s\n",
+				__func__, np->full_name);
+			iounmap(psc);
+			/*
+			 * chances are that another device requests less
+			 * fifo space, so we continue.
+			 */
+			continue;
+		}
+
+		/* set tx and rx fifo size registers */
+		out_be32(&FIFOC(psc)->txsz, (fifobase << 16) | tx_fifo_size);
+		fifobase += tx_fifo_size;
+		out_be32(&FIFOC(psc)->rxsz, (fifobase << 16) | rx_fifo_size);
+		fifobase += rx_fifo_size;
+
+		/* reset and enable the slices */
+		out_be32(&FIFOC(psc)->txcmd, 0x80);
+		out_be32(&FIFOC(psc)->txcmd, 0x01);
+		out_be32(&FIFOC(psc)->rxcmd, 0x80);
+		out_be32(&FIFOC(psc)->rxcmd, 0x01);
+
+		iounmap(psc);
+	}
+}
+
 void __init mpc512x_init(void)
 {
 	mpc512x_declare_of_platform_devices();
 	mpc5121_clk_init();
 	mpc512x_restart_init();
+	mpc512x_psc_fifo_init();
 }
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 3119fdd..843e7fb 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -430,34 +430,10 @@ static unsigned long mpc512x_getuartclk(void *p)
 	return mpc5xxx_get_bus_frequency(p);
 }
 
-#define DEFAULT_FIFO_SIZE 16
-
-static unsigned int __init get_fifo_size(struct device_node *np,
-					 char *fifo_name)
-{
-	const unsigned int *fp;
-
-	fp = of_get_property(np, fifo_name, NULL);
-	if (fp)
-		return *fp;
-
-	pr_warning("no %s property in %s node, defaulting to %d\n",
-		   fifo_name, np->full_name, DEFAULT_FIFO_SIZE);
-
-	return DEFAULT_FIFO_SIZE;
-}
-
-#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
-		    ((u32)(_base) + sizeof(struct mpc52xx_psc)))
-
 /* Init PSC FIFO Controller */
 static int __init mpc512x_psc_fifoc_init(void)
 {
 	struct device_node *np;
-	void __iomem *psc;
-	unsigned int tx_fifo_size;
-	unsigned int rx_fifo_size;
-	int fifobase = 0; /* current fifo address in 32 bit words */
 
 	np = of_find_compatible_node(NULL, NULL,
 				     "fsl,mpc5121-psc-fifo");
@@ -480,51 +456,6 @@ static int __init mpc512x_psc_fifoc_init(void)
 		return -ENODEV;
 	}
 
-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc-uart") {
-		tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
-		rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");
-
-		/* size in register is in 4 byte units */
-		tx_fifo_size /= 4;
-		rx_fifo_size /= 4;
-		if (!tx_fifo_size)
-			tx_fifo_size = 1;
-		if (!rx_fifo_size)
-			rx_fifo_size = 1;
-
-		psc = of_iomap(np, 0);
-		if (!psc) {
-			pr_err("%s: Can't map %s device\n",
-				__func__, np->full_name);
-			continue;
-		}
-
-		/* FIFO space is 4KiB, check if requested size is available */
-		if ((fifobase + tx_fifo_size + rx_fifo_size) > 0x1000) {
-			pr_err("%s: no fifo space available for %s\n",
-				__func__, np->full_name);
-			iounmap(psc);
-			/*
-			 * chances are that another device requests less
-			 * fifo space, so we continue.
-			 */
-			continue;
-		}
-		/* set tx and rx fifo size registers */
-		out_be32(&FIFOC(psc)->txsz, (fifobase << 16) | tx_fifo_size);
-		fifobase += tx_fifo_size;
-		out_be32(&FIFOC(psc)->rxsz, (fifobase << 16) | rx_fifo_size);
-		fifobase += rx_fifo_size;
-
-		/* reset and enable the slices */
-		out_be32(&FIFOC(psc)->txcmd, 0x80);
-		out_be32(&FIFOC(psc)->txcmd, 0x01);
-		out_be32(&FIFOC(psc)->rxcmd, 0x80);
-		out_be32(&FIFOC(psc)->rxcmd, 0x01);
-
-		iounmap(psc);
-	}
-
 	return 0;
 }
 
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] spi: Add SPI master driver for MPC5121 PSC
  2010-04-30 13:21 ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Anatolij Gustschin
@ 2010-04-30 13:21   ` Anatolij Gustschin
  2010-04-30 13:42   ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Grant Likely
  1 sibling, 0 replies; 4+ messages in thread
From: Anatolij Gustschin @ 2010-04-30 13:21 UTC (permalink / raw)
  To: spi-devel-general, linuxppc-dev
  Cc: David Brownell, Wolfgang Denk, Detelv Zundel

Signed-off-by: John Rigby <jcrigby@gmail.com>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 arch/powerpc/include/asm/mpc52xx_psc.h |    1 +
 drivers/spi/Kconfig                    |    7 +
 drivers/spi/Makefile                   |    1 +
 drivers/spi/mpc512x_psc_spi.c          |  576 ++++++++++++++++++++++++++++++++
 4 files changed, 585 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/mpc512x_psc_spi.c

diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h b/arch/powerpc/include/asm/mpc52xx_psc.h
index 42561f4..ecc4fc6 100644
--- a/arch/powerpc/include/asm/mpc52xx_psc.h
+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
@@ -248,6 +248,7 @@ struct mpc52xx_psc_fifo {
 	u16		tflwfptr;	/* PSC + 0x9e */
 };
 
+#define MPC512x_PSC_FIFO_EOF		0x100
 #define MPC512x_PSC_FIFO_RESET_SLICE	0x80
 #define MPC512x_PSC_FIFO_ENABLE_SLICE	0x01
 #define MPC512x_PSC_FIFO_ENABLE_DMA	0x04
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a191fa2..317bb01 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -165,6 +165,13 @@ config SPI_MPC52xx_PSC
 	  This enables using the Freescale MPC52xx Programmable Serial
 	  Controller in master SPI mode.
 
+config SPI_MPC512x_PSC
+	tristate "Freescale MPC512x PSC SPI controller"
+	depends on SPI_MASTER && PPC_MPC512x
+	help
+	  This enables using the Freescale MPC5121 Programmable Serial
+	  Controller in SPI master mode.
+
 config SPI_MPC8xxx
 	tristate "Freescale MPC8xxx SPI controller"
 	depends on FSL_SOC
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index d7d0f89..b989ffb 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
 obj-$(CONFIG_SPI_ORION)			+= orion_spi.o
 obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
+obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
 obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
new file mode 100644
index 0000000..28a126d
--- /dev/null
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -0,0 +1,576 @@
+/*
+ * MPC512x PSC in SPI mode driver.
+ *
+ * Copyright (C) 2007,2008 Freescale Semiconductor Inc.
+ * Original port from 52xx driver:
+ *	Hongjun Chen <hong-jun.chen@freescale.com>
+ *
+ * Fork of mpc52xx_psc_spi.c:
+ *	Copyright (C) 2006 TOPTICA Photonics AG., Dragos Carp
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc52xx_psc.h>
+
+struct mpc512x_psc_spi {
+	void (*cs_control)(struct spi_device *spi, bool on);
+	u32 sysclk;
+
+	/* driver internal data */
+	struct mpc52xx_psc __iomem *psc;
+	struct mpc512x_psc_fifo __iomem *fifo;
+	unsigned int irq;
+	u8 bits_per_word;
+	u8 busy;
+	u32 mclk;
+	u8 eofbyte;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;	/* Message queue lock */
+
+	struct completion done;
+};
+
+/* controller state */
+struct mpc512x_psc_spi_cs {
+	int bits_per_word;
+	int speed_hz;
+};
+
+/* set clock freq, clock ramp, bits per work
+ * if t is NULL then reset the values to the default values
+ */
+static int mpc512x_psc_spi_transfer_setup(struct spi_device *spi,
+					  struct spi_transfer *t)
+{
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+
+	cs->speed_hz = (t && t->speed_hz)
+	    ? t->speed_hz : spi->max_speed_hz;
+	cs->bits_per_word = (t && t->bits_per_word)
+	    ? t->bits_per_word : spi->bits_per_word;
+	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
+	return 0;
+}
+
+static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	u32 sicr;
+	u32 ccr;
+	u16 bclkdiv;
+
+	sicr = in_be32(&psc->sicr);
+
+	/* Set clock phase and polarity */
+	if (spi->mode & SPI_CPHA)
+		sicr |= 0x00001000;
+	else
+		sicr &= ~0x00001000;
+
+	if (spi->mode & SPI_CPOL)
+		sicr |= 0x00002000;
+	else
+		sicr &= ~0x00002000;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		sicr |= 0x10000000;
+	else
+		sicr &= ~0x10000000;
+	out_be32(&psc->sicr, sicr);
+
+	ccr = in_be32(&psc->ccr);
+	ccr &= 0xFF000000;
+	if (cs->speed_hz)
+		bclkdiv = (mps->mclk / cs->speed_hz) - 1;
+	else
+		bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+
+	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
+	out_be32(&psc->ccr, ccr);
+	mps->bits_per_word = cs->bits_per_word;
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+
+	if (mps->cs_control)
+		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1);
+
+}
+
+/* extract and scale size field in txsz or rxsz */
+#define MPC512x_PSC_FIFO_SZ(sz) ((sz & 0x7ff) << 2);
+
+#define EOFBYTE 1
+
+static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
+					 struct spi_transfer *t)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+	size_t len = t->len;
+	u8 *tx_buf = (u8 *)t->tx_buf;
+	u8 *rx_buf = (u8 *)t->rx_buf;
+
+	if (!tx_buf && !rx_buf && t->len)
+		return -EINVAL;
+
+	/* Zero MR2 */
+	in_8(&psc->mode);
+	out_8(&psc->mode, 0x0);
+
+	while (len) {
+		int count;
+		int i;
+		u8 data;
+		size_t fifosz;
+		int rxcount;
+
+		/*
+		 * The number of bytes that can be sent at a time
+		 * depends on the fifo size.
+		 */
+		fifosz = MPC512x_PSC_FIFO_SZ(in_be32(&fifo->txsz));
+		count = min(fifosz, len);
+
+		for (i = count; i > 0; i--) {
+			data = tx_buf ? *tx_buf++ : 0;
+			if (len == EOFBYTE)
+				setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
+			out_8(&fifo->txdata_8, data);
+			len--;
+		}
+
+		INIT_COMPLETION(mps->done);
+
+		/* interrupt on tx fifo empty */
+		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
+		out_be32(&fifo->tximr, MPC512x_PSC_FIFO_EMPTY);
+
+		/* enable transmiter/receiver */
+		out_8(&psc->command,
+		      MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+
+		wait_for_completion(&mps->done);
+
+		mdelay(1);
+
+		/* rx fifo should have count bytes in it */
+		rxcount = in_be32(&fifo->rxcnt);
+		if (rxcount != count)
+			mdelay(1);
+
+		rxcount = in_be32(&fifo->rxcnt);
+		if (rxcount != count) {
+			dev_warn(&spi->dev, "expected %d bytes in rx fifo "
+				 "but got %d\n", count, rxcount);
+		}
+
+		rxcount = min(rxcount, count);
+		for (i = rxcount; i > 0; i--) {
+			data = in_8(&fifo->rxdata_8);
+			if (rx_buf)
+				*rx_buf++ = data;
+		}
+		while (in_be32(&fifo->rxcnt)) {
+			in_8(&fifo->rxdata_8);
+		}
+
+		out_8(&psc->command,
+		      MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	}
+	/* disable transmiter/receiver and fifo interrupt */
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+	out_be32(&fifo->tximr, 0);
+	return 0;
+}
+
+static void mpc512x_psc_spi_work(struct work_struct *work)
+{
+	struct mpc512x_psc_spi *mps = container_of(work,
+						   struct mpc512x_psc_spi,
+						   work);
+
+	spin_lock_irq(&mps->lock);
+	mps->busy = 1;
+	while (!list_empty(&mps->queue)) {
+		struct spi_message *m;
+		struct spi_device *spi;
+		struct spi_transfer *t = NULL;
+		unsigned cs_change;
+		int status;
+
+		m = container_of(mps->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mps->lock);
+
+		spi = m->spi;
+		cs_change = 1;
+		status = 0;
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->bits_per_word || t->speed_hz) {
+				status = mpc512x_psc_spi_transfer_setup(spi, t);
+				if (status < 0)
+					break;
+			}
+
+			if (cs_change)
+				mpc512x_psc_spi_activate_cs(spi);
+			cs_change = t->cs_change;
+
+			status = mpc512x_psc_spi_transfer_rxtx(spi, t);
+			if (status)
+				break;
+			m->actual_length += t->len;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (cs_change)
+				mpc512x_psc_spi_deactivate_cs(spi);
+		}
+
+		m->status = status;
+		m->complete(m->context);
+
+		if (status || !cs_change)
+			mpc512x_psc_spi_deactivate_cs(spi);
+
+		mpc512x_psc_spi_transfer_setup(spi, NULL);
+
+		spin_lock_irq(&mps->lock);
+	}
+	mps->busy = 0;
+	spin_unlock_irq(&mps->lock);
+}
+
+static int mpc512x_psc_spi_setup(struct spi_device *spi)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc512x_psc_spi_cs *cs = spi->controller_state;
+	unsigned long flags;
+
+	if (spi->bits_per_word % 8)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	cs->bits_per_word = spi->bits_per_word;
+	cs->speed_hz = spi->max_speed_hz;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	if (!mps->busy)
+		mpc512x_psc_spi_deactivate_cs(spi);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static int mpc512x_psc_spi_transfer(struct spi_device *spi,
+				    struct spi_message *m)
+{
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	list_add_tail(&m->queue, &mps->queue);
+	queue_work(mps->workqueue, &mps->work);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static void mpc512x_psc_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static int mpc512x_psc_spi_port_config(struct spi_master *master,
+				       struct mpc512x_psc_spi *mps)
+{
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+	struct clk *spiclk;
+	int ret = 0;
+	char name[32];
+	u32 sicr;
+	u32 ccr;
+	u16 bclkdiv;
+
+	sprintf(name, "psc%d_mclk", master->bus_num);
+	spiclk = clk_get(&master->dev, name);
+	clk_enable(spiclk);
+	mps->mclk = clk_get_rate(spiclk);
+	clk_put(spiclk);
+
+	/* Reset the PSC into a known state */
+	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	/* Disable psc interrupts all useful interrupts are in fifo */
+	out_be16(&psc->isr_imr.imr, 0);
+
+	/* Disable fifo interrupts, will be enabled later */
+	out_be32(&fifo->tximr, 0);
+	out_be32(&fifo->rximr, 0);
+
+	/* Setup fifo slice address and size */
+	/*out_be32(&fifo->txsz, 0x0fe00004);*/
+	/*out_be32(&fifo->rxsz, 0x0ff00004);*/
+
+	sicr =	0x01000000 |	/* SIM = 0001 -- 8 bit */
+		0x00800000 |	/* GenClk = 1 -- internal clk */
+		0x00008000 |	/* SPI = 1 */
+		0x00004000 |	/* MSTR = 1   -- SPI master */
+		0x00000800;	/* UseEOF = 1 -- SS low until EOF */
+
+	out_be32(&psc->sicr, sicr);
+
+	ccr = in_be32(&psc->ccr);
+	ccr &= 0xFF000000;
+	bclkdiv = (mps->mclk / 1000000) - 1;	/* default 1MHz */
+	ccr |= (((bclkdiv & 0xff) << 16) | (((bclkdiv >> 8) & 0xff) << 8));
+	out_be32(&psc->ccr, ccr);
+
+	/* Set 2ms DTL delay */
+	out_8(&psc->ctur, 0x00);
+	out_8(&psc->ctlr, 0x82);
+
+	/* we don't use the alarms */
+	out_be32(&fifo->rxalarm, 0xfff);
+	out_be32(&fifo->txalarm, 0);
+
+	/* Enable FIFO slices for Rx/Tx */
+	out_be32(&fifo->rxcmd,
+		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
+	out_be32(&fifo->txcmd,
+		 MPC512x_PSC_FIFO_ENABLE_SLICE | MPC512x_PSC_FIFO_ENABLE_DMA);
+
+	mps->bits_per_word = 8;
+
+	return ret;
+}
+
+static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)
+{
+	struct mpc512x_psc_spi *mps = (struct mpc512x_psc_spi *)dev_id;
+	struct mpc512x_psc_fifo __iomem *fifo = mps->fifo;
+
+	/* clear interrupt and wake up the work queue */
+	if (in_be32(&fifo->txisr) &
+	    in_be32(&fifo->tximr) & MPC512x_PSC_FIFO_EMPTY) {
+		out_be32(&fifo->txisr, MPC512x_PSC_FIFO_EMPTY);
+		out_be32(&fifo->tximr, 0);
+		complete(&mps->done);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/* bus_num is used only for the case dev->platform_data == NULL */
+static int __init mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
+					   u32 size, unsigned int irq,
+					   s16 bus_num)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc512x_psc_spi *mps;
+	struct spi_master *master;
+	int ret;
+	void *tempp;
+
+	master = spi_alloc_master(dev, sizeof *mps);
+	if (master == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, master);
+	mps = spi_master_get_devdata(master);
+	mps->irq = irq;
+
+	if (pdata == NULL) {
+		dev_err(dev, "probe called without platform data, no "
+			"cs_control function will be called\n");
+		mps->cs_control = NULL;
+		mps->sysclk = 0;
+		master->bus_num = bus_num;
+		master->num_chipselect = 255;
+	} else {
+		mps->cs_control = pdata->cs_control;
+		mps->sysclk = pdata->sysclk;
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->max_chipselect;
+	}
+
+	master->setup = mpc512x_psc_spi_setup;
+	master->transfer = mpc512x_psc_spi_transfer;
+	master->cleanup = mpc512x_psc_spi_cleanup;
+
+	tempp = ioremap(regaddr, size);
+	if (!tempp) {
+		dev_err(dev, "could not ioremap I/O port range\n");
+		ret = -EFAULT;
+		goto free_master;
+	}
+	mps->psc = tempp;
+	mps->fifo =
+		(struct mpc512x_psc_fifo *)(tempp + sizeof(struct mpc52xx_psc));
+
+	ret = request_irq(mps->irq, mpc512x_psc_spi_isr, IRQF_SHARED,
+			  "mpc512x-psc-spi", mps);
+	if (ret)
+		goto free_master;
+
+	ret = mpc512x_psc_spi_port_config(master, mps);
+	if (ret < 0)
+		goto free_irq;
+
+	spin_lock_init(&mps->lock);
+	init_completion(&mps->done);
+	INIT_WORK(&mps->work, mpc512x_psc_spi_work);
+	INIT_LIST_HEAD(&mps->queue);
+
+	mps->workqueue =
+		create_singlethread_workqueue(dev_name(master->dev.parent));
+	if (mps->workqueue == NULL) {
+		ret = -EBUSY;
+		goto free_irq;
+	}
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	return ret;
+
+unreg_master:
+	destroy_workqueue(mps->workqueue);
+free_irq:
+	free_irq(mps->irq, mps);
+free_master:
+	if (mps->psc)
+		iounmap(mps->psc);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int __exit mpc512x_psc_spi_do_remove(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
+
+	flush_workqueue(mps->workqueue);
+	destroy_workqueue(mps->workqueue);
+	spi_unregister_master(master);
+	free_irq(mps->irq, mps);
+	if (mps->psc)
+		iounmap(mps->psc);
+
+	return 0;
+}
+
+static int __init mpc512x_psc_spi_of_probe(struct of_device *op,
+					   const struct of_device_id *match)
+{
+	const u32 *regaddr_p;
+	u64 regaddr64, size64;
+	s16 id = -1;
+
+	regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+	if (!regaddr_p) {
+		dev_err(&op->dev, "Invalid PSC address\n");
+		return -EINVAL;
+	}
+	regaddr64 = of_translate_address(op->node, regaddr_p);
+
+	/* get PSC id (0..11, used by port_config) */
+	if (op->dev.platform_data == NULL) {
+		const u32 *psc_nump;
+
+		psc_nump = of_get_property(op->node, "cell-index", NULL);
+		if (!psc_nump || *psc_nump > 11) {
+			dev_err(&op->dev, "mpc512x_psc_spi: Device node %s "
+				"has invalid cell-index property\n",
+				op->node->full_name);
+			return -EINVAL;
+		}
+		id = *psc_nump;
+	}
+
+	return mpc512x_psc_spi_do_probe(&op->dev, (u32) regaddr64, (u32) size64,
+					irq_of_parse_and_map(op->node, 0), id);
+}
+
+static int __exit mpc512x_psc_spi_of_remove(struct of_device *op)
+{
+	return mpc512x_psc_spi_do_remove(&op->dev);
+}
+
+static struct of_device_id mpc512x_psc_spi_of_match[] = {
+	{ .compatible = "fsl,mpc5121-psc-spi", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
+
+static struct of_platform_driver mpc512x_psc_spi_of_driver = {
+	.match_table = mpc512x_psc_spi_of_match,
+	.probe = mpc512x_psc_spi_of_probe,
+	.remove = __exit_p(mpc512x_psc_spi_of_remove),
+	.driver = {
+		.name = "mpc512x-psc-spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mpc512x_psc_spi_init(void)
+{
+	return of_register_platform_driver(&mpc512x_psc_spi_of_driver);
+}
+module_init(mpc512x_psc_spi_init);
+
+static void __exit mpc512x_psc_spi_exit(void)
+{
+	of_unregister_platform_driver(&mpc512x_psc_spi_of_driver);
+}
+module_exit(mpc512x_psc_spi_exit);
+
+MODULE_AUTHOR("John Rigby");
+MODULE_DESCRIPTION("MPC512x PSC SPI Driver");
+MODULE_LICENSE("GPL");
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code
  2010-04-30 13:21 ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Anatolij Gustschin
  2010-04-30 13:21   ` [PATCH 2/2] spi: Add SPI master driver for MPC5121 PSC Anatolij Gustschin
@ 2010-04-30 13:42   ` Grant Likely
  1 sibling, 0 replies; 4+ messages in thread
From: Grant Likely @ 2010-04-30 13:42 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: spi-devel-general, David Brownell, Wolfgang Denk, Detelv Zundel,
	linuxppc-dev

On Fri, Apr 30, 2010 at 7:21 AM, Anatolij Gustschin <agust@denx.de> wrote:
> Since PSC could also be used in other modes than UART mode
> we move PSC FIFO memory initialization from serial driver to
> common platform code. The initialized FIFO memory slices may
> not overlap, so the most easy way would be to configure them
> all at once at init time for all PSC devices. This is now done
> by this patch.
>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>

Looks good.  I'll pick it up.

g.

> ---
> =A0arch/powerpc/platforms/512x/mpc512x_shared.c | =A0 78 ++++++++++++++++=
++++++++++
> =A0drivers/serial/mpc52xx_uart.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =A0 69 =
-----------------------
> =A02 files changed, 78 insertions(+), 69 deletions(-)
>
> diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/=
platforms/512x/mpc512x_shared.c
> index 796080c..a717466 100644
> --- a/arch/powerpc/platforms/512x/mpc512x_shared.c
> +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
> @@ -26,6 +26,7 @@
> =A0#include <asm/prom.h>
> =A0#include <asm/time.h>
> =A0#include <asm/mpc5121.h>
> +#include <asm/mpc52xx_psc.h>
>
> =A0#include "mpc512x.h"
>
> @@ -369,9 +370,86 @@ void __init mpc512x_declare_of_platform_devices(void=
)
> =A0 =A0 =A0 =A0}
> =A0}
>
> +#define DEFAULT_FIFO_SIZE 16
> +
> +static unsigned int __init get_fifo_size(struct device_node *np,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0char *prop_name)
> +{
> + =A0 =A0 =A0 const unsigned int *fp;
> +
> + =A0 =A0 =A0 fp =3D of_get_property(np, prop_name, NULL);
> + =A0 =A0 =A0 if (fp)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return *fp;
> +
> + =A0 =A0 =A0 pr_warning("no %s property in %s node, defaulting to %d\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prop_name, np->full_name, DEFAULT_FI=
FO_SIZE);
> +
> + =A0 =A0 =A0 return DEFAULT_FIFO_SIZE;
> +}
> +
> +#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ((u32)(_base) + sizeof(struct mpc52=
xx_psc)))
> +
> +/* Init PSC FIFO space for TX and RX slices */
> +void __init mpc512x_psc_fifo_init(void)
> +{
> + =A0 =A0 =A0 struct device_node *np;
> + =A0 =A0 =A0 void __iomem *psc;
> + =A0 =A0 =A0 unsigned int tx_fifo_size;
> + =A0 =A0 =A0 unsigned int rx_fifo_size;
> + =A0 =A0 =A0 int fifobase =3D 0; /* current fifo address in 32 bit words=
 */
> +
> + =A0 =A0 =A0 for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size =3D get_fifo_size(np, "fsl,tx-=
fifo-size");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size =3D get_fifo_size(np, "fsl,rx-=
fifo-size");
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* size in register is in 4 byte units */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size /=3D 4;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size /=3D 4;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!tx_fifo_size)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size =3D 1;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!rx_fifo_size)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size =3D 1;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 psc =3D of_iomap(np, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!psc) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: Can't map %s de=
vice\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, n=
p->full_name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* FIFO space is 4KiB, check if requested s=
ize is available */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((fifobase + tx_fifo_size + rx_fifo_size=
) > 0x1000) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: no fifo space a=
vailable for %s\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, n=
p->full_name);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(psc);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* chances are that anoth=
er device requests less
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* fifo space, so we cont=
inue.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* set tx and rx fifo size registers */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txsz, (fifobase << 16=
) | tx_fifo_size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fifobase +=3D tx_fifo_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxsz, (fifobase << 16=
) | rx_fifo_size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fifobase +=3D rx_fifo_size;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* reset and enable the slices */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txcmd, 0x80);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txcmd, 0x01);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxcmd, 0x80);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxcmd, 0x01);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(psc);
> + =A0 =A0 =A0 }
> +}
> +
> =A0void __init mpc512x_init(void)
> =A0{
> =A0 =A0 =A0 =A0mpc512x_declare_of_platform_devices();
> =A0 =A0 =A0 =A0mpc5121_clk_init();
> =A0 =A0 =A0 =A0mpc512x_restart_init();
> + =A0 =A0 =A0 mpc512x_psc_fifo_init();
> =A0}
> diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.=
c
> index 3119fdd..843e7fb 100644
> --- a/drivers/serial/mpc52xx_uart.c
> +++ b/drivers/serial/mpc52xx_uart.c
> @@ -430,34 +430,10 @@ static unsigned long mpc512x_getuartclk(void *p)
> =A0 =A0 =A0 =A0return mpc5xxx_get_bus_frequency(p);
> =A0}
>
> -#define DEFAULT_FIFO_SIZE 16
> -
> -static unsigned int __init get_fifo_size(struct device_node *np,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0char *fifo_name)
> -{
> - =A0 =A0 =A0 const unsigned int *fp;
> -
> - =A0 =A0 =A0 fp =3D of_get_property(np, fifo_name, NULL);
> - =A0 =A0 =A0 if (fp)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return *fp;
> -
> - =A0 =A0 =A0 pr_warning("no %s property in %s node, defaulting to %d\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fifo_name, np->full_name, DEFAULT_FI=
FO_SIZE);
> -
> - =A0 =A0 =A0 return DEFAULT_FIFO_SIZE;
> -}
> -
> -#define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ((u32)(_base) + sizeof(struct mpc52=
xx_psc)))
> -
> =A0/* Init PSC FIFO Controller */
> =A0static int __init mpc512x_psc_fifoc_init(void)
> =A0{
> =A0 =A0 =A0 =A0struct device_node *np;
> - =A0 =A0 =A0 void __iomem *psc;
> - =A0 =A0 =A0 unsigned int tx_fifo_size;
> - =A0 =A0 =A0 unsigned int rx_fifo_size;
> - =A0 =A0 =A0 int fifobase =3D 0; /* current fifo address in 32 bit words=
 */
>
> =A0 =A0 =A0 =A0np =3D of_find_compatible_node(NULL, NULL,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "=
fsl,mpc5121-psc-fifo");
> @@ -480,51 +456,6 @@ static int __init mpc512x_psc_fifoc_init(void)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return -ENODEV;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 for_each_compatible_node(np, NULL, "fsl,mpc5121-psc-uart") =
{
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size =3D get_fifo_size(np, "fsl,tx-=
fifo-size");
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size =3D get_fifo_size(np, "fsl,rx-=
fifo-size");
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* size in register is in 4 byte units */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size /=3D 4;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size /=3D 4;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!tx_fifo_size)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx_fifo_size =3D 1;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!rx_fifo_size)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 rx_fifo_size =3D 1;
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 psc =3D of_iomap(np, 0);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!psc) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: Can't map %s de=
vice\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, n=
p->full_name);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* FIFO space is 4KiB, check if requested s=
ize is available */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if ((fifobase + tx_fifo_size + rx_fifo_size=
) > 0x1000) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pr_err("%s: no fifo space a=
vailable for %s\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, n=
p->full_name);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(psc);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* chances are that anoth=
er device requests less
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* fifo space, so we cont=
inue.
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* set tx and rx fifo size registers */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txsz, (fifobase << 16=
) | tx_fifo_size);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 fifobase +=3D tx_fifo_size;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxsz, (fifobase << 16=
) | rx_fifo_size);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 fifobase +=3D rx_fifo_size;
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* reset and enable the slices */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txcmd, 0x80);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->txcmd, 0x01);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxcmd, 0x80);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&FIFOC(psc)->rxcmd, 0x01);
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 iounmap(psc);
> - =A0 =A0 =A0 }
> -
> =A0 =A0 =A0 =A0return 0;
> =A0}
>
> --
> 1.6.3.3
>
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-04-30 13:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-30 13:21 [PATCH 0/2] Add SPI driver for MPC5121 PSC SPI Anatolij Gustschin
2010-04-30 13:21 ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Anatolij Gustschin
2010-04-30 13:21   ` [PATCH 2/2] spi: Add SPI master driver for MPC5121 PSC Anatolij Gustschin
2010-04-30 13:42   ` [PATCH 1/2] powerpc/mpc5121: move PSC FIFO memory init to platform code Grant Likely

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).