mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* Re: [PATCH][v2] nios2: Add Altera SPI master driver
       [not found] <1312226629-12064-1-git-send-email-franck.jullien@gmail.com>
@ 2011-08-11 19:35 ` Franck JULLIEN
  2011-08-12  7:24   ` Sascha Hauer
  0 siblings, 1 reply; 7+ messages in thread
From: Franck JULLIEN @ 2011-08-11 19:35 UTC (permalink / raw)
  To: barebox

2011/8/1 Franck Jullien <franck.jullien@gmail.com>:
> From: Franck Jullien <franck.jullien@gmail.com>
>
> Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
> ---
>  arch/nios2/include/asm/spi.h |   21 ++++
>  drivers/spi/Kconfig          |    5 +
>  drivers/spi/Makefile         |    1 +
>  drivers/spi/altera_spi.c     |  228 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 255 insertions(+), 0 deletions(-)
>  create mode 100644 arch/nios2/include/asm/spi.h
>  create mode 100644 drivers/spi/altera_spi.c
>
> diff --git a/arch/nios2/include/asm/spi.h b/arch/nios2/include/asm/spi.h
> new file mode 100644
> index 0000000..4e576b9
> --- /dev/null
> +++ b/arch/nios2/include/asm/spi.h
> @@ -0,0 +1,21 @@
> +#ifndef __ALTERA_SPI_H_
> +#define __ALTERA_SPI_H_
> +
> +#include <spi/spi.h>
> +
> +struct spi_altera_master {
> +       int     num_chipselect;
> +       int     spi_mode;
> +       int     databits;
> +       int     speed;
> +};
> +
> +struct altera_spi {
> +       struct spi_master       master;
> +       int                     databits;
> +       int                     speed;
> +       int                     mode;
> +       void __iomem            *regs;
> +};
> +
> +#endif /*__ALTERA_SPI_H_*/
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 9ab03f6..c72493c 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -19,4 +19,9 @@ config DRIVER_SPI_IMX_2_3
>        depends on ARCH_IMX51 || ARCH_IMX53
>        default y
>
> +config DRIVER_SPI_ALTERA
> +       bool "Altera SPI Master driver"
> +       depends on NIOS2
> +       depends on SPI
> +
>  endmenu
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index b2b2f67..90e141d 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -1,2 +1,3 @@
>  obj-$(CONFIG_SPI) += spi.o
>  obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
> +obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
> diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
> new file mode 100644
> index 0000000..3ee6d00
> --- /dev/null
> +++ b/drivers/spi/altera_spi.c
> @@ -0,0 +1,228 @@
> +/*
> + * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
> + * Inspired from Thomas Chou Linux spi_altera.c driver
> + *
> + * 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 <init.h>
> +#include <driver.h>
> +#include <spi/spi.h>
> +#include <asm/io.h>
> +#include <asm/spi.h>
> +#include <asm/nios2-io.h>
> +
> +static int altera_spi_setup(struct spi_device *spi)
> +{
> +       struct spi_master *master = spi->master;
> +       struct device_d spi_dev = spi->dev;
> +       struct altera_spi *altera_spi = container_of(master, struct altera_spi, master);
> +
> +       if (spi->bits_per_word != altera_spi->databits) {
> +               dev_err(master->dev, " master doesn't support %d bits per word requested by %s\n",
> +                       spi->bits_per_word, spi_dev.name);
> +               return -1;
> +       }
> +
> +       if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != altera_spi->mode) {
> +               dev_err(master->dev, " master doesn't support SPI_MODE%d requested by %s\n",
> +                       spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name);
> +               return -1;
> +       }
> +
> +       if (spi->max_speed_hz < altera_spi->speed) {
> +               dev_err(master->dev, " frequency is too high for %s\n", spi_dev.name);
> +               return -1;
> +       }
> +
> +       dev_dbg(master->dev, " mode 0x%08x, bits_per_word: %d, speed: %d\n",
> +               spi->mode, spi->bits_per_word, altera_spi->speed);
> +
> +       return 0;
> +}
> +
> +
> +static unsigned int altera_spi_xchg_single(struct altera_spi *altera_spi, unsigned int data)
> +{
> +       struct nios_spi *nios_spi = altera_spi->regs;
> +
> +       while (!(readl(&nios_spi->status) & NIOS_SPI_TRDY));
> +       writel(data, &nios_spi->txdata);
> +
> +       while (!(readl(&nios_spi->status) & NIOS_SPI_RRDY));
> +
> +       return readl(&nios_spi->rxdata);
> +}
> +
> +/*
> + * When using SPI_CS_HIGH devices, only one device is allowed to be
> + * connected to the Altera SPI master. This limitation is due to the
> + * emulation of an active high CS by writing 0 to the slaveselect register
> + * (this produce a '1' to all CS pins).
> + */
> +
> +static void altera_spi_cs_active(struct spi_device *spi)
> +{
> +       struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
> +       struct nios_spi *nios_spi = altera_spi->regs;
> +       uint32_t tmp;
> +
> +       if (spi->mode & SPI_CS_HIGH) {
> +               tmp = readw(&nios_spi->control);
> +               writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control);
> +               writel(0, &nios_spi->slaveselect);
> +       } else {
> +               writel(1 << spi->chip_select, &nios_spi->slaveselect);
> +               tmp = readl(&nios_spi->control);
> +               writel(tmp | NIOS_SPI_SSO, &nios_spi->control);
> +       }
> +}
> +
> +static void altera_spi_cs_inactive(struct spi_device *spi)
> +{
> +       struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
> +       struct nios_spi *nios_spi = altera_spi->regs;
> +       uint32_t tmp;
> +
> +       if (spi->mode & SPI_CS_HIGH) {
> +               writel(1 << spi->chip_select, &nios_spi->slaveselect);
> +               tmp = readl(&nios_spi->control);
> +               writel(tmp | NIOS_SPI_SSO, &nios_spi->control);
> +       } else {
> +               tmp = readw(&nios_spi->control);
> +               writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control);
> +       }
> +}
> +
> +static unsigned altera_spi_do_xfer(struct spi_device *spi, struct spi_transfer *t)
> +{
> +       struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
> +       int word_len = spi->bits_per_word;
> +       unsigned retval = 0;
> +       u32 txval;
> +       u32 rxval;
> +
> +       word_len = spi->bits_per_word;
> +
> +       if (word_len <= 8) {
> +               const u8 *txbuf = t->tx_buf;
> +               u8 *rxbuf = t->rx_buf;
> +               int i = 0;
> +
> +               while (i < t->len) {
> +                       txval = txbuf ? txbuf[i] : 0;
> +                       rxval = altera_spi_xchg_single(altera_spi, txval);
> +                       if (rxbuf)
> +                               rxbuf[i] = rxval;
> +                       i++;
> +                       retval++;
> +               }
> +       } else if (word_len <= 16) {
> +               const u16 *txbuf = t->tx_buf;
> +               u16 *rxbuf = t->rx_buf;
> +               int i = 0;
> +
> +               while (i < t->len >> 1) {
> +                       txval = txbuf ? txbuf[i] : 0;
> +                       rxval = altera_spi_xchg_single(altera_spi, txval);
> +                       if (rxbuf)
> +                               rxbuf[i] = rxval;
> +                       i++;
> +                       retval += 2;
> +               }
> +       } else if (word_len <= 32) {
> +               const u32 *txbuf = t->tx_buf;
> +               u32 *rxbuf = t->rx_buf;
> +               int i = 0;
> +
> +               while (i < t->len >> 2) {
> +                       txval = txbuf ? txbuf[i] : 0;
> +                       rxval = altera_spi_xchg_single(altera_spi, txval);
> +                       if (rxbuf)
> +                               rxbuf[i] = rxval;
> +                       i++;
> +                       retval += 4;
> +               }
> +       }
> +
> +       return retval;
> +}
> +
> +static int altera_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
> +{
> +       struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
> +       struct nios_spi *nios_spi = altera_spi->regs;
> +       struct spi_transfer *t;
> +
> +       altera_spi_cs_active(spi);
> +
> +       mesg->actual_length = 0;
> +
> +       list_for_each_entry(t, &mesg->transfers, transfer_list) {
> +               mesg->actual_length += altera_spi_do_xfer(spi, t);
> +       }
> +
> +       /* Wait the end of any pending transfert */
> +       while ((readl(&nios_spi->status) & NIOS_SPI_TMT) == 0);
> +
> +       altera_spi_cs_inactive(spi);
> +
> +       return 0;
> +}
> +
> +static int altera_spi_probe(struct device_d *dev)
> +{
> +       struct spi_master *master;
> +       struct altera_spi *altera_spi;
> +       struct spi_altera_master *pdata = dev->platform_data;
> +       struct nios_spi *nios_spi;
> +
> +       altera_spi = xzalloc(sizeof(*altera_spi));
> +
> +       master = &altera_spi->master;
> +       master->dev = dev;
> +
> +       master->setup = altera_spi_setup;
> +       master->transfer = altera_spi_transfer;
> +       master->num_chipselect = pdata->num_chipselect;
> +
> +       altera_spi->regs = dev_request_mem_region(dev, 0);
> +       altera_spi->databits = pdata->databits;
> +       altera_spi->speed = pdata->speed;
> +       altera_spi->mode = pdata->spi_mode;
> +
> +       nios_spi = altera_spi->regs;
> +       writel(0, &nios_spi->slaveselect);
> +       writel(0, &nios_spi->control);
> +
> +       spi_register_master(master);
> +
> +       return 0;
> +}
> +
> +static struct driver_d altera_spi_driver = {
> +       .name  = "altera_spi",
> +       .probe = altera_spi_probe,
> +};
> +
> +static int altera_spi_driver_init(void)
> +{
> +       return register_driver(&altera_spi_driver);
> +}
> +
> +device_initcall(altera_spi_driver_init);
> --
> 1.7.6
>
>

