[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