
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;