Hello,

any chance to get this one in next ?

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][v2] nios2: Add Altera SPI master driver
  2011-08-11 19:35 ` [PATCH][v2] nios2: Add Altera SPI master driver Franck JULLIEN
@ 2011-08-12  7:24   ` Sascha Hauer
  2011-08-12  9:40     ` Franck JULLIEN
  0 siblings, 1 reply; 7+ messages in thread
From: Sascha Hauer @ 2011-08-12  7:24 UTC (permalink / raw)
  To: Franck JULLIEN; +Cc: barebox

On Thu, Aug 11, 2011 at 09:35:30PM +0200, Franck JULLIEN wrote:
> 2011/8/1 Franck Jullien <franck.jullien@gmail.com>:
> > From: Franck Jullien <franck.jullien@gmail.com>
> >
> >
> 
> Hello,
> 
> any chance to get this one in next ?

Generally yes. Care to update this according to the last comments I
made?

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][v2] nios2: Add Altera SPI master driver
  2011-08-12  7:24   ` Sascha Hauer
@ 2011-08-12  9:40     ` Franck JULLIEN
  2011-08-12 12:19       ` Sascha Hauer
  0 siblings, 1 reply; 7+ messages in thread
From: Franck JULLIEN @ 2011-08-12  9:40 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Hello,

