[U-Boot] [PATCH v2 1/2] ppc4xx: Add 440EPx SPI driver

Stefan Roese sr at denx.de
Tue Dec 9 06:38:36 CET 2008


On Monday 08 December 2008, Steven A. Falco wrote:
> This patch adds an SPI driver for the 440EPx processor.
>
> Tested on Sequoia.
>
> Signed-off-by: Steven A. Falco <sfalco at harris.com>
> ---
>
> Regarding Ben's comments:
>
> First, thanks for reviewing.  You gave me two different approaches to
> consider, 1) using in/out functions, and 2) using a structure.  So, for
> this version, I've followed the style of the example you gave, using the
> structure approach.

No, you _need_ to use the in_/out_() accessor functions. This is unrelated to 
using plain addresses and offsets vs. a structure. I really welcome the 
change to the structure in this version, so please just add the in_()/out_() 
functions upon accessing the SoC registers.

> This driver may be applicable to other 4xx chips, but after looking at
> the 405gp and 440gp, neither have a SPI hw device.  So, I'm making this
> one exclusive to the 440epx until someone else wants it on another
> processor.  At that point, it can be adapted as needed.

Many other 4xx PPC's have the same SPI controller as 440EPx. Unfortunately you 
looked at the wrong examples. Here a (incomplete) list of some other PPC's 
with the same controller:

405EX, 440EP, 440GR, 440GRx, 460EX, 460GT

But, yes. Your driver seems generic enough to be adapted to other controllers 
when needed.

> Regarding Stefan's comments:
>
> I've renamed the file, and cleaned up the nits.  Given that I've used
> the structure approach, I believe the in/out calls are not applicable.

No, as mentioned above you need to add the in_()/out_() calls as well.

Please find some more comments below.

> Regarding Wolfgang's comments:
>
> It is not for the fun of it.  We are planning a custom board which will
> use the SPI port.  We are entering layout now, and the hardware won't
> appear for at least a few months.  However, the Sequoia board does have
> a connector for the SPI port, and I have connected a device to that
> connector for prototyping purposes.  Other purchasers of the Sequoia may
> well have a similar need.
>
> You are certainly welcome to reject this driver if you feel that is
> insufficient grounds for "usage".  Please let me know, so I don't bother
> the list with it.
>
>  drivers/spi/Makefile      |    1 +
>  drivers/spi/ppc4xx_spi.c  |  119
> +++++++++++++++++++++++++++++++++++++++++++++ lude/asm-ppc/ppc4xx_spi.h |  
> 62 +++++++++++++++++++++++
>  3 files changed, 182 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..7dbba5d 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_PPC440EPX_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..156b056
> --- /dev/null
> +++ b/drivers/spi/ppc4xx_spi.c
> @@ -0,0 +1,119 @@
> +/*
> + * Copyright (C) 2008 Harris Corporation
> + * Author: Steven A. Falco <sfalco at 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)
> +{
> +	volatile spi4xx_t *spi = (volatile spi4xx_t *) SPI_BASE_ADDR;
> +
> +	spi->cdm = 0;			/* Default to "go fast" */
> +	spi->mode = SPI_MODE_SPE;	/* Enable port */
> +}
> +
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +			unsigned int max_hz, unsigned int mode)
> +{
> +	volatile spi4xx_t *spi = (volatile 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;
> +
> +	spi->cdm = divisor;
> +
> +	if (!(s = malloc(sizeof(struct spi_slave))))
> +		return NULL;
> +
> +	if (mode & SPI_CPHA)
> +		spi->mode &= ~SPI_MODE_SCP;
> +	else
> +		spi->mode |= SPI_MODE_SCP;
> +
> +	if (mode & SPI_CPOL)
> +		spi->mode |= SPI_MODE_CI;
> +	else
> +		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)
> +{
> +}
> +
> +#define GO	spi->cr = SPI_CR_STR
> +#define TXWAIT	while(spi->sr & SPI_SR_BSY)
> +#define RXWAIT	while(!(spi->sr & SPI_SR_RBR))

I would prefer static inlined functions here.

> +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +		const void *dout, void *din, unsigned long flags)
> +{
> +	volatile spi4xx_t *spi = (volatile 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++) {
> +		TXWAIT;
> +		spi->txd = *txd++;
> +		GO;
> +		RXWAIT;
> +		*rxd++ = 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..135c9e6
> --- /dev/null
> +++ b/include/asm-ppc/ppc4xx_spi.h
> @@ -0,0 +1,62 @@
> +/*
> + * Copyright (C) 2008 Harris Corporation
> + * Author: Steven A. Falco <sfalco at 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)

And 440GRx please.

> +#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
> +
> +#if defined(CONFIG_440EPX) || \
> +	defined(CONFIG_440GRX)

Please remove this "#if". All other 4xx PPC's with an SPI controller have the 
same register layout. So the only thing that is 440EPx/440GRx specific is the 
base address.

> +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
> +
> +#endif /* _4xx_spi_h_ */

Thanks.

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 at denx.de
=====================================================================


More information about the U-Boot mailing list