[U-Boot] [PATCH v3 1/2] ppc4xx: Add PPC4xx SPI driver

This patch adds an SPI driver for the 440EPx processor.
Tested on Sequoia.
Signed-off-by: Steven A. Falco sfalco@harris.com --- Thanks for the comments.
I've added the in/out accessors, and included the other comments made by reviewers (inlines, etc). The patch passes a checkpatch test.
drivers/spi/Makefile | 1 + drivers/spi/ppc4xx_spi.c | 141 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/ppc4xx_spi.h | 58 +++++++++++++++++ 3 files changed, 200 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/ppc4xx_spi.c create mode 100644 include/asm-ppc/ppc4xx_spi.h
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 15e0f7a..a699760 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)libspi.a COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o +COBJS-$(CONFIG_PPC4xx_SPI) += ppc4xx_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
COBJS := $(COBJS-y) diff --git a/drivers/spi/ppc4xx_spi.c b/drivers/spi/ppc4xx_spi.c new file mode 100644 index 0000000..273f8c4 --- /dev/null +++ b/drivers/spi/ppc4xx_spi.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 Harris Corporation + * Author: Steven A. Falco sfalco@harris.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <spi.h> +#include <malloc.h> + +#include <asm/io.h> +#include <asm/ppc4xx_spi.h> + +void spi_init(void) +{ + spi4xx_t *spi = (spi4xx_t *) SPI_BASE_ADDR; + + out_8(&spi->cdm, 0); /* Default to the highest speed */ + out_8(&spi->mode, SPI_MODE_SPE); /* Enable the port */ +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + spi4xx_t *spi = (spi4xx_t *) SPI_BASE_ADDR; + + ulong opb = get_OPB_freq(); + ulong divisor; + struct spi_slave *s; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + divisor = ((opb + (max_hz * 4) - 1) / (max_hz * 4)) - 1; + if (divisor > 255) + return NULL; + + out_8(&spi->cdm, divisor); + + s = malloc(sizeof(struct spi_slave)); + if (!s) + return NULL; + + if (mode & SPI_CPHA) + clrbits_8(&spi->mode, SPI_MODE_SCP); + else + setbits_8(&spi->mode, SPI_MODE_SCP); + + if (mode & SPI_CPOL) + setbits_8(&spi->mode, SPI_MODE_CI); + else + clrbits_8(&spi->mode, SPI_MODE_CI); + + s->bus = bus; + s->cs = cs; + + return s; +} + +void spi_free_slave(struct spi_slave *slave) +{ + free(slave); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ +} + +/* Start an 8-bit transaction. */ +static inline void spi_start(spi4xx_t *spi) +{ + out_8(&spi->cr, SPI_CR_STR); +} + +/* Wait for the TX to be empty. */ +static inline void spi_tx_wait(spi4xx_t *spi) +{ + while (in_8(&spi->sr) & SPI_SR_BSY) + ; +} + +/* Wait for the RX to have data. */ +static inline void spi_rx_wait(spi4xx_t *spi) +{ + while (!(in_8(&spi->sr) & SPI_SR_RBR)) + ; +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + spi4xx_t *spi = (spi4xx_t *) SPI_BASE_ADDR; + + const u8 *txd = dout; + u8 *rxd = din; + int ii; + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(slave); + + /* Do a byte at a time */ + for (ii = 0; ii < ((bitlen + 7) / 8); ii++) { + /* Wait for room, then load the next byte. */ + spi_tx_wait(spi); + out_8(&spi->txd, *txd++); + + /* Send/receive 8 bits. */ + spi_start(spi); + + /* Wait for the incoming byte, then store it. */ + spi_rx_wait(spi); + *rxd++ = in_8(&spi->rxd); + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); + + return 0; +} diff --git a/include/asm-ppc/ppc4xx_spi.h b/include/asm-ppc/ppc4xx_spi.h new file mode 100644 index 0000000..f908ef8 --- /dev/null +++ b/include/asm-ppc/ppc4xx_spi.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008 Harris Corporation + * Author: Steven A. Falco sfalco@harris.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _4xx_spi_h_ +#define _4xx_spi_h_ + +#include <asm/types.h> + +#if defined(CONFIG_440EPX) || \ + defined(CONFIG_440GRX) +#define SPI_BASE_ADDR (CONFIG_SYS_PERIPHERAL_BASE + 0x00000900) +#endif + +/* Bits in the command register */ +#define SPI_CR_STR 0x01 + +/* Bits in the status register */ +#define SPI_SR_RBR 0x01 +#define SPI_SR_BSY 0x02 + +/* Bits in the mode register */ +#define SPI_MODE_IL 0x01 +#define SPI_MODE_CI 0x02 +#define SPI_MODE_RD 0x04 +#define SPI_MODE_SPE 0x08 +#define SPI_MODE_SCP 0x10 + +typedef struct spi4xx { + u8 mode; /* mode register */ + u8 rxd; /* receive register */ + u8 txd; /* transmit register */ + u8 cr; /* command register */ + u8 sr; /* status register */ + u8 res0; /* reserved */ + u8 cdm; /* clock divisor */ +} spi4xx_t; + +#endif /* _4xx_spi_h_ */

Dear "Steven A. Falco",
In message 493E9BB6.8080302@harris.com you wrote:
This patch adds an SPI driver for the 440EPx processor.
Tested on Sequoia.
Signed-off-by: Steven A. Falco sfalco@harris.com
Stefan, I vote to put this driver on hold until there are any users for it.
Best regards,
Wolfgang Denk

On Tuesday 09 December 2008, Wolfgang Denk wrote:
This patch adds an SPI driver for the 440EPx processor.
Tested on Sequoia.
Signed-off-by: Steven A. Falco sfalco@harris.com
Stefan, I vote to put this driver on hold until there are any users for it.
I would prefer to include it now (next merge window) since it *can* be used on Sequoia actually. So it may serve as an example for other 4xx boards as well.
But it's your decision in the end.
Best regards, Stefan
===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: office@denx.de =====================================================================

Dear Stefan,
In message 200812091752.46585.sr@denx.de you wrote:
I would prefer to include it now (next merge window) since it *can* be used on Sequoia actually. So it may serve as an example for other 4xx boards as well.
Well, we had similar examples before - things that can be used but did not get checked in (for example the dummy EEPROM driver, etc. The policy so far has always been not to add dead code.
But it's your decision in the end.
Well, you are the 4xx custodian, and if you really think it's useful to add such dead code...
Best regards,
Wolfgang Denk
participants (3)
-
Stefan Roese
-
Steven A. Falco
-
Wolfgang Denk