2011/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
> On Thu, Aug 11, 2011 at 09:35:30PM +0200, Franck JULLIEN wrote:
>> 2011/8/1 Franck Jullien <franck.jullien@gmail.com>:
>> > From: Franck Jullien <franck.jullien@gmail.com>
>> >
>> >
>>
>> Hello,
>>
>> any chance to get this one in next ?
>
> Generally yes. Care to update this according to the last comments I
> made?
>

Yes I did sir :)

> Sascha
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][v2] nios2: Add Altera SPI master driver
  2011-08-12  9:40     ` Franck JULLIEN
@ 2011-08-12 12:19       ` Sascha Hauer
  2011-08-12 13:03         ` Franck JULLIEN
  0 siblings, 1 reply; 7+ messages in thread
From: Sascha Hauer @ 2011-08-12 12:19 UTC (permalink / raw)
  To: Franck JULLIEN; +Cc: barebox

On Fri, Aug 12, 2011 at 11:40:07AM +0200, Franck JULLIEN wrote:
> Hello,
> 
> 2011/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
> > On Thu, Aug 11, 2011 at 09:35:30PM +0200, Franck JULLIEN wrote:
> >> 2011/8/1 Franck Jullien <franck.jullien@gmail.com>:
> >> > From: Franck Jullien <franck.jullien@gmail.com>
> >> >
> >> >
> >>
> >> Hello,
> >>
> >> any chance to get this one in next ?
> >
> > Generally yes. Care to update this according to the last comments I
> > made?
> >
> 
> Yes I did sir :)

Indeed, the patch in the mail you were replying to is updated according
my comments. It seems the original mail is lost somewhere on the way.
It's neither in my inbox nor in the list archive, that's why I thought
you are refering to the first version. Same with the SPI flash driver.

Can you please send the patches once again?

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH][v2] nios2: Add Altera SPI master driver
  2011-08-12 12:19       ` Sascha Hauer
