mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/3] Add mxs spi driver and mx28evk as its first user
@ 2013-02-04 16:26 Michael Grzeschik
  2013-02-04 16:26 ` [PATCH 1/3] mxs: ssp move to common register layout Michael Grzeschik
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 16:26 UTC (permalink / raw)
  To: barebox

this series adds support for the mxs spi driver
and adds the mx28evk as the first user to use it
with an m25p80 flash memory.

The driver was tested to work with the pio mode,
as its implementation has currently no dma support.

The SSP clock needed to be lower than the max possible
frequency for the flash. Otherwise it sometimes, after
a lot of spi transactions, the SSP stopped working.

Michael Grzeschik (3):
  mxs: ssp move to common register layout
  mxs_spi: initial commit
  mx28evk: add spi

 arch/arm/boards/freescale-mx28-evk/mx28-evk.c |   28 +++
 arch/arm/mach-mxs/include/mach/imx23-regs.h   |   16 ++
 arch/arm/mach-mxs/include/mach/imx28-regs.h   |   21 ++
 arch/arm/mach-mxs/include/mach/ssp.h          |   79 +++++++
 drivers/mci/mxs.c                             |  118 +---------
 drivers/spi/Kconfig                           |    5 +
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mxs_spi.c                         |  306 +++++++++++++++++++++++++
 8 files changed, 457 insertions(+), 117 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/ssp.h
 create mode 100644 drivers/spi/mxs_spi.c

-- 
1.7.10.4


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

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

* [PATCH 1/3] mxs: ssp move to common register layout
  2013-02-04 16:26 [PATCH 0/3] Add mxs spi driver and mx28evk as its first user Michael Grzeschik
@ 2013-02-04 16:26 ` Michael Grzeschik
  2013-02-04 16:26 ` [PATCH 2/3] mxs_spi: initial commit Michael Grzeschik
  2013-02-04 16:26 ` Michael Grzeschik
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 16:26 UTC (permalink / raw)
  To: barebox

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/mach-mxs/include/mach/imx23-regs.h |   16 ++++
 arch/arm/mach-mxs/include/mach/imx28-regs.h |   21 +++++
 arch/arm/mach-mxs/include/mach/ssp.h        |   77 +++++++++++++++++
 drivers/mci/mxs.c                           |  118 +--------------------------
 4 files changed, 115 insertions(+), 117 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/ssp.h

diff --git a/arch/arm/mach-mxs/include/mach/imx23-regs.h b/arch/arm/mach-mxs/include/mach/imx23-regs.h
index 7fb664b..9e8e86c 100644
--- a/arch/arm/mach-mxs/include/mach/imx23-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx23-regs.h
@@ -36,4 +36,20 @@
 #define IMX_DIGCTL_BASE		0x8001c000
 #define IMX_USB_BASE		0x80080000
 
+#define HW_SSP_CTRL0		0x000
+#define HW_SSP_CMD0		0x010
+#define HW_SSP_CMD1		0x020
+#define HW_SSP_COMPREF		0x030
+#define HW_SSP_COMPMASK		0x040
+#define HW_SSP_TIMING		0x050
+#define HW_SSP_CTRL1		0x060
+#define HW_SSP_DATA		0x070
+#define HW_SSP_SDRESP0		0x080
+#define HW_SSP_SDRESP1		0x090
+#define HW_SSP_SDRESP2		0x0A0
+#define HW_SSP_SDRESP3		0x0B0
+#define HW_SSP_STATUS		0x0C0
+#define HW_SSP_DEBUG		0x100
+#define HW_SSP_VERSION		0x110
+
 #endif /* __ASM_ARCH_MX23_REGS_H */
diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h
index fa8edd7..bbe1848 100644
--- a/arch/arm/mach-mxs/include/mach/imx28-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h
@@ -45,4 +45,25 @@
 #define IMX_FEC0_BASE		0x800F0000
 #define IMX_FEC1_BASE		0x800F4000
 
+#define HW_SSP_CTRL0		0x000
+#define HW_SSP_CMD0		0x010
+#define HW_SSP_CMD1		0x020
+#define HW_SSP_XFER_COUNT	0x030
+#define HW_SSP_BLOCK_SIZE	0x040
+#define HW_SSP_COMPREF		0x050
+#define HW_SSP_COMPMASK		0x060
+#define HW_SSP_TIMING		0x070
+#define HW_SSP_CTRL1		0x080
+#define HW_SSP_DATA		0x090
+#define HW_SSP_SDRESP0		0x0A0
+#define HW_SSP_SDRESP1		0x0B0
+#define HW_SSP_SDRESP2		0x0C0
+#define HW_SSP_SDRESP3		0x0D0
+#define HW_SSP_DDR_CTRL		0x0E0
+#define HW_SSP_DLL_CTRL		0x0F0
+#define HW_SSP_STATUS		0x100
+#define HW_SSP_DLL_STS		0x110
+#define HW_SSP_DEBUG		0x120
+#define HW_SSP_VERSION		0x130
+
 #endif /* __ASM_ARCH_MX28_REGS_H */
