[U-Boot] [RFC] [mpc8xxx_spi] enabling driver to support MPC8360e SPI in cpu-mode

Richard Retanubun RichardRetanubun at RuggedCom.com
Wed Oct 14 00:00:45 CEST 2009


Hi,

I am working on getting u-boot (circa 2009.08) to program an SPI flash (STMicro M25P40)
that contains the equations for our board's fpga.

While looking at mpc8xxx_spi I realized it is coded for a non-QUICC-Engine based SPI flavor of 8xxx.

I worked up this patch that compiles for mpc8360e. I'd like to share to get some sanity check if this is
a good approach that have a hope of being mainlined. The idea is to use the MPC8360e SPI controller
in cpu-mode, in which case SOME bits are different, but none are being used at the moment.

Another approach I looked at is the /cpu/mpc8260/spi.c but I think this will eventually be superseded by mpc_8xxx.spi, no?

Right now I'm stuck in the transfer timing out. With a slight head-scratching at this comment:

/*
  * Wait for SPI transmit to get out
  * or time out (1 second = 1000 ms)
  * The NE event must be read and cleared first
  */

Yet in the loop I don't see any udelay(1000) to get us to 1second (based on SPI_TIMEOUT = 1000)
am I missing something here?


This is what I've done so far to compile with mpc8360
-----------------------------------------------------

diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index c4b36f0..ff4b44e 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/drivers/spi/mpc8xxx_spi.c
@@ -27,14 +27,27 @@
  #include <spi.h>
  #include <asm/mpc8xxx_spi.h>

+#if defined (CONFIG_MPC8360)
+#include <asm/immap_qe.h>
+#endif
+
+#if defined (CONFIG_MPC8360)
+#define SPI_EV_NE	(0x80 >> 6)	/* Receiver Not Empty */
+#define SPI_EV_NF	(0x80 >> 7)	/* Transmitter Not Full */
+#else
  #define SPI_EV_NE	(0x80000000 >> 22)	/* Receiver Not Empty */
  #define SPI_EV_NF	(0x80000000 >> 23)	/* Transmitter Not Full */
+#endif

  #define SPI_MODE_LOOP	(0x80000000 >> 1)	/* Loopback mode */
  #define SPI_MODE_REV	(0x80000000 >> 5)	/* Reverse mode - MSB first */
  #define SPI_MODE_MS	(0x80000000 >> 6)	/* Always master */
  #define SPI_MODE_EN	(0x80000000 >> 7)	/* Enable interface */

+#if defined (CONFIG_MPC8360)
+#define SPI_MODE_OP	(0x80000000 >> 17)	/* CPU mode */
+#endif
+
  #define SPI_TIMEOUT	1000

  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
@@ -67,6 +80,22 @@ void spi_free_slave(struct spi_slave *slave)

  void spi_init(void)
  {
+#if defined (CONFIG_MPC8360)
+	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
+	volatile qe_map_t *qe = (volatile qe_map_t *)&im->qe;
+	volatile spi_t *spi = (volatile spi_t *)&qe->spi;
+
+	/*
+	 * SPI pins on the MPC83xx are not muxed, so all we do is initialize
+	 * some registers (mode must be CPU mode to use this driver)
+	 */
+	spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN | SPI_MODE_OP;
+	spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use QE_CLK / 16
+							     (12.5 MHz typ.) */
+	spi->event = 0xff;	/* Clear all SPI events */
+	spi->mask = 0x00;	/* Mask  all SPI interrupts */
+	spi->com = 0;		/* LST bit doesn't do anything, so disregard */
+#else
  	volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;

  	/*
@@ -79,6 +108,8 @@ void spi_init(void)
  	spi->event = 0xffffffff;	/* Clear all SPI events */
  	spi->mask = 0x00000000;	/* Mask  all SPI interrupts */
  	spi->com = 0;		/* LST bit doesn't do anything, so disregard */
+#endif
+
  }

  int spi_claim_bus(struct spi_slave *slave)
@@ -94,19 +125,32 @@ void spi_release_bus(struct spi_slave *slave)
  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
  		void *din, unsigned long flags)
  {
+#if defined (CONFIG_MPC8360)
+	volatile immap_t *im = (volatile immap_t *)CONFIG_SYS_IMMR;
+	volatile qe_map_t *qe = (volatile qe_map_t *)&im->qe;
+	volatile spi_t *spi = (volatile spi_t *)&qe->spi;
+	unsigned short event;
+#else
  	volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
-	unsigned int tmpdout, tmpdin, event;
+	unsigned int event;
+#endif
+
+	unsigned int tmpdout, tmpdin;
  	int numBlks = bitlen / 32 + (bitlen % 32 ? 1 : 0);
  	int tm, isRead = 0;
  	unsigned char charSize = 32;

-	debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+	printf("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
  	      slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);

  	if (flags & SPI_XFER_BEGIN)
  		spi_cs_activate(slave);

+#if defined (CONFIG_MPC8360)
+	spi->event = 0xff;	/* Clear all SPI events */
+#else
  	spi->event = 0xffffffff;	/* Clear all SPI events */
+#endif

  	/* handle data in 32-bit chunks */
  	while (numBlks--) {
@@ -139,7 +183,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
  		}

  		spi->tx = tmpdout;	/* Write the data out */
-		debug("*** spi_xfer: ... %08x written\n", tmpdout);
+		printf("*** spi_xfer: ... %08x written\n", tmpdout);

  		/*
  		 * Wait for SPI transmit to get out
diff --git a/include/asm-ppc/immap_qe.h b/include/asm-ppc/immap_qe.h
index 531cfc8..4f11e04 100644
--- a/include/asm-ppc/immap_qe.h
+++ b/include/asm-ppc/immap_qe.h
@@ -159,18 +159,18 @@ typedef struct qe_brg {
  */
  typedef struct spi {
  	u8 res0[0x20];
-	u32 spmode;		/* SPI mode register */
+	u32 mode;		/* SPI mode register */
  	u8 res1[0x2];
-	u8 spie;		/* SPI event register */
+	u8 event;		/* SPI event register */
  	u8 res2[0x1];
  	u8 res3[0x2];
-	u8 spim;		/* SPI mask register */
+	u8 mask;		/* SPI mask register */
  	u8 res4[0x1];
  	u8 res5[0x1];
-	u8 spcom;		/* SPI command register  */
+	u8 com;			/* SPI command register  */
  	u8 res6[0x2];
-	u32 spitd;		/* SPI transmit data register (cpu mode) */
-	u32 spird;		/* SPI receive data register (cpu mode) */
+	u32 tx;			/* SPI transmit data register (cpu mode) */
+	u32 rx;			/* SPI receive data register (cpu mode) */
  	u8 res7[0x8];
  } __attribute__ ((packed)) spi_t;




More information about the U-Boot mailing list