@ 2011-08-12 13:03         ` Franck JULLIEN
  0 siblings, 0 replies; 7+ messages in thread
From: Franck JULLIEN @ 2011-08-12 13:03 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

2011/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
> On Fri, Aug 12, 2011 at 11:40:07AM +0200, Franck JULLIEN wrote:
>> Hello,
>>
>> 2011/8/12 Sascha Hauer <s.hauer@pengutronix.de>:
>> > On Thu, Aug 11, 2011 at 09:35:30PM +0200, Franck JULLIEN wrote:
>> >> 2011/8/1 Franck Jullien <franck.jullien@gmail.com>:
>> >> > From: Franck Jullien <franck.jullien@gmail.com>
>> >> >
>> >> >
>> >>
>> >> Hello,
>> >>
>> >> any chance to get this one in next ?
>> >
>> > Generally yes. Care to update this according to the last comments I
>> > made?
>> >
>>
>> Yes I did sir :)
>
> Indeed, the patch in the mail you were replying to is updated according
> my comments. It seems the original mail is lost somewhere on the way.
> It's neither in my inbox nor in the list archive, that's why I thought
> you are refering to the first version. Same with the SPI flash driver.
>
> Can you please send the patches once again?
>

Ok I'll do that when I'm back from holidays (2 weeks).

Franck.

> Sascha
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2] nios2: Add Altera SPI master driver
  2011-08-24 10:19 [PATCH v2] " franck.jullien
@ 2011-08-24 16:45 ` Sascha Hauer
  0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2011-08-24 16:45 UTC (permalink / raw)
  To: franck.jullien; +Cc: barebox


Applied this series to next


On Wed, Aug 24, 2011 at 12:19:23PM +0200, franck.jullien@gmail.com wrote:
> +
> +	/* Wait the end of any pending transfert */