diff --git a/arch/arm/mach-mxs/include/mach/ssp.h b/arch/arm/mach-mxs/include/mach/ssp.h
new file mode 100644
index 0000000..f91770f
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/ssp.h
@@ -0,0 +1,77 @@
+/*
+ * Freescale MXS SSP
+ *
+ * Copyright (C) 2013 Michael Grzeschik <mgr@pengutronix.de>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __SSP_H__
+#define __SSP_H__
+
+#define SSP_CTRL0_SFTRST		(1 << 31)
+#define SSP_CTRL0_CLKGATE		(1 << 30)
+#define SSP_CTRL0_RUN			(1 << 29)
+#define SSP_CTRL0_LOCK_CS		(1 << 27)
+#define SSP_CTRL0_READ			(1 << 25)
+#define SSP_CTRL0_IGNORE_CRC		(1 << 26)
+#define SSP_CTRL0_DATA_XFER		(1 << 24)
+#define SSP_CTRL0_BUS_WIDTH(x)		(((x) & 0x3) << 22)
+#define SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
+#define SSP_CTRL0_WAIT_FOR_CMD		(1 << 20)
+#define SSP_CTRL0_LONG_RESP		(1 << 19)
+#define SSP_CTRL0_GET_RESP		(1 << 17)
+#define SSP_CTRL0_ENABLE		(1 << 16)
+
+#define SSP_CMD0_SLOW_CLK		(1 << 22)
+#define SSP_CMD0_CONT_CLK		(1 << 21)
+#define SSP_CMD0_APPEND_8CYC		(1 << 20)
+#ifdef CONFIG_ARCH_IMX23
+# define SSP_CTRL0_XFER_COUNT(x)	((x) & 0xffff)
+# define SSP_CMD0_BLOCK_SIZE(x)		(((x) & 0xf) << 16)
+# define SSP_CMD0_BLOCK_COUNT(x)	(((x) & 0xff) << 8)
+#endif
+#define SSP_CMD0_CMD(x)			((x) & 0xff)
+
+#ifdef CONFIG_ARCH_IMX28
+# define SSP_BLOCK_SIZE(x)		((x) & 0xf)
+# define SSP_BLOCK_COUNT(x)		(((x) & 0xffffff) << 4)
+#endif
+
+/* bit definition for register HW_SSP_TIMING */
+#define SSP_TIMING_TIMEOUT_MASK	(0xffff0000)
+#define SSP_TIMING_TIMEOUT(x)		((x) << 16)
+#define SSP_TIMING_CLOCK_DIVIDE(x)	(((x) & 0xff) << 8)
+#define SSP_TIMING_CLOCK_RATE(x)	((x) & 0xff)
+
+/* bit definition for register HW_SSP_CTRL1 */
+#define SSP_CTRL1_POLARITY		(1 << 9)
+#define SSP_CTRL1_PHASE			(1 << 10)
+#define SSP_CTRL1_WORD_LENGTH(x)	(((x) & 0xf) << 4)
+#define SSP_CTRL1_SSP_MODE(x)		((x) & 0xf)
+
+/* bit definition for register HW_SSP_STATUS */
+# define SSP_STATUS_PRESENT		(1 << 31)
+# define SSP_STATUS_SD_PRESENT		(1 << 29)
+# define SSP_STATUS_CARD_DETECT		(1 << 28)
+# define SSP_STATUS_RESP_CRC_ERR	(1 << 16)
+# define SSP_STATUS_RESP_ERR		(1 << 15)
+# define SSP_STATUS_RESP_TIMEOUT	(1 << 14)
+# define SSP_STATUS_DATA_CRC_ERR	(1 << 13)
+# define SSP_STATUS_TIMEOUT		(1 << 12)
+# define SSP_STATUS_FIFO_OVRFLW		(1 << 9)
+# define SSP_STATUS_FIFO_FULL		(1 << 8)
+# define SSP_STATUS_FIFO_EMPTY		(1 << 5)
+# define SSP_STATUS_FIFO_UNDRFLW	(1 << 4)
+# define SSP_STATUS_CMD_BUSY		(1 << 3)
+# define SSP_STATUS_DATA_BUSY		(1 << 2)
+# define SSP_STATUS_BUSY		(1 << 0)
+# define SSP_STATUS_ERROR		(SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW | \
+	SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR | \
+	SSP_STATUS_RESP_TIMEOUT | SSP_STATUS_DATA_CRC_ERR | SSP_STATUS_TIMEOUT)
+
+#endif	/* __SSP_H__ */
diff --git a/drivers/mci/mxs.c b/drivers/mci/mxs.c
index ed644d1..5bdcd1b 100644
--- a/drivers/mci/mxs.c
+++ b/drivers/mci/mxs.c
@@ -40,127 +40,11 @@
 #include <mach/imx-regs.h>
 #include <mach/mci.h>
 #include <mach/clock.h>
