Message ID | 1227628088-10849-1-git-send-email-sr@denx.de (mailing list archive) |
---|---|
State | Accepted, archived |
Delegated to: | Josh Boyer |
Headers | show |
Stefan Roese wrote: > This adds a SPI driver for the SPI controller found in the IBM/AMCC > 4xx PowerPC's. > > Signed-off-by: Stefan Roese <sr@denx.de> > Signed-off-by: Wolfgang Ocker <weo@reccoware.de> > Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> > --- I have a question as to how to use this driver. of_num_gpios() starts testing for gpio's at num = 0, and stops at the first invalid one. However, gpio numbers are apparently allocated dynamically from 255 down, meaning that there probably is no gpio-0. For example, on my Sequoia board I have gpiochip176, gpiochip192, and gpiochip224. So, of_num_gpios() returns zero, even though there are 72 gpio's on my board. This gets back to an earlier discussion about setting the gpio index of each controller, which was rejected, IIRC. If we could set the base gpio of each chip, we could start at zero and use consecutive numbers. Failing that, it seems that Stefan's SPI driver needs to probe the entire 0-255 gpio space. How is this intended to work? An example .dts would be greatly appreciated. Steve
Steven A. Falco wrote: > Stefan Roese wrote: >> This adds a SPI driver for the SPI controller found in the IBM/AMCC >> 4xx PowerPC's. >> >> Signed-off-by: Stefan Roese <sr@denx.de> >> Signed-off-by: Wolfgang Ocker <weo@reccoware.de> >> Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> >> --- > > How is this intended to work? An example .dts would be greatly > appreciated. Answered my own question. The gpios must be directly under the spi node rather than elsewhere in the tree. This works: SPI0: spi@ef600900 { compatible = "ibm,ppc4xx-spi"; reg = <ef600900 7>; interrupts = <8 4>; interrupt-parent = <&UIC0>; gpios = <&GPIO1 14 0>; };
On Tuesday 25 November 2008, Stefan Roese wrote: > Changes in v5: > - Don't call setupxfer() from setup() so that the baudrate etc > won't get changed while another transfer is active, as suggested > by David Brownell. Better, but this still doesn't seem quite right: > +static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) > +{ > + struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); > + struct spi_ppc4xx_cs *cs = spi->controller_state; > + unsigned char cdm = 0; > + int scr; > + u8 bpw; > + > + /* Write new configration */ > + out_8(&hw->regs->mode, cs->mode); > + > + /* > + * Allow platform reduce the interrupt load on the CPU during SPI > + * transfers. We do not target maximum performance, but rather allow > + * platform to limit SPI bus frequency and interrupt rate. That comment doesn't seem even vaguely related to the code it allegedly refers to ... nothing in this routine affects the IRQ load. > + */ > + bpw = t ? t->bits_per_word : spi->bits_per_word; > + cs->speed_hz = t ? min(t->speed_hz, spi->max_speed_hz) : > + spi->max_speed_hz; > + > + if (bpw != 8) { > + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); > + return -EINVAL; > + } > + > + if (cs->speed_hz == 0) { > + dev_err(&spi->dev, "invalid speed_hz (must be non-zero)\n"); > + return -EINVAL; > + } > + > + /* set the clock */ > + /* opb_freq was already divided by 4 */ > + scr = (hw->opb_freq / cs->speed_hz) - 1; > + > + if (scr > 0) > + cdm = min(scr, 0xff); > + > + dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, > + cs->speed_hz); > + > + if (in_8(&hw->regs->cdm) != cdm) > + out_8(&hw->regs->cdm, cdm); > + > + spin_lock(&hw->bitbang.lock); > + if (!hw->bitbang.busy) { > + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); > + /* need to ndelay here? */ > + } > + spin_unlock(&hw->bitbang.lock); > + > + return 0; > +} > + > +static int spi_ppc4xx_setup(struct spi_device *spi) > +{ > + int ret; > + struct spi_ppc4xx_cs *cs = spi->controller_state; > + int init = 0; > + > + if (!spi->bits_per_word) > + spi->bits_per_word = 8; Given the above restrictions, it'd be better to if (spi->bits_per_word != 8) return -EINVAL; On the general policy of reporting such errors as near as practical to the place they appear ... otherwise it gets hard to track them down, since the faults get reported a long time later, well after the point drivers expect to see such reports. Likewise with spi->max_speed_hz. > + > + if (spi->mode & ~MODEBITS) { > + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", > + spi->mode & ~MODEBITS); > + return -EINVAL; > + } > + > + if (cs == NULL) { > + cs = kzalloc(sizeof *cs, GFP_KERNEL); > + if (!cs) > + return -ENOMEM; > + spi->controller_state = cs; > + > + /* > + * First time called, so let's init the SPI controller > + * at the end of this function > + */ > + init = 1; > + } > + > + /* > + * We set all bits of the SPI0_MODE register, so, > + * no need to read-modify-write > + */ > + cs->mode = SPI_PPC4XX_MODE_SPE; > + > + switch (spi->mode & (SPI_CPHA | SPI_CPOL)) { > + case SPI_MODE_0: > + cs->mode |= SPI_CLK_MODE0; > + break; > + case SPI_MODE_1: > + cs->mode |= SPI_CLK_MODE1; > + break; > + case SPI_MODE_2: > + cs->mode |= SPI_CLK_MODE2; > + break; > + case SPI_MODE_3: > + cs->mode |= SPI_CLK_MODE3; > + break; > + } > + > + if (spi->mode & SPI_LSB_FIRST) { > + /* this assumes that bit 7 is the LSb! */ > + cs->mode |= SPI_PPC4XX_MODE_RD; The Linux bit numbering convention is that BIT(0) is the LSB, so that comment is nonsensical. BIT(7) will always bee the MSB of an 8-bit byte. If the issue is a PPC convention that BIT(0) is the MSB, then please adjust comments accordingly. Or better, just strike the comment ... bit numbering is irrelevant here, the only requirement is that LSB_FIRST causes the LSB to be sent first, instead of the MSB. > + } > + > + /* > + * New configuration (mode, speed etc) will be written to the > + * controller in spi_ppc4xx_setupxfer(). Only call > + * spi_ppc4xx_setupxfer() directly upon first initialization. > + */ > + if (init) { > + ret = spi_ppc4xx_setupxfer(spi, NULL); Here it is, calling setupxfer()... despite one of the goals of the v5 patch being to *not* do that from spi_setup()! I suspect what you must intend here is to just force the slave to be deselected. If so, then just call your hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); directly, instead of letting setupxfer() trash register state that may be controlling some active transfer. > + if (ret < 0) { > + dev_err(&spi->dev, "setupxfer returned %d\n", ret); > + return ret; > + } > + } > + > + dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", > + __func__, spi->mode, spi->bits_per_word, > + spi->max_speed_hz); > + > + return 0; > +}
Also: > +static struct of_platform_driver spi_ppc4xx_of_driver = { > + .owner = THIS_MODULE, > + .name = DRIVER_NAME, I'd hope the PPC folk eliminate this duplication soonish. Those fields are obvious duplicates of the driver model fields... > + .match_table = spi_ppc4xx_of_match, > + .probe = spi_ppc4xx_of_probe, > + .remove = __exit_p(spi_ppc4xx_of_remove), > + .driver = { > + .name = DRIVER_NAME, > + .owner = THIS_MODULE, > + }, > +};
Hi David, Stefan, On Sat, 27 Dec 2008 11:32:25 -0800 David Brownell <david-b@pacbell.net> wrote: > > Also: > > > +static struct of_platform_driver spi_ppc4xx_of_driver = { > > + .owner = THIS_MODULE, > > + .name = DRIVER_NAME, > > I'd hope the PPC folk eliminate this duplication soonish. > Those fields are obvious duplicates of the driver model > fields... We are on the path (have been for some time). Only the driver model versions should be filled in for new drivers. For old drivers we copy the values into the driver model fields if they are not already set. We intend to remove the of_platform_drivers versions of "name" and "owner" soon. > > + .match_table = spi_ppc4xx_of_match, > > + .probe = spi_ppc4xx_of_probe, > > + .remove = __exit_p(spi_ppc4xx_of_remove), > > + .driver = { > > + .name = DRIVER_NAME, > > + .owner = THIS_MODULE, > > + }, > > +};
On Saturday 27 December 2008, David Brownell wrote: > On Tuesday 25 November 2008, Stefan Roese wrote: > > Changes in v5: > > - Don't call setupxfer() from setup() so that the baudrate etc > > won't get changed while another transfer is active, as suggested > > by David Brownell. > > Better, but this still doesn't seem quite right: David, thanks for the review. Please find some comments below. > > +static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct > > spi_transfer *t) +{ > > + struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); > > + struct spi_ppc4xx_cs *cs = spi->controller_state; > > + unsigned char cdm = 0; > > + int scr; > > + u8 bpw; > > + > > + /* Write new configration */ > > + out_8(&hw->regs->mode, cs->mode); > > + > > + /* > > + * Allow platform reduce the interrupt load on the CPU during SPI > > + * transfers. We do not target maximum performance, but rather allow > > + * platform to limit SPI bus frequency and interrupt rate. > > That comment doesn't seem even vaguely related to the > code it allegedly refers to ... nothing in this routine > affects the IRQ load. IIRC (I didn't write the original version of this driver) then this comments simply refers to the fact that the platform can select a maximum SPI frequency via spi->max_speed_hz which is pretty obvious. So I'll just remove this comment in the next version. > > + */ > > + bpw = t ? t->bits_per_word : spi->bits_per_word; > > + cs->speed_hz = t ? min(t->speed_hz, spi->max_speed_hz) : > > + spi->max_speed_hz; > > + > > + if (bpw != 8) { > > + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); > > + return -EINVAL; > > + } > > + > > + if (cs->speed_hz == 0) { > > + dev_err(&spi->dev, "invalid speed_hz (must be non-zero)\n"); > > + return -EINVAL; > > + } > > + > > + /* set the clock */ > > + /* opb_freq was already divided by 4 */ > > + scr = (hw->opb_freq / cs->speed_hz) - 1; > > + > > + if (scr > 0) > > + cdm = min(scr, 0xff); > > + > > + dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, > > + cs->speed_hz); > > + > > + if (in_8(&hw->regs->cdm) != cdm) > > + out_8(&hw->regs->cdm, cdm); > > + > > + spin_lock(&hw->bitbang.lock); > > + if (!hw->bitbang.busy) { > > + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); > > + /* need to ndelay here? */ > > + } > > + spin_unlock(&hw->bitbang.lock); > > + > > + return 0; > > +} > > + > > +static int spi_ppc4xx_setup(struct spi_device *spi) > > +{ > > + int ret; > > + struct spi_ppc4xx_cs *cs = spi->controller_state; > > + int init = 0; > > + > > + if (!spi->bits_per_word) > > + spi->bits_per_word = 8; > > Given the above restrictions, it'd be better to > > if (spi->bits_per_word != 8) > return -EINVAL; > > On the general policy of reporting such errors as near as > practical to the place they appear ... otherwise it gets > hard to track them down, since the faults get reported a > long time later, well after the point drivers expect to see > such reports. OK, point gotten. Will change in next version. > Likewise with spi->max_speed_hz. OK. > > + > > + if (spi->mode & ~MODEBITS) { > > + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", > > + spi->mode & ~MODEBITS); > > + return -EINVAL; > > + } > > + > > + if (cs == NULL) { > > + cs = kzalloc(sizeof *cs, GFP_KERNEL); > > + if (!cs) > > + return -ENOMEM; > > + spi->controller_state = cs; > > + > > + /* > > + * First time called, so let's init the SPI controller > > + * at the end of this function > > + */ > > + init = 1; > > + } > > + > > + /* > > + * We set all bits of the SPI0_MODE register, so, > > + * no need to read-modify-write > > + */ > > + cs->mode = SPI_PPC4XX_MODE_SPE; > > + > > + switch (spi->mode & (SPI_CPHA | SPI_CPOL)) { > > + case SPI_MODE_0: > > + cs->mode |= SPI_CLK_MODE0; > > + break; > > + case SPI_MODE_1: > > + cs->mode |= SPI_CLK_MODE1; > > + break; > > + case SPI_MODE_2: > > + cs->mode |= SPI_CLK_MODE2; > > + break; > > + case SPI_MODE_3: > > + cs->mode |= SPI_CLK_MODE3; > > + break; > > + } > > + > > + if (spi->mode & SPI_LSB_FIRST) { > > + /* this assumes that bit 7 is the LSb! */ > > + cs->mode |= SPI_PPC4XX_MODE_RD; > > The Linux bit numbering convention is that BIT(0) is the LSB, > so that comment is nonsensical. BIT(7) will always bee the > MSB of an 8-bit byte. > > If the issue is a PPC convention that BIT(0) is the MSB, > then please adjust comments accordingly. Or better, just > strike the comment ... bit numbering is irrelevant here, > the only requirement is that LSB_FIRST causes the LSB > to be sent first, instead of the MSB. OK, comment removed. > > + } > > + > > + /* > > + * New configuration (mode, speed etc) will be written to the > > + * controller in spi_ppc4xx_setupxfer(). Only call > > + * spi_ppc4xx_setupxfer() directly upon first initialization. > > + */ > > + if (init) { > > + ret = spi_ppc4xx_setupxfer(spi, NULL); > > Here it is, calling setupxfer()... despite one of the goals > of the v5 patch being to *not* do that from spi_setup()! It's only called upon first driver initialization (as the comment above explains). > I suspect what you must intend here is to just force the > slave to be deselected. If so, then just call your > > hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); > > directly, No, this doesn't work. I just tried it in my next driver version. Somehow the communication doesn't start up when setupxfer is not called at least once upon initialization. Sorry, but I worked on this driver quite some time ago and don't remember the details now. > instead of letting setupxfer() trash register > state that may be controlling some active transfer. As this call is done only upon first driver initialization, no active transfer can be interrupted. Or did I miss something here? Please let me know if this approach is acceptable for now, or if I need to dig into this deeper. The problem is that I don't have the time for this now so further patch versions would come (much) later. Otherwise I will send a new patch version with the fixes/changes mentioned above tomorrow. Thanks. Best regards, Stefan
Dear Stefan, In message <200901051912.25874.sr@denx.de> you wrote: > > > > + /* Write new configration */ > > > + out_8(&hw->regs->mode, cs->mode); > > > + > > > + /* > > > + * Allow platform reduce the interrupt load on the CPU during SPI > > > + * transfers. We do not target maximum performance, but rather allow > > > + * platform to limit SPI bus frequency and interrupt rate. > > > > That comment doesn't seem even vaguely related to the > > code it allegedly refers to ... nothing in this routine > > affects the IRQ load. > > IIRC (I didn't write the original version of this driver) then this comments > simply refers to the fact that the platform can select a maximum SPI > frequency via spi->max_speed_hz which is pretty obvious. So I'll just remove > this comment in the next version. On PPC4xx systems we get one interrupt per transferred byte, i. e. there is a direct relation between SPI bus frequency and interrupt rate. Since this is a PPC4xx SPI driver, the comment is actually helpful to understand the operation of the driver especially in relation to the limitations of the hardware. Instead of removing the comment (which leaves the casual reader clueless) it would probably better to add a sentence explaining the one byte / one interrupt situation? Best regards, Wolfgang Denk
Hi Stefan, On Tue, Nov 25, 2008 at 04:48:08PM +0100, Stefan Roese wrote: > This adds a SPI driver for the SPI controller found in the IBM/AMCC > 4xx PowerPC's. > > Signed-off-by: Stefan Roese <sr@denx.de> > Signed-off-by: Wolfgang Ocker <weo@reccoware.de> > Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> > --- [...] > +static unsigned int of_num_gpios(struct device_node *node) > +{ > + unsigned int num = 0; > + > + while (gpio_is_valid(of_get_gpio(node, num))) > + num++; > + return num; > +} FYI, as of commit 749820928a2fd47ff536773d869d2c3f8038b7d1 ("of/gpio: Implement of_gpio_count()") you can use of_gpio_count() from linux/of_gpio.h.
Hi Anton, On Tuesday 06 January 2009, Anton Vorontsov wrote: > > This adds a SPI driver for the SPI controller found in the IBM/AMCC > > 4xx PowerPC's. > > > > Signed-off-by: Stefan Roese <sr@denx.de> > > Signed-off-by: Wolfgang Ocker <weo@reccoware.de> > > Acked-by: Josh Boyer <jwboyer@linux.vnet.ibm.com> > > --- > > [...] > > > +static unsigned int of_num_gpios(struct device_node *node) > > +{ > > + unsigned int num = 0; > > + > > + while (gpio_is_valid(of_get_gpio(node, num))) > > + num++; > > + return num; > > +} > > FYI, as of commit 749820928a2fd47ff536773d869d2c3f8038b7d1 ("of/gpio: > Implement of_gpio_count()") you can use of_gpio_count() from > linux/of_gpio.h. Thanks for the hint. I'll use it in the next version. Best regards, Stefan
Hi Wolfgang, On Monday 05 January 2009, Wolfgang Denk wrote: > > IIRC (I didn't write the original version of this driver) then this > > comments simply refers to the fact that the platform can select a maximum > > SPI frequency via spi->max_speed_hz which is pretty obvious. So I'll just > > remove this comment in the next version. > > On PPC4xx systems we get one interrupt per transferred byte, i. e. > there is a direct relation between SPI bus frequency and interrupt > rate. > > Since this is a PPC4xx SPI driver, the comment is actually helpful to > understand the operation of the driver especially in relation to the > limitations of the hardware. > > Instead of removing the comment (which leaves the casual reader > clueless) it would probably better to add a sentence explaining the > one byte / one interrupt situation? OK, I'll this explanation instead. Thanks. Best regards, Stefan
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b9d0efb..69d5fee 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -155,6 +155,13 @@ config SPI_ORION help This enables using the SPI master controller on the Orion chips. +config SPI_PPC4xx + tristate "PPC4xx SPI Controller" + depends on 4xx && SPI_MASTER + select SPI_BITBANG + help + This selects a driver for the PPC4xx SPI Controller. + config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on ARCH_PXA && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index ccf18de..a2e5816 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o obj-$(CONFIG_SPI_ORION) += orion_spi.o obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o +obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c new file mode 100644 index 0000000..e46292b --- /dev/null +++ b/drivers/spi/spi_ppc4xx.c @@ -0,0 +1,597 @@ +/* + * SPI_PPC4XX SPI controller driver. + * + * Copyright (C) 2007 Gary Jennejohn <garyj@denx.de> + * Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering + * + * Based in part on drivers/spi/spi_s3c24xx.c + * + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/wait.h> +#include <linux/of_platform.h> +#include <linux/of_spi.h> +#include <linux/of_gpio.h> +#include <linux/interrupt.h> +#include <linux/delay.h> + +#include <linux/gpio.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi_bitbang.h> + +#include <asm/io.h> +#include <asm/dcr.h> +#include <asm/dcr-regs.h> + +/* bits in mode register - bit 0 ist MSb */ +/* data latched on leading edge of clock, else trailing edge */ +#define SPI_PPC4XX_MODE_SCP (0x80 >> 3) +/* port enabled */ +#define SPI_PPC4XX_MODE_SPE (0x80 >> 4) +/* MSB first, else LSB first */ +#define SPI_PPC4XX_MODE_RD (0x80 >> 5) +/* clock invert - idle clock = 1, active clock = 0; else reversed */ +#define SPI_PPC4XX_MODE_CI (0x80 >> 6) +/* loopback enable */ +#define SPI_PPC4XX_MODE_IL (0x80 >> 7) +/* bits in control register */ +/* starts a transfer when set */ +#define SPI_PPC4XX_CR_STR (0x80 >> 7) +/* bits in status register */ +/* port is busy with a transfer */ +#define SPI_PPC4XX_SR_BSY (0x80 >> 6) +/* RxD ready */ +#define SPI_PPC4XX_SR_RBR (0x80 >> 7) + +/* the spi->mode bits understood by this driver: */ +#define MODEBITS (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST) + +/* clock settings (SCP and CI) for various SPI modes */ +#define SPI_CLK_MODE0 SPI_PPC4XX_MODE_SCP +#define SPI_CLK_MODE1 0 +#define SPI_CLK_MODE2 SPI_PPC4XX_MODE_CI +#define SPI_CLK_MODE3 (SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI) + +#define DRIVER_NAME "spi_ppc4xx_of" + +struct spi_ppc4xx_regs { + u8 mode; + u8 rxd; + u8 txd; + u8 cr; + u8 sr; + u8 dummy; + /* + * Clock divisor modulus register + * This uses the follwing formula: + * SCPClkOut = OPBCLK/(4(CDM + 1)) + * or + * CDM = (OPBCLK/4*SCPClkOut) - 1 + * bit 0 is the MSb! + */ + u8 cdm; +}; + +/* SPI Controller driver's private data. */ +struct ppc4xx_spi { + /* bitbang has to be first */ + struct spi_bitbang bitbang; + struct completion done; + + u64 mapbase; + u64 mapsize; + int irqnum; + /* need this to set the SPI clock */ + unsigned int opb_freq; + + /* for transfers */ + int len; + int count; + /* data buffers */ + const unsigned char *tx; + unsigned char *rx; + + int *gpios; + unsigned int num_gpios; + + struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */ + struct spi_master *master; + struct device *dev; +}; + +/* need this so we can set the clock in the chipselect routine */ +struct spi_ppc4xx_cs { + u32 speed_hz; + u8 mode; +}; + +static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct ppc4xx_spi *hw; + u8 data; + + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", + t->tx_buf, t->rx_buf, t->len); + + hw = spi_master_get_devdata(spi->master); + + hw->tx = t->tx_buf; + hw->rx = t->rx_buf; + hw->len = t->len; + hw->count = 0; + + /* send the first byte */ + data = hw->tx ? hw->tx[0] : 0; + out_8(&hw->regs->txd, data); + out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); + wait_for_completion(&hw->done); + + return hw->count; +} + +static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); + struct spi_ppc4xx_cs *cs = spi->controller_state; + unsigned char cdm = 0; + int scr; + u8 bpw; + + /* Write new configration */ + out_8(&hw->regs->mode, cs->mode); + + /* + * Allow platform reduce the interrupt load on the CPU during SPI + * transfers. We do not target maximum performance, but rather allow + * platform to limit SPI bus frequency and interrupt rate. + */ + bpw = t ? t->bits_per_word : spi->bits_per_word; + cs->speed_hz = t ? min(t->speed_hz, spi->max_speed_hz) : + spi->max_speed_hz; + + if (bpw != 8) { + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); + return -EINVAL; + } + + if (cs->speed_hz == 0) { + dev_err(&spi->dev, "invalid speed_hz (must be non-zero)\n"); + return -EINVAL; + } + + /* set the clock */ + /* opb_freq was already divided by 4 */ + scr = (hw->opb_freq / cs->speed_hz) - 1; + + if (scr > 0) + cdm = min(scr, 0xff); + + dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, + cs->speed_hz); + + if (in_8(&hw->regs->cdm) != cdm) + out_8(&hw->regs->cdm, cdm); + + spin_lock(&hw->bitbang.lock); + if (!hw->bitbang.busy) { + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); + /* need to ndelay here? */ + } + spin_unlock(&hw->bitbang.lock); + + return 0; +} + +static int spi_ppc4xx_setup(struct spi_device *spi) +{ + int ret; + struct spi_ppc4xx_cs *cs = spi->controller_state; + int init = 0; + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + if (spi->mode & ~MODEBITS) { + dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", + spi->mode & ~MODEBITS); + return -EINVAL; + } + + if (cs == NULL) { + cs = kzalloc(sizeof *cs, GFP_KERNEL); + if (!cs) + return -ENOMEM; + spi->controller_state = cs; + + /* + * First time called, so let's init the SPI controller + * at the end of this function + */ + init = 1; + } + + /* + * We set all bits of the SPI0_MODE register, so, + * no need to read-modify-write + */ + cs->mode = SPI_PPC4XX_MODE_SPE; + + switch (spi->mode & (SPI_CPHA | SPI_CPOL)) { + case SPI_MODE_0: + cs->mode |= SPI_CLK_MODE0; + break; + case SPI_MODE_1: + cs->mode |= SPI_CLK_MODE1; + break; + case SPI_MODE_2: + cs->mode |= SPI_CLK_MODE2; + break; + case SPI_MODE_3: + cs->mode |= SPI_CLK_MODE3; + break; + } + + if (spi->mode & SPI_LSB_FIRST) { + /* this assumes that bit 7 is the LSb! */ + cs->mode |= SPI_PPC4XX_MODE_RD; + } + + /* + * New configuration (mode, speed etc) will be written to the + * controller in spi_ppc4xx_setupxfer(). Only call + * spi_ppc4xx_setupxfer() directly upon first initialization. + */ + if (init) { + ret = spi_ppc4xx_setupxfer(spi, NULL); + if (ret < 0) { + dev_err(&spi->dev, "setupxfer returned %d\n", ret); + return ret; + } + } + + dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", + __func__, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + + return 0; +} + +static void spi_ppc4xx_chipsel(struct spi_device *spi, int value) +{ + struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); + unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; + unsigned int cs = spi->chip_select; + + if (!hw->num_gpios) + return; + + if (cs >= hw->num_gpios) + return; + + if (value != BITBANG_CS_INACTIVE && value != BITBANG_CS_ACTIVE) + return; + + if (value == BITBANG_CS_INACTIVE) + cspol = !cspol; + + gpio_set_value(hw->gpios[cs], cspol); +} + +static irqreturn_t spi_ppc4xx_int(int irq, void *dev_id) +{ + struct ppc4xx_spi *hw; + u8 status; + u8 data; + unsigned int count; + + hw = (struct ppc4xx_spi *)dev_id; + + status = in_8(&hw->regs->sr); + if (!status) + return IRQ_NONE; + + /* should never happen but check anyway */ + if (status & SPI_PPC4XX_SR_BSY) { + u8 lstatus; + int cnt = 0; + + dev_dbg(hw->dev, "got interrupt but spi still busy?\n"); + do { + ndelay(10); + lstatus = in_8(&hw->regs->sr); + } while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY); + + if (cnt >= 100) { + dev_err(hw->dev, "busywait: too many loops!\n"); + complete(&hw->done); + return IRQ_HANDLED; + } else { + /* status is always 1 (RBR) here */ + status = in_8(&hw->regs->sr); + dev_dbg(hw->dev, "loops %d status %x\n", cnt, status); + } + } + + count = hw->count; + hw->count++; + + if (status & SPI_PPC4XX_SR_RBR) { + /* Data Ready */ + data = in_8(&hw->regs->rxd); + if (hw->rx) + hw->rx[count] = data; + } + + count++; + + if (count < hw->len) { + data = hw->tx ? hw->tx[count] : 0; + out_8(&hw->regs->txd, data); + out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); + } else { + complete(&hw->done); + } + + return IRQ_HANDLED; +} + +static void spi_ppc4xx_cleanup(struct spi_device *spi) +{ + kfree(spi->controller_state); +} + +static void spi_ppc4xx_enable(struct ppc4xx_spi *hw) +{ + /* + * On all 4xx PPC's the SPI bus is shared/multiplexed with + * the 2nd I2C bus. We need to enable the the SPI bus before + * using it. + */ + + /* need to clear bit 14 to enable SPC */ + dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0); +} + +static unsigned int of_num_gpios(struct device_node *node) +{ + unsigned int num = 0; + + while (gpio_is_valid(of_get_gpio(node, num))) + num++; + return num; +} + +static void free_gpios(struct ppc4xx_spi *hw) +{ + if (hw->num_gpios) { + int i; + for (i = 0; i < hw->num_gpios; i++) + gpio_free(hw->gpios[i]); + + kfree(hw->gpios); + hw->gpios = NULL; + } +} + +/* + * of_device layer stuff... + */ +static int __init spi_ppc4xx_of_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct ppc4xx_spi *hw; + struct spi_master *master; + struct spi_bitbang *bbp; + struct resource resource; + struct device_node *np = op->node; + struct device *dev = &op->dev; + struct device_node *opbnp; + int ret; + const unsigned int *clk; + + master = spi_alloc_master(dev, sizeof *hw); + if (master == NULL) + return -ENOMEM; + dev_set_drvdata(dev, master); + hw = spi_master_get_devdata(master); + memset(hw, 0, sizeof(struct ppc4xx_spi)); + + hw->master = spi_master_get(master); + hw->dev = dev; + + init_completion(&hw->done); + + hw->num_gpios = of_num_gpios(np); + if (hw->num_gpios) { + int i; + + hw->gpios = kzalloc(sizeof(int) * hw->num_gpios, + GFP_KERNEL); + if (!hw->gpios) { + ret = -ENOMEM; + goto free_master; + } + + for (i = 0; i < hw->num_gpios; i++) { + int gpio = of_get_gpio(np, i); + if (gpio < 0) { + dev_err(dev, "Invalid gpio spec %d\n", i); + ret = gpio; + goto free_gpios; + } + + ret = gpio_request(gpio, np->name); + if (ret < 0) { + dev_err(dev, "gpio %d already in use\n", i); + ret = gpio; + goto free_gpios; + } + + gpio_direction_output(gpio, 0); + hw->gpios[i] = gpio; + } + } + + /* Setup the state for the bitbang driver */ + bbp = &hw->bitbang; + bbp->master = hw->master; + bbp->setup_transfer = spi_ppc4xx_setupxfer; + bbp->chipselect = spi_ppc4xx_chipsel; + bbp->txrx_bufs = spi_ppc4xx_txrx; + bbp->use_dma = 0; + bbp->master->setup = spi_ppc4xx_setup; + bbp->master->cleanup = spi_ppc4xx_cleanup; + /* only one SPI controller */ + bbp->master->bus_num = 0; + if (bbp->master->num_chipselect == 0) { + /* this many pins in al GPIO controllers */ + bbp->master->num_chipselect = hw->num_gpios; + } + + /* Get the clock for the OPB */ + opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); + if (opbnp == NULL) { + dev_err(dev, "OPB: cannot find node\n"); + ret = -ENODEV; + goto free_gpios; + } + /* Get the clock (Hz) for the OPB */ + clk = of_get_property(opbnp, "clock-frequency", NULL); + if (clk == NULL) { + dev_err(dev, "OPB: no clock-frequency property set\n"); + of_node_put(opbnp); + ret = -ENODEV; + goto free_gpios; + } + hw->opb_freq = *clk; + hw->opb_freq >>= 2; + of_node_put(opbnp); + + ret = of_address_to_resource(np, 0, &resource); + if (ret) { + dev_err(dev, "error while parsing device node resource\n"); + goto free_gpios; + } + hw->mapbase = resource.start; + hw->mapsize = resource.end - resource.start + 1; + + /* Sanity check */ + if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) { + dev_err(dev, "too small to map registers\n"); + ret = -EINVAL; + goto free_gpios; + } + + /* Request IRQ */ + hw->irqnum = irq_of_parse_and_map(np, 0); + ret = request_irq(hw->irqnum, spi_ppc4xx_int, + IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw); + if (ret) { + dev_err(dev, "unable to allocate interrupt\n"); + goto free_gpios; + } + + if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) { + dev_err(dev, "resource unavailable\n"); + ret = -EBUSY; + goto request_mem_error; + } + + hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs)); + + if (!hw->regs) { + dev_err(dev, "unable to memory map registers\n"); + ret = -ENXIO; + goto map_io_error; + } + + spi_ppc4xx_enable(hw); + + /* Finally register our spi controller */ + dev->dma_mask = 0; + ret = spi_bitbang_start(bbp); + if (ret) { + dev_err(dev, "failed to register SPI master\n"); + goto unmap_regs; + } + + dev_info(dev, "driver initialized\n"); + of_register_spi_devices(master, np); + + return 0; + +unmap_regs: + iounmap(hw->regs); +map_io_error: + release_mem_region(hw->mapbase, hw->mapsize); +request_mem_error: + free_irq(hw->irqnum, hw); +free_gpios: + free_gpios(hw); +free_master: + dev_set_drvdata(dev, NULL); + spi_master_put(master); + + dev_err(dev, "initialization failed\n"); + return ret; +} + +static int __exit spi_ppc4xx_of_remove(struct of_device *op) +{ + struct spi_master *master = dev_get_drvdata(&op->dev); + struct ppc4xx_spi *hw = spi_master_get_devdata(master); + + spi_bitbang_stop(&hw->bitbang); + dev_set_drvdata(&op->dev, NULL); + release_mem_region(hw->mapbase, hw->mapsize); + free_irq(hw->irqnum, hw); + iounmap(hw->regs); + free_gpios(hw); + return 0; +} + +static struct of_device_id spi_ppc4xx_of_match[] = { + { .compatible = "ibm,ppc4xx-spi", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match); + +static struct of_platform_driver spi_ppc4xx_of_driver = { + .owner = THIS_MODULE, + .name = DRIVER_NAME, + .match_table = spi_ppc4xx_of_match, + .probe = spi_ppc4xx_of_probe, + .remove = __exit_p(spi_ppc4xx_of_remove), + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init spi_ppc4xx_init(void) +{ + return of_register_platform_driver(&spi_ppc4xx_of_driver); +} +module_init(spi_ppc4xx_init); + +static void __exit spi_ppc4xx_exit(void) +{ + of_unregister_platform_driver(&spi_ppc4xx_of_driver); +} +module_exit(spi_ppc4xx_exit); + +MODULE_AUTHOR("Gary Jennejohn & Stefan Roese"); +MODULE_DESCRIPTION("Simple PPC4xx SPI Driver"); +MODULE_LICENSE("GPL");