And fixed this little typo on the fly.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2] nios2: Add Altera SPI master driver
@ 2011-08-24 10:19 franck.jullien
  2011-08-24 16:45 ` Sascha Hauer
  0 siblings, 1 reply; 7+ messages in thread
From: franck.jullien @ 2011-08-24 10:19 UTC (permalink / raw)
  To: barebox

From: Franck Jullien <franck.jullien@gmail.com>

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 arch/nios2/include/asm/spi.h |   21 ++++
 drivers/spi/Kconfig          |    5 +
 drivers/spi/Makefile         |    1 +
 drivers/spi/altera_spi.c     |  227 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 254 insertions(+), 0 deletions(-)
 create mode 100644 arch/nios2/include/asm/spi.h
 create mode 100644 drivers/spi/altera_spi.c

diff --git a/arch/nios2/include/asm/spi.h b/arch/nios2/include/asm/spi.h
new file mode 100644
index 0000000..4e576b9
--- /dev/null
+++ b/arch/nios2/include/asm/spi.h
@@ -0,0 +1,21 @@
+#ifndef __ALTERA_SPI_H_
+#define __ALTERA_SPI_H_
+
+#include <spi/spi.h>
+
+struct spi_altera_master {
+	int	num_chipselect;
+	int	spi_mode;
+	int	databits;
+	int	speed;
+};
+
+struct altera_spi {
+	struct spi_master	master;
+	int			databits;
+	int			speed;
+	int			mode;
+	void __iomem		*regs;
+};
+
+#endif /*__ALTERA_SPI_H_*/
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9ab03f6..c72493c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -19,4 +19,9 @@ config DRIVER_SPI_IMX_2_3
 	depends on ARCH_IMX51 || ARCH_IMX53
 	default y
 
+config DRIVER_SPI_ALTERA
+	bool "Altera SPI Master driver"
+	depends on NIOS2
+	depends on SPI
+
 endmenu
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b2b2f67..90e141d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_SPI) += spi.o
 obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
+obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
new file mode 100644
index 0000000..7f1b9b2
--- /dev/null
+++ b/drivers/spi/altera_spi.c
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * 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 <init.h>
+#include <driver.h>
+#include <spi/spi.h>
+#include <asm/io.h>
+#include <asm/spi.h>
+#include <asm/nios2-io.h>
+
+static int altera_spi_setup(struct spi_device *spi)
+{
+	struct spi_master *master = spi->master;
+	struct device_d spi_dev = spi->dev;
+	struct altera_spi *altera_spi = container_of(master, struct altera_spi, master);
+
+	if (spi->bits_per_word != altera_spi->databits) {
+		dev_err(master->dev, " master doesn't support %d bits per word requested by %s\n",
+			spi->bits_per_word, spi_dev.name);
+		return -1;
+	}
+
+	if ((spi->mode & (SPI_CPHA | SPI_CPOL)) != altera_spi->mode) {
+		dev_err(master->dev, " master doesn't support SPI_MODE%d requested by %s\n",
+			spi->mode & (SPI_CPHA | SPI_CPOL), spi_dev.name);
+		return -1;
+	}
+
+	if (spi->max_speed_hz < altera_spi->speed) {
+		dev_err(master->dev, " frequency is too high for %s\n", spi_dev.name);
+		return -1;
+	}
+
+	dev_dbg(master->dev, " mode 0x%08x, bits_per_word: %d, speed: %d\n",
+		spi->mode, spi->bits_per_word, altera_spi->speed);
+
+	return 0;
+}
+
+
+static unsigned int altera_spi_xchg_single(struct altera_spi *altera_spi, unsigned int data)
+{
+	struct nios_spi *nios_spi = altera_spi->regs;
+
+	while (!(readl(&nios_spi->status) & NIOS_SPI_TRDY));
+	writel(data, &nios_spi->txdata);
+
+	while (!(readl(&nios_spi->status) & NIOS_SPI_RRDY));
+
+	return readl(&nios_spi->rxdata);
+}
+
+/*
+ * When using SPI_CS_HIGH devices, only one device is allowed to be
+ * connected to the Altera SPI master. This limitation is due to the
+ * emulation of an active high CS by writing 0 to the slaveselect register
+ * (this produce a '1' to all CS pins).
+ */
+
+static void altera_spi_cs_active(struct spi_device *spi)
+{
+	struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
+	struct nios_spi *nios_spi = altera_spi->regs;
+	uint32_t tmp;
+
+	if (spi->mode & SPI_CS_HIGH) {
+		tmp = readw(&nios_spi->control);
+		writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control);
+		writel(0, &nios_spi->slaveselect);
+	} else {
+		writel(1 << spi->chip_select, &nios_spi->slaveselect);
+		tmp = readl(&nios_spi->control);
+		writel(tmp | NIOS_SPI_SSO, &nios_spi->control);
+	}
+}
+
+static void altera_spi_cs_inactive(struct spi_device *spi)
+{
+	struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
+	struct nios_spi *nios_spi = altera_spi->regs;
+	uint32_t tmp;
+
+	if (spi->mode & SPI_CS_HIGH) {
+		writel(1 << spi->chip_select, &nios_spi->slaveselect);
+		tmp = readl(&nios_spi->control);
+		writel(tmp | NIOS_SPI_SSO, &nios_spi->control);
+	} else {
+		tmp = readw(&nios_spi->control);
+		writew(tmp & ~NIOS_SPI_SSO, &nios_spi->control);
+	}
+}
+
+static unsigned altera_spi_do_xfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
+	int word_len = spi->bits_per_word;
+	unsigned retval = 0;
+	u32 txval;
+	u32 rxval;
+
+	word_len = spi->bits_per_word;
+
+	if (word_len <= 8) {
+		const u8 *txbuf = t->tx_buf;
+		u8 *rxbuf = t->rx_buf;
+		int i = 0;
+
+		while (i < t->len) {
+			txval = txbuf ? txbuf[i] : 0;
+			rxval = altera_spi_xchg_single(altera_spi, txval);
+			if (rxbuf)
+				rxbuf[i] = rxval;
+			i++;
+			retval++;
+		}
+	} else if (word_len <= 16) {
+		const u16 *txbuf = t->tx_buf;
+		u16 *rxbuf = t->rx_buf;
+		int i = 0;
+
+		while (i < t->len >> 1) {
+			txval = txbuf ? txbuf[i] : 0;
+			rxval = altera_spi_xchg_single(altera_spi, txval);
+			if (rxbuf)
+				rxbuf[i] = rxval;
+			i++;
+			retval += 2;
+		}
+	} else if (word_len <= 32) {
+		const u32 *txbuf = t->tx_buf;
+		u32 *rxbuf = t->rx_buf;
+		int i = 0;
+
+		while (i < t->len >> 2) {
+			txval = txbuf ? txbuf[i] : 0;
+			rxval = altera_spi_xchg_single(altera_spi, txval);
+			if (rxbuf)
+				rxbuf[i] = rxval;
+			i++;
+			retval += 4;
+		}
+	}
+
+	return retval;
+}
+
+static int altera_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
+	struct nios_spi *nios_spi = altera_spi->regs;
+	struct spi_transfer *t;
+
+	altera_spi_cs_active(spi);
+
+	mesg->actual_length = 0;
+
+	list_for_each_entry(t, &mesg->transfers, transfer_list) {
+		mesg->actual_length += altera_spi_do_xfer(spi, t);
+	}
+
+	/* Wait the end of any pending transfert */
+	while ((readl(&nios_spi->status) & NIOS_SPI_TMT) == 0);
+
+	altera_spi_cs_inactive(spi);
+
+	return 0;
+}
+
+static int altera_spi_probe(struct device_d *dev)
+{
+	struct spi_master *master;
+	struct altera_spi *altera_spi;
+	struct spi_altera_master *pdata = dev->platform_data;
+	struct nios_spi *nios_spi;
+
+	altera_spi = xzalloc(sizeof(*altera_spi));
+
+	master = &altera_spi->master;
+	master->dev = dev;
+
+	master->setup = altera_spi_setup;
+	master->transfer = altera_spi_transfer;
+	master->num_chipselect = pdata->num_chipselect;
+
+	altera_spi->regs = dev_request_mem_region(dev, 0);
+	altera_spi->databits = pdata->databits;
+	altera_spi->speed = pdata->speed;
+	altera_spi->mode = pdata->spi_mode;
+
+	nios_spi = altera_spi->regs;
+	writel(0, &nios_spi->slaveselect);
+	writel(0, &nios_spi->control);
+
+	spi_register_master(master);
+
+	return 0;
+}
+
+static struct driver_d altera_spi_driver = {
+	.name  = "altera_spi",
+	.probe = altera_spi_probe,
+};
+
+static int altera_spi_driver_init(void)
+{
+	return register_driver(&altera_spi_driver);
+}
+
+device_initcall(altera_spi_driver_init);
-- 
1.7.6


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-08-24 16:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1312226629-12064-1-git-send-email-franck.jullien@gmail.com>
2011-08-11 19:35 ` [PATCH][v2] nios2: Add Altera SPI master driver Franck JULLIEN
2011-08-12  7:24   ` Sascha Hauer
2011-08-12  9:40     ` Franck JULLIEN
2011-08-12 12:19       ` Sascha Hauer
2011-08-12 13:03         ` Franck JULLIEN
2011-08-24 10:19 [PATCH v2] " franck.jullien
2011-08-24 16:45 ` Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox