* 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
* [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