+#include <mach/ssp.h>
 
 #define CLOCKRATE_MIN (1 * 1000 * 1000)
 #define CLOCKRATE_MAX (480 * 1000 * 1000)
 
-#define HW_SSP_CTRL0 0x000
-# define SSP_CTRL0_SFTRST (1 << 31)
-# define SSP_CTRL0_CLKGATE (1 << 30)
-# define SSP_CTRL0_RUN (1 << 29)
-# define SSP_CTRL0_LOCK_CS (1 << 27)
-# define SSP_CTRL0_READ (1 << 25)
-# define SSP_CTRL0_IGNORE_CRC (1 << 26)
-# define SSP_CTRL0_DATA_XFER (1 << 24)
-# define SSP_CTRL0_BUS_WIDTH(x) (((x) & 0x3) << 22)
-# define SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
-# define SSP_CTRL0_LONG_RESP (1 << 19)
-# define SSP_CTRL0_GET_RESP (1 << 17)
-# define SSP_CTRL0_ENABLE (1 << 16)
-#ifdef CONFIG_ARCH_IMX23
-# define SSP_CTRL0_XFER_COUNT(x) ((x) & 0xffff)
-#endif
-
-#define HW_SSP_CMD0 0x010
-# define SSP_CMD0_SLOW_CLK (1 << 22)
-# define SSP_CMD0_CONT_CLK (1 << 21)
-# define SSP_CMD0_APPEND_8CYC (1 << 20)
-#ifdef CONFIG_ARCH_IMX23
-# define SSP_CMD0_BLOCK_SIZE(x) (((x) & 0xf) << 16)
-# define SSP_CMD0_BLOCK_COUNT(x) (((x) & 0xff) << 8)
-#endif
-# define SSP_CMD0_CMD(x) ((x) & 0xff)
-
-#define HW_SSP_CMD1 0x020
-
-#ifdef CONFIG_ARCH_IMX23
-# define HW_SSP_COMPREF 0x030
-# define HW_SSP_COMPMASK 0x040
-# define HW_SSP_TIMING 0x050
-# define HW_SSP_CTRL1 0x060
-# define HW_SSP_DATA 0x070
-#endif
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_XFER_COUNT 0x30
-# define HW_SSP_BLOCK_SIZE 0x40
-#  define SSP_BLOCK_SIZE(x) ((x) & 0xf)
-#  define SSP_BLOCK_COUNT(x) (((x) & 0xffffff) << 4)
-# define HW_SSP_COMPREF 0x050
-# define HW_SSP_COMPMASK 0x060
-# define HW_SSP_TIMING 0x070
-# define HW_SSP_CTRL1 0x080
-# define HW_SSP_DATA 0x090
-#endif
-/* bit definition for register HW_SSP_TIMING */
-# define SSP_TIMING_TIMEOUT_MASK (0xffff0000)
-# define SSP_TIMING_TIMEOUT(x) ((x) << 16)
-# define SSP_TIMING_CLOCK_DIVIDE(x) (((x) & 0xff) << 8)
-# define SSP_TIMING_CLOCK_RATE(x) ((x) & 0xff)
-
-/* bit definition for register HW_SSP_CTRL1 */
-# define SSP_CTRL1_POLARITY (1 << 9)
-# define SSP_CTRL1_WORD_LENGTH(x) (((x) & 0xf) << 4)
-# define SSP_CTRL1_SSP_MODE(x) ((x) & 0xf)
-
-#ifdef CONFIG_ARCH_IMX23
-# define HW_SSP_SDRESP0 0x080
-# define HW_SSP_SDRESP1 0x090
-# define HW_SSP_SDRESP2 0x0A0
-# define HW_SSP_SDRESP3 0x0B0
-#endif
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_SDRESP0 0x0A0
-# define HW_SSP_SDRESP1 0x0B0
-# define HW_SSP_SDRESP2 0x0C0
-# define HW_SSP_SDRESP3 0x0D0
-#endif
-
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_DDR_CTRL 0x0E0
-# define HW_SSP_DLL_CTRL 0x0F0
-#endif
-
-#ifdef CONFIG_ARCH_IMX23
-# define HW_SSP_STATUS 0x0C0
-#endif
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_STATUS 0x100
-#endif
-
-/* bit definition for register HW_SSP_STATUS */
-# define SSP_STATUS_PRESENT (1 << 31)
-# define SSP_STATUS_SD_PRESENT (1 << 29)
-# define SSP_STATUS_CARD_DETECT (1 << 28)
-# define SSP_STATUS_RESP_CRC_ERR (1 << 16)
-# define SSP_STATUS_RESP_ERR (1 << 15)
-# define SSP_STATUS_RESP_TIMEOUT (1 << 14)
-# define SSP_STATUS_DATA_CRC_ERR (1 << 13)
-# define SSP_STATUS_TIMEOUT (1 << 12)
-# define SSP_STATUS_FIFO_OVRFLW (1 << 9)
-# define SSP_STATUS_FIFO_FULL (1 << 8)
-# define SSP_STATUS_FIFO_EMPTY (1 << 5)
-# define SSP_STATUS_FIFO_UNDRFLW (1 << 4)
-# define SSP_STATUS_CMD_BUSY (1 << 3)
-# define SSP_STATUS_DATA_BUSY (1 << 2)
-# define SSP_STATUS_BUSY (1 << 0)
-# define SSP_STATUS_ERROR (SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW | \
-	SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR | \
-	SSP_STATUS_RESP_TIMEOUT | SSP_STATUS_DATA_CRC_ERR | SSP_STATUS_TIMEOUT)
-
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_DLL_STS 0x110
-#endif
-
-#ifdef CONFIG_ARCH_IMX23
-# define HW_SSP_DEBUG 0x100
-# define HW_SSP_VERSION 0x110
-#endif
-
-#ifdef CONFIG_ARCH_IMX28
-# define HW_SSP_DEBUG 0x120
-# define HW_SSP_VERSION 0x130
-#endif
-
 struct mxs_mci_host {
 	struct mci_host	host;
 	void __iomem	*regs;
-- 
1.7.10.4


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

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

* [PATCH 2/3] mxs_spi: initial commit
  2013-02-04 16:26 [PATCH 0/3] Add mxs spi driver and mx28evk as its first user Michael Grzeschik
  2013-02-04 16:26 ` [PATCH 1/3] mxs: ssp move to common register layout Michael Grzeschik
@ 2013-02-04 16:26 ` Michael Grzeschik
  2013-02-04 16:26 ` Michael Grzeschik
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 16:26 UTC (permalink / raw)
  To: barebox

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/mach-mxs/include/mach/ssp.h |    2 +
 drivers/spi/Kconfig                  |    5 +
 drivers/spi/Makefile                 |    1 +
 drivers/spi/mxs_spi.c                |  306 ++++++++++++++++++++++++++++++++++
 4 files changed, 314 insertions(+)
 create mode 100644 drivers/spi/mxs_spi.c

diff --git a/arch/arm/mach-mxs/include/mach/ssp.h b/arch/arm/mach-mxs/include/mach/ssp.h
index f91770f..067cf12 100644
--- a/arch/arm/mach-mxs/include/mach/ssp.h
+++ b/arch/arm/mach-mxs/include/mach/ssp.h
@@ -23,6 +23,7 @@
 #define SSP_CTRL0_BUS_WIDTH(x)		(((x) & 0x3) << 22)
 #define SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
 #define SSP_CTRL0_WAIT_FOR_CMD		(1 << 20)
+#define SSP_CTRL0_SSP_ASSERT_OUT(x)	(((x) & 0x3) << 20)
 #define SSP_CTRL0_LONG_RESP		(1 << 19)
 #define SSP_CTRL0_GET_RESP		(1 << 17)
 #define SSP_CTRL0_ENABLE		(1 << 16)
@@ -51,6 +52,7 @@
 /* bit definition for register HW_SSP_CTRL1 */
 #define SSP_CTRL1_POLARITY		(1 << 9)
 #define SSP_CTRL1_PHASE			(1 << 10)
+#define SSP_CTRL1_DMA_ENABLE		(1 << 13)
 #define SSP_CTRL1_WORD_LENGTH(x)	(((x) & 0xf) << 4)
 #define SSP_CTRL1_SSP_MODE(x)		((x) & 0xf)
 
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 10b8fea..218c2ff 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -33,6 +33,11 @@ config DRIVER_SPI_IMX_2_3
 	depends on ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6
 	default y
 
+config DRIVER_SPI_MXS
+	bool "i.MX (23,28) SPI Master driver"
+	depends on ARCH_MXS
+	depends on SPI
+
 config DRIVER_SPI_OMAP3
 	bool "OMAP3 McSPI Master driver"
 	depends on ARCH_OMAP3
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b53061e..642b7ec 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_SPI) += spi.o
 obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
+obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o
 obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o
 obj-$(CONFIG_DRIVER_SPI_ATMEL) += atmel_spi.o
 obj-$(CONFIG_DRIVER_SPI_OMAP3) += omap3_spi.o
diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
new file mode 100644
index 0000000..6fb7f9c
--- /dev/null
+++ b/drivers/spi/mxs_spi.c
@@ -0,0 +1,306 @@
+/*
+ * Freescale i.MX28 SPI driver
+ *
+ * Copyright (C) 2013 Michael Grzeschik <mgr@pengutronix.de>
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * 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.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <spi/spi.h>
+#include <clock.h>
+#include <errno.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <asm/mmu.h>
+#include <mach/generic.h>
+#include <mach/imx-regs.h>
+#include <mach/mxs.h>
+#include <mach/clock.h>
+#include <mach/ssp.h>
+
+#define	MXS_SPI_MAX_TIMEOUT		(10 * MSECOND)
+
+#define	SPI_XFER_BEGIN	0x01 /* Assert CS before transfer */
+#define	SPI_XFER_END	0x02 /* Deassert CS after transfer */
+
+struct mxs_spi {
+	struct spi_master	master;
+	uint32_t		max_khz;
+	uint32_t		mode;
+	struct clk		*clk;
+	void __iomem		*regs;
+};
+
+static inline struct mxs_spi *to_mxs(struct spi_master *master)
+{
+	return container_of(master, struct mxs_spi, master);
+}
+
+/*
+ * Set SSP/MMC bus frequency, in kHz
+ */
+static void imx_set_ssp_busclock(struct spi_master *master, uint32_t freq)
+{
+	struct mxs_spi *mxs = to_mxs(master);
+	const uint32_t sspclk = imx_get_sspclk(master->bus_num);
+	uint32_t val;
+	uint32_t divide, rate, tgtclk;
+
+	/*
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	for (divide = 2; divide < 254; divide += 2) {
+		rate = sspclk / freq / divide;
+		if (rate <= 256)
+			break;
+	}
+
+	tgtclk = sspclk / divide / rate;
+	while (tgtclk > freq) {
+		rate++;
+		tgtclk = sspclk / divide / rate;
+	}
+	if (rate > 256)
+		rate = 256;
+
+	/* Always set timeout the maximum */
+	val = SSP_TIMING_TIMEOUT_MASK |
+		SSP_TIMING_CLOCK_DIVIDE(divide) |
+		SSP_TIMING_CLOCK_RATE(rate - 1);
+	writel(val, mxs->regs + HW_SSP_TIMING);
+
+	debug("SPI%d: Set freq rate to %d KHz (requested %d KHz)\n",
+		bus, tgtclk, freq);
+}
+
+static int mxs_spi_setup(struct spi_device *spi)
+{
+	struct spi_master *master = spi->master;
+	struct mxs_spi *mxs = to_mxs(master);
+	uint32_t val = 0;
+
+	/* MXS SPI: 4 ports and 3 chip selects maximum */
+	if (master->bus_num > 3 || spi->chip_select > 2) {
+		printf("mxs_spi: invalid bus %d / chip select %d\n",
+			 master->bus_num, spi->chip_select);
+		return -EINVAL;
+	}
+
+	mxs_reset_block(mxs->regs + HW_SSP_CTRL0, 0);
+
+	val |= SSP_CTRL0_SSP_ASSERT_OUT(spi->chip_select);
+	val |= SSP_CTRL0_BUS_WIDTH(0);
+	writel(val, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+
+	val = SSP_CTRL1_SSP_MODE(0) | SSP_CTRL1_WORD_LENGTH(7);
+	val |= (mxs->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+	val |= (mxs->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+	writel(val, mxs->regs + HW_SSP_CTRL1);
+
+	writel(0x0, mxs->regs + HW_SSP_CMD0);
+	writel(0x0, mxs->regs + HW_SSP_CMD1);
+
+	imx_set_ssp_busclock(master, spi->max_speed_hz);
+
+	return 0;
+}
+
+static void mxs_spi_start_xfer(struct mxs_spi *mxs)
+{
+	writel(SSP_CTRL0_LOCK_CS, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+	writel(SSP_CTRL0_IGNORE_CRC, mxs->regs + HW_SSP_CTRL0 + BIT_CLR);
+}
+
+static void mxs_spi_end_xfer(struct mxs_spi *mxs)
+{
+	writel(SSP_CTRL0_LOCK_CS, mxs->regs + HW_SSP_CTRL0 + BIT_CLR);
+	writel(SSP_CTRL0_IGNORE_CRC, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+}
+
+static uint32_t mxs_spi_cs_to_reg(unsigned cs)
+{
+	uint32_t select = 0;
+
+	if (cs & 1)
+		select |= SSP_CTRL0_WAIT_FOR_CMD;
+	if (cs & 2)
+		select |= SSP_CTRL0_WAIT_FOR_IRQ;
+
+	return select;
+}
+
+static void mxs_spi_set_cs(struct spi_device *spi)
+{
+	const uint32_t mask = SSP_CTRL0_WAIT_FOR_CMD | SSP_CTRL0_WAIT_FOR_IRQ;
+	uint32_t select;
+	struct mxs_spi *mxs = to_mxs(spi->master);
+
+	writel(mask, mxs->regs + HW_SSP_CTRL0 + BIT_CLR);
+	select = mxs_spi_cs_to_reg(spi->chip_select);
+	writel(select, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+}
+
+static int mxs_spi_xfer_pio(struct spi_device *spi,
+			char *data, int length, int write, unsigned long flags)
+{
+	struct mxs_spi *mxs = to_mxs(spi->master);
+
+	if (flags & SPI_XFER_BEGIN)
+		mxs_spi_start_xfer(mxs);
+
+	mxs_spi_set_cs(spi);
+
+	while (length--) {
+		if ((flags & SPI_XFER_END) && !length)
+			mxs_spi_end_xfer(mxs);
+
+		/* We transfer 1 byte */
+		writel(1, mxs->regs + HW_SSP_XFER_COUNT);
+
+		if (write)
+			writel(SSP_CTRL0_READ, mxs->regs + HW_SSP_CTRL0 + BIT_CLR);
+		else
+			writel(SSP_CTRL0_READ, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+
+		writel(SSP_CTRL0_RUN, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+
+		if (wait_on_timeout(MXS_SPI_MAX_TIMEOUT,
+				(readl(mxs->regs + HW_SSP_CTRL0) & SSP_CTRL0_RUN) == SSP_CTRL0_RUN)) {
+			printf("MXS SPI: Timeout waiting for start\n");
+			return -ETIMEDOUT;
+		}
+
+		if (write)
+			writel(*data++, mxs->regs + HW_SSP_DATA);
+
+		writel(SSP_CTRL0_DATA_XFER, mxs->regs + HW_SSP_CTRL0 + BIT_SET);
+
+		if (!write) {
+			if (wait_on_timeout(MXS_SPI_MAX_TIMEOUT,
+				!(readl(mxs->regs + HW_SSP_STATUS) & SSP_STATUS_FIFO_EMPTY))) {
+				printf("MXS SPI: Timeout waiting for data\n");
+				return -ETIMEDOUT;
+			}
+
+			*data++ = readl(mxs->regs + HW_SSP_DATA) & 0xff;
+		}
+
+		if (wait_on_timeout(MXS_SPI_MAX_TIMEOUT,
+			!(readl(mxs->regs + HW_SSP_CTRL0) & SSP_CTRL0_RUN))) {
+			printf("MXS SPI: Timeout waiting for finish\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int mxs_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct mxs_spi *mxs = to_mxs(spi->master);
+	struct spi_transfer *t = NULL;
+	char dummy;
+	unsigned long flags = 0;
+	int write = 0;
+	char *data = NULL;
+	int ret;
+	mesg->actual_length = 0;
+
+	list_for_each_entry(t, &mesg->transfers, transfer_list) {
+
+		flags = 0;
+
+		if (t->tx_buf) {
+			data = (char *) t->tx_buf;
+			write = 1;
+		} else if (t->rx_buf) {
+			data = (char *) t->rx_buf;
+			write = 0;
+		}
+
+		if (&t->transfer_list == mesg->transfers.next)
+			flags |= SPI_XFER_BEGIN;
+
+		if (&t->transfer_list == mesg->transfers.prev)
+			flags |= SPI_XFER_END;
+
+		if ((t->rx_buf && t->tx_buf)) {
+			printf("Cannot send and receive simultaneously \n");
+			break;
+		}
+
+		if ((!t->rx_buf && !t->tx_buf)) {
+			printf("No Data\n");
+			break;
+		}
+
+		if (t->len == 0) {
+			if (flags == SPI_XFER_END) {
+				t->len = 1;
+				t->rx_buf = (void *) &dummy;
+			} else {
+				return 0;
+			}
+		}
+
+		writel(SSP_CTRL1_DMA_ENABLE, mxs->regs + HW_SSP_CTRL1 + BIT_CLR);
+		ret = mxs_spi_xfer_pio(spi, data, t->len, write, flags);
+		mesg->actual_length += t->len;
+	}
+
+	return 0;
+}
+
+static int mxs_spi_probe(struct device_d *dev)
+{
+	struct spi_master *master;
+	struct mxs_spi *mxs;
+
+	mxs = xzalloc(sizeof(*mxs));
+	if (!mxs)
+		return -ENOMEM;
+
+	master = &mxs->master;
+	master->dev = dev;
+
+	master->bus_num = dev->id;
+	master->setup = mxs_spi_setup;
+	master->transfer = mxs_spi_transfer;
+	master->num_chipselect = 3;
+	mxs->mode = SPI_CPOL | SPI_CPHA;
+
+	mxs->regs = dev_request_mem_region(dev, 0);
+
+	spi_register_master(master);
+
+	return 0;
+}
+
+static struct driver_d mxs_spi_driver = {
+	.name  = "mxs_spi",
+	.probe = mxs_spi_probe,
+};
+
+static int __init mxs_spi_init(void)
+{
+	platform_driver_register(&mxs_spi_driver);
+	return 0;
+}
+
+device_initcall(mxs_spi_init);
+
+MODULE_AUTHOR("Denx Software Engeneering and Michael Grzeschik");
+MODULE_DESCRIPTION("MXS SPI driver");
+MODULE_LICENSE("GPL");
-- 
1.7.10.4


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

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

* [PATCH 2/3] mxs_spi: initial commit
  2013-02-04 16:26 [PATCH 0/3] Add mxs spi driver and mx28evk as its first user Michael Grzeschik
  2013-02-04 16:26 ` [PATCH 1/3] mxs: ssp move to common register layout Michael Grzeschik
  2013-02-04 16:26 ` [PATCH 2/3] mxs_spi: initial commit Michael Grzeschik
@ 2013-02-04 16:26 ` Michael Grzeschik
  2013-02-04 17:10   ` Michael Grzeschik
  2 siblings, 1 reply; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 16:26 UTC (permalink / raw)
  To: barebox

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 arch/arm/boards/freescale-mx28-evk/mx28-evk.c |   28 +++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
index 4311473..325365b 100644
--- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
+++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
@@ -30,6 +30,7 @@
 #include <mach/mci.h>
 #include <mach/fb.h>
 #include <mach/ocotp.h>
+#include <spi/spi.h>
 
 #include <asm/armlinux.h>
 #include <asm/mmu.h>
@@ -126,6 +127,13 @@ static const uint32_t mx28evk_pads[] = {
 	GPMI_ALE | VE_3_3V,
 	GPMI_CLE | VE_3_3V,
 	GPMI_RESETN,		/* act as WP, external PU */
+
+	/* SSP */
+	SSP2_D0 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MISO DO */
+	SSP2_D3 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* SS0 !CS */
+	SSP2_CMD | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MOSI DIO */
+	SSP2_SCK | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* CLK */
+
 };
 
 static struct mxs_mci_platform_data mci_pdata = {
@@ -225,6 +233,17 @@ static int mx28_evk_mem_init(void)
 }
 mem_initcall(mx28_evk_mem_init);
 
+static const struct spi_board_info mx28evk_spi_board_info[] = {
+	{
+		.name = "m25p80",
+		/* we leave this with the lower frequency
+		   as the ssp unit otherwise locks up */
+		.max_speed_hz = 32000000,
+		.bus_num = 2,
+		.chip_select = 0,
+	}
+};
+
 static int mx28_evk_devices_init(void)
 {
 	int i;
@@ -235,8 +254,11 @@ static int mx28_evk_devices_init(void)
 
 	/* enable IOCLK0 to run at the PLL frequency */
 	imx_set_ioclk(0, 480000000);
+	imx_set_ioclk(1, 320000000);
 	/* run the SSP unit clock at 100 MHz */
 	imx_set_sspclk(0, 100000000, 1);
+	/* run the SSP unit 2 clock at 160Mhz */
+	imx_set_sspclk(2, 160000000, 1);
 
 	armlinux_set_bootparams((void *)IMX_MEMORY_BASE + 0x100);
 	armlinux_set_architecture(MACH_TYPE_MX28EVK);
@@ -259,6 +281,12 @@ static int mx28_evk_devices_init(void)
 	add_generic_device("mxs_nand", 0, NULL, MXS_GPMI_BASE, 0x2000,
 			   IORESOURCE_MEM, NULL);
 
+	spi_register_board_info(mx28evk_spi_board_info,
+			ARRAY_SIZE(mx28evk_spi_board_info));
+
+	add_generic_device("mxs_spi", 2, NULL, IMX_SSP2_BASE, 0x2000,
+			   IORESOURCE_MEM, NULL);
+
 	return 0;
 }
 device_initcall(mx28_evk_devices_init);
-- 
1.7.10.4


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

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

* Re: [PATCH 2/3] mxs_spi: initial commit
  2013-02-04 16:26 ` Michael Grzeschik
@ 2013-02-04 17:10   ` Michael Grzeschik
  0 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 17:10 UTC (permalink / raw)
  To: Michael Grzeschik; +Cc: barebox

Somehow this patch doesn't have the corrent subject.
I will resend. Thanks.

On Mon, Feb 04, 2013 at 05:26:19PM +0100, Michael Grzeschik wrote:
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> ---
>  arch/arm/boards/freescale-mx28-evk/mx28-evk.c |   28 +++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
> 
> diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
> index 4311473..325365b 100644
> --- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
> +++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
> @@ -30,6 +30,7 @@
>  #include <mach/mci.h>
>  #include <mach/fb.h>
>  #include <mach/ocotp.h>
> +#include <spi/spi.h>
>  
>  #include <asm/armlinux.h>
>  #include <asm/mmu.h>
> @@ -126,6 +127,13 @@ static const uint32_t mx28evk_pads[] = {
>  	GPMI_ALE | VE_3_3V,
>  	GPMI_CLE | VE_3_3V,
>  	GPMI_RESETN,		/* act as WP, external PU */
> +
> +	/* SSP */
> +	SSP2_D0 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MISO DO */
> +	SSP2_D3 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* SS0 !CS */
> +	SSP2_CMD | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MOSI DIO */
> +	SSP2_SCK | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* CLK */
> +
>  };
>  
>  static struct mxs_mci_platform_data mci_pdata = {
> @@ -225,6 +233,17 @@ static int mx28_evk_mem_init(void)
>  }
>  mem_initcall(mx28_evk_mem_init);
>  
> +static const struct spi_board_info mx28evk_spi_board_info[] = {
> +	{
> +		.name = "m25p80",
> +		/* we leave this with the lower frequency
> +		   as the ssp unit otherwise locks up */
> +		.max_speed_hz = 32000000,
> +		.bus_num = 2,
> +		.chip_select = 0,
> +	}
> +};
> +
>  static int mx28_evk_devices_init(void)
>  {
>  	int i;
> @@ -235,8 +254,11 @@ static int mx28_evk_devices_init(void)
>  
>  	/* enable IOCLK0 to run at the PLL frequency */
>  	imx_set_ioclk(0, 480000000);
> +	imx_set_ioclk(1, 320000000);
>  	/* run the SSP unit clock at 100 MHz */
>  	imx_set_sspclk(0, 100000000, 1);
> +	/* run the SSP unit 2 clock at 160Mhz */
> +	imx_set_sspclk(2, 160000000, 1);
>  
>  	armlinux_set_bootparams((void *)IMX_MEMORY_BASE + 0x100);
>  	armlinux_set_architecture(MACH_TYPE_MX28EVK);
> @@ -259,6 +281,12 @@ static int mx28_evk_devices_init(void)
>  	add_generic_device("mxs_nand", 0, NULL, MXS_GPMI_BASE, 0x2000,
>  			   IORESOURCE_MEM, NULL);
>  
> +	spi_register_board_info(mx28evk_spi_board_info,
> +			ARRAY_SIZE(mx28evk_spi_board_info));
> +
> +	add_generic_device("mxs_spi", 2, NULL, IMX_SSP2_BASE, 0x2000,
> +			   IORESOURCE_MEM, NULL);
> +
>  	return 0;
>  }
>  device_initcall(mx28_evk_devices_init);
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
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] 6+ messages in thread

* [PATCH 0/3] Add mxs spi driver and mx28evk as its first user
@ 2013-02-04 17:26 Michael Grzeschik
  0 siblings, 0 replies; 6+ messages in thread
From: Michael Grzeschik @ 2013-02-04 17:26 UTC (permalink / raw)
  To: barebox

this series adds support for the mxs spi driver
and adds the mx28evk as the first user to use it
with an m25p80 flash memory.

The driver was tested to work with the pio mode,
as its implementation has currently no dma support.

The SSP clock needed to be lower than the max possible
frequency for the flash. Otherwise it sometimes, after
a lot of spi transactions, the SSP stopped working.

Michael Grzeschik (3):
  mxs: ssp move to common register layout
  mxs_spi: initial commit
  mx28evk: add m25p80 flash via ssp2

 arch/arm/boards/freescale-mx28-evk/mx28-evk.c |   28 +++
 arch/arm/mach-mxs/include/mach/imx23-regs.h   |   16 ++
 arch/arm/mach-mxs/include/mach/imx28-regs.h   |   21 ++
 arch/arm/mach-mxs/include/mach/ssp.h          |   79 +++++++
 drivers/mci/mxs.c                             |  118 +---------
 drivers/spi/Kconfig                           |    5 +
 drivers/spi/Makefile                          |    1 +
 drivers/spi/mxs_spi.c                         |  306 +++++++++++++++++++++++++
 8 files changed, 457 insertions(+), 117 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/ssp.h
 create mode 100644 drivers/spi/mxs_spi.c

-- 
1.7.10.4


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

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

end of thread, other threads:[~2013-02-04 17:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-04 16:26 [PATCH 0/3] Add mxs spi driver and mx28evk as its first user Michael Grzeschik
2013-02-04 16:26 ` [PATCH 1/3] mxs: ssp move to common register layout Michael Grzeschik
2013-02-04 16:26 ` [PATCH 2/3] mxs_spi: initial commit Michael Grzeschik
2013-02-04 16:26 ` Michael Grzeschik
2013-02-04 17:10   ` Michael Grzeschik
2013-02-04 17:26 [PATCH 0/3] Add mxs spi driver and mx28evk as its first user Michael Grzeschik

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