* [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 02/10] mmc: spi: Rename IMX2[38]_MMC to IMX2[38]_SSP Marek Vasut
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Move the definitions into separate file so separate SPI driver can be
implemented. The SSP controller in MXS can act both as a MMC host and
as a SPI host.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/mmc/host/mxs-mmc.c | 87 ++--------------------------------
include/linux/spi/mxs-spi.h | 109 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 84 deletions(-)
create mode 100644 include/linux/spi/mxs-spi.h
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 93b661d..584f982 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -45,87 +45,10 @@
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/mmc/mxs-mmc.h>
+#include <linux/spi/mxs-spi.h>
#define DRIVER_NAME "mxs-mmc"
-/* card detect polling timeout */
-#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
-
-#define ssp_is_old(host) ((host)->devid == IMX23_MMC)
-
-/* SSP registers */
-#define HW_SSP_CTRL0 0x000
-#define BM_SSP_CTRL0_RUN (1 << 29)
-#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28)
-#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26)
-#define BM_SSP_CTRL0_READ (1 << 25)
-#define BM_SSP_CTRL0_DATA_XFER (1 << 24)
-#define BP_SSP_CTRL0_BUS_WIDTH (22)
-#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22)
-#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
-#define BM_SSP_CTRL0_LONG_RESP (1 << 19)
-#define BM_SSP_CTRL0_GET_RESP (1 << 17)
-#define BM_SSP_CTRL0_ENABLE (1 << 16)
-#define BP_SSP_CTRL0_XFER_COUNT (0)
-#define BM_SSP_CTRL0_XFER_COUNT (0xffff)
-#define HW_SSP_CMD0 0x010
-#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25)
-#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22)
-#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21)
-#define BM_SSP_CMD0_APPEND_8CYC (1 << 20)
-#define BP_SSP_CMD0_BLOCK_SIZE (16)
-#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16)
-#define BP_SSP_CMD0_BLOCK_COUNT (8)
-#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8)
-#define BP_SSP_CMD0_CMD (0)
-#define BM_SSP_CMD0_CMD (0xff)
-#define HW_SSP_CMD1 0x020
-#define HW_SSP_XFER_SIZE 0x030
-#define HW_SSP_BLOCK_SIZE 0x040
-#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT (4)
-#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4)
-#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0)
-#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf)
-#define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070)
-#define BP_SSP_TIMING_TIMEOUT (16)
-#define BM_SSP_TIMING_TIMEOUT (0xffff << 16)
-#define BP_SSP_TIMING_CLOCK_DIVIDE (8)
-#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8)
-#define BP_SSP_TIMING_CLOCK_RATE (0)
-#define BM_SSP_TIMING_CLOCK_RATE (0xff)
-#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080)
-#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31)
-#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30)
-#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29)
-#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28)
-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27)
-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26)
-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25)
-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24)
-#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23)
-#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22)
-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21)
-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20)
-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17)
-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16)
-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15)
-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14)
-#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13)
-#define BM_SSP_CTRL1_POLARITY (1 << 9)
-#define BP_SSP_CTRL1_WORD_LENGTH (4)
-#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4)
-#define BP_SSP_CTRL1_SSP_MODE (0)
-#define BM_SSP_CTRL1_SSP_MODE (0xf)
-#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0)
-#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0)
-#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0)
-#define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0)
-#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100)
-#define BM_SSP_STATUS_CARD_DETECT (1 << 28)
-#define BM_SSP_STATUS_SDIO_IRQ (1 << 17)
-
-#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field)
-
#define MXS_MMC_IRQ_BITS (BM_SSP_CTRL1_SDIO_IRQ | \
BM_SSP_CTRL1_RESP_ERR_IRQ | \
BM_SSP_CTRL1_RESP_TIMEOUT_IRQ | \
@@ -135,12 +58,8 @@
BM_SSP_CTRL1_RECV_TIMEOUT_IRQ | \
BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
-#define SSP_PIO_NUM 3
-
-enum mxs_mmc_id {
- IMX23_MMC,
- IMX28_MMC,
-};
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
struct mxs_mmc_host {
struct mmc_host *mmc;
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
new file mode 100644
index 0000000..b7ccd57
--- /dev/null
+++ b/include/linux/spi/mxs-spi.h
@@ -0,0 +1,109 @@
+/*
+ * include/linux/spi/mxs-spi.h
+ *
+ * Freescale i.MX233/i.MX28 SPI controller register definition
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LINUX_SPI_MXS_SPI_H__
+#define __LINUX_SPI_MXS_SPI_H__
+
+#define ssp_is_old(host) ((host)->devid == IMX23_MMC)
+
+/* SSP registers */
+#define HW_SSP_CTRL0 0x000
+#define BM_SSP_CTRL0_RUN (1 << 29)
+#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28)
+#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26)
+#define BM_SSP_CTRL0_READ (1 << 25)
+#define BM_SSP_CTRL0_DATA_XFER (1 << 24)
+#define BP_SSP_CTRL0_BUS_WIDTH 22
+#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22)
+#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
+#define BM_SSP_CTRL0_LONG_RESP (1 << 19)
+#define BM_SSP_CTRL0_GET_RESP (1 << 17)
+#define BM_SSP_CTRL0_ENABLE (1 << 16)
+#define BP_SSP_CTRL0_XFER_COUNT 0
+#define BM_SSP_CTRL0_XFER_COUNT 0xffff
+#define HW_SSP_CMD0 0x010
+#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25)
+#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22)
+#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21)
+#define BM_SSP_CMD0_APPEND_8CYC (1 << 20)
+#define BP_SSP_CMD0_BLOCK_SIZE 16
+#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16)
+#define BP_SSP_CMD0_BLOCK_COUNT 8
+#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8)
+#define BP_SSP_CMD0_CMD 0
+#define BM_SSP_CMD0_CMD 0xff
+#define HW_SSP_CMD1 0x020
+#define HW_SSP_XFER_SIZE 0x030
+#define HW_SSP_BLOCK_SIZE 0x040
+#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT 4
+#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4)
+#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE 0
+#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE 0xf
+#define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070)
+#define BP_SSP_TIMING_TIMEOUT 16
+#define BM_SSP_TIMING_TIMEOUT (0xffff << 16)
+#define BP_SSP_TIMING_CLOCK_DIVIDE 8
+#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8)
+#define BP_SSP_TIMING_CLOCK_RATE 0
+#define BM_SSP_TIMING_CLOCK_RATE 0xff
+#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080)
+#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31)
+#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30)
+#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29)
+#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28)
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27)
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26)
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25)
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24)
+#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23)
+#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22)
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21)
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20)
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17)
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16)
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15)
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14)
+#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13)
+#define BM_SSP_CTRL1_POLARITY (1 << 9)
+#define BP_SSP_CTRL1_WORD_LENGTH 4
+#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4)
+#define BP_SSP_CTRL1_SSP_MODE 0
+#define BM_SSP_CTRL1_SSP_MODE 0xf
+#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100)
+#define BM_SSP_STATUS_CARD_DETECT (1 << 28)
+#define BM_SSP_STATUS_SDIO_IRQ (1 << 17)
+
+#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define SSP_PIO_NUM 3
+
+enum mxs_mmc_id {
+ IMX23_MMC,
+ IMX28_MMC,
+};
+
+#endif /* __LINUX_SPI_MXS_SPI_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 02/10] mmc: spi: Rename IMX2[38]_MMC to IMX2[38]_SSP
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
2012-07-16 12:09 ` [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 03/10] mmc: spi: Add necessary bits into mxs-spi.h Marek Vasut
` (7 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Since the SSP controller can act as both SPI and MMC host,
renaming the enum to properly reflect the naming seems
appropriate.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/mmc/host/mxs-mmc.c | 18 +++++++++---------
include/linux/spi/mxs-spi.h | 8 ++++----
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 584f982..f9509e8 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -78,7 +78,7 @@ struct mxs_mmc_host {
enum dma_transfer_direction slave_dirn;
u32 ssp_pio_words[SSP_PIO_NUM];
- enum mxs_mmc_id devid;
+ enum mxs_ssp_id devid;
unsigned char bus_width;
spinlock_t lock;
int sdio_irq_en;
@@ -601,22 +601,22 @@ static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
return true;
}
-static struct platform_device_id mxs_mmc_ids[] = {
+static struct platform_device_id mxs_ssp_ids[] = {
{
.name = "imx23-mmc",
- .driver_data = IMX23_MMC,
+ .driver_data = IMX23_SSP,
}, {
.name = "imx28-mmc",
- .driver_data = IMX28_MMC,
+ .driver_data = IMX28_SSP,
}, {
/* sentinel */
}
};
-MODULE_DEVICE_TABLE(platform, mxs_mmc_ids);
+MODULE_DEVICE_TABLE(platform, mxs_ssp_ids);
static const struct of_device_id mxs_mmc_dt_ids[] = {
- { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_MMC, },
- { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_MMC, },
+ { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_SSP, },
+ { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_SSP, },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids);
@@ -655,7 +655,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
}
if (np) {
- host->devid = (enum mxs_mmc_id) of_id->data;
+ host->devid = (enum mxs_ssp_id) of_id->data;
/*
* TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helpers get in.
@@ -829,7 +829,7 @@ static const struct dev_pm_ops mxs_mmc_pm_ops = {
static struct platform_driver mxs_mmc_driver = {
.probe = mxs_mmc_probe,
.remove = mxs_mmc_remove,
- .id_table = mxs_mmc_ids,
+ .id_table = mxs_ssp_ids,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index b7ccd57..c08aef5 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -24,7 +24,7 @@
#ifndef __LINUX_SPI_MXS_SPI_H__
#define __LINUX_SPI_MXS_SPI_H__
-#define ssp_is_old(host) ((host)->devid == IMX23_MMC)
+#define ssp_is_old(host) ((host)->devid == IMX23_SSP)
/* SSP registers */
#define HW_SSP_CTRL0 0x000
@@ -101,9 +101,9 @@
#define SSP_PIO_NUM 3
-enum mxs_mmc_id {
- IMX23_MMC,
- IMX28_MMC,
+enum mxs_ssp_id {
+ IMX23_SSP,
+ IMX28_SSP,
};
#endif /* __LINUX_SPI_MXS_SPI_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 03/10] mmc: spi: Add necessary bits into mxs-spi.h
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
2012-07-16 12:09 ` [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file Marek Vasut
2012-07-16 12:09 ` [PATCH 02/10] mmc: spi: Rename IMX2[38]_MMC to IMX2[38]_SSP Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 04/10] mmc: spi: Pull out parts shared between MMC and SPI Marek Vasut
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Add missing register bits and registers into mxs-spi.h .
These will be used by the SPI driver.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
include/linux/spi/mxs-spi.h | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index c08aef5..b0a0335 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -30,12 +30,14 @@
#define HW_SSP_CTRL0 0x000
#define BM_SSP_CTRL0_RUN (1 << 29)
#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28)
+#define BM_SSP_CTRL0_LOCK_CS (1 << 27)
#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26)
#define BM_SSP_CTRL0_READ (1 << 25)
#define BM_SSP_CTRL0_DATA_XFER (1 << 24)
#define BP_SSP_CTRL0_BUS_WIDTH 22
#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22)
#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
+#define BM_SSP_CTRL0_WAIT_FOR_CMD (1 << 20)
#define BM_SSP_CTRL0_LONG_RESP (1 << 19)
#define BM_SSP_CTRL0_GET_RESP (1 << 17)
#define BM_SSP_CTRL0_ENABLE (1 << 16)
@@ -64,8 +66,12 @@
#define BM_SSP_TIMING_TIMEOUT (0xffff << 16)
#define BP_SSP_TIMING_CLOCK_DIVIDE 8
#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8)
+#define BF_SSP_TIMING_CLOCK_DIVIDE(v) \
+ (((v) << 8) & BM_SSP_TIMING_CLOCK_DIVIDE)
#define BP_SSP_TIMING_CLOCK_RATE 0
#define BM_SSP_TIMING_CLOCK_RATE 0xff
+#define BF_SSP_TIMING_CLOCK_RATE(v) \
+ (((v) << 0) & BM_SSP_TIMING_CLOCK_RATE)
#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080)
#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31)
#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30)
@@ -84,11 +90,26 @@
#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15)
#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14)
#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13)
+#define BM_SSP_CTRL1_PHASE (1 << 10)
#define BM_SSP_CTRL1_POLARITY (1 << 9)
#define BP_SSP_CTRL1_WORD_LENGTH 4
#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4)
+#define BF_SSP_CTRL1_WORD_LENGTH(v) \
+ (((v) << 4) & BM_SSP_CTRL1_WORD_LENGTH)
+#define BV_SSP_CTRL1_WORD_LENGTH__FOUR_BITS 0x3
+#define BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS 0x7
+#define BV_SSP_CTRL1_WORD_LENGTH__SIXTEEN_BITS 0xF
#define BP_SSP_CTRL1_SSP_MODE 0
#define BM_SSP_CTRL1_SSP_MODE 0xf
+#define BF_SSP_CTRL1_SSP_MODE(v) \
+ (((v) << 0) & BM_SSP_CTRL1_SSP_MODE)
+#define BV_SSP_CTRL1_SSP_MODE__SPI 0x0
+#define BV_SSP_CTRL1_SSP_MODE__SSI 0x1
+#define BV_SSP_CTRL1_SSP_MODE__SD_MMC 0x3
+#define BV_SSP_CTRL1_SSP_MODE__MS 0x4
+
+#define HW_SSP_DATA 0x090
+
#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0)
#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0)
#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0)
@@ -96,6 +117,7 @@
#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100)
#define BM_SSP_STATUS_CARD_DETECT (1 << 28)
#define BM_SSP_STATUS_SDIO_IRQ (1 << 17)
+#define BM_SSP_STATUS_FIFO_EMPTY (1 << 5)
#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 04/10] mmc: spi: Pull out parts shared between MMC and SPI
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (2 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 03/10] mmc: spi: Add necessary bits into mxs-spi.h Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function Marek Vasut
` (5 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Abstract out the common part of private data shared between MMC
and SPI. These shall later allow to use common clock configuration
function.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/mmc/host/mxs-mmc.c | 107 ++++++++++++++++++++++++-------------------
include/linux/spi/mxs-spi.h | 8 ++++
2 files changed, 67 insertions(+), 48 deletions(-)
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index f9509e8..1ea1cba 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -62,23 +62,20 @@
#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
struct mxs_mmc_host {
+ struct mxs_ssp ssp;
+
struct mmc_host *mmc;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
- void __iomem *base;
int dma_channel;
- struct clk *clk;
- unsigned int clk_rate;
-
struct dma_chan *dmach;
struct mxs_dma_data dma_data;
unsigned int dma_dir;
enum dma_transfer_direction slave_dirn;
u32 ssp_pio_words[SSP_PIO_NUM];
- enum mxs_ssp_id devid;
unsigned char bus_width;
spinlock_t lock;
int sdio_irq_en;
@@ -105,16 +102,18 @@ static int mxs_mmc_get_ro(struct mmc_host *mmc)
static int mxs_mmc_get_cd(struct mmc_host *mmc)
{
struct mxs_mmc_host *host = mmc_priv(mmc);
+ struct mxs_ssp *ssp = &host->ssp;
- return !(readl(host->base + HW_SSP_STATUS(host)) &
+ return !(readl(ssp->base + HW_SSP_STATUS(ssp)) &
BM_SSP_STATUS_CARD_DETECT);
}
static void mxs_mmc_reset(struct mxs_mmc_host *host)
{
+ struct mxs_ssp *ssp = &host->ssp;
u32 ctrl0, ctrl1;
- stmp_reset_block(host->base);
+ stmp_reset_block(ssp->base);
ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
@@ -130,15 +129,15 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host)
writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
BF_SSP(2, TIMING_CLOCK_DIVIDE) |
BF_SSP(0, TIMING_CLOCK_RATE),
- host->base + HW_SSP_TIMING(host));
+ ssp->base + HW_SSP_TIMING(ssp));
if (host->sdio_irq_en) {
ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
}
- writel(ctrl0, host->base + HW_SSP_CTRL0);
- writel(ctrl1, host->base + HW_SSP_CTRL1(host));
+ writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+ writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp));
}
static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -149,15 +148,16 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host)
struct mmc_command *cmd = host->cmd;
struct mmc_data *data = host->data;
struct mmc_request *mrq = host->mrq;
+ struct mxs_ssp *ssp = &host->ssp;
if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
if (mmc_resp_type(cmd) & MMC_RSP_136) {
- cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0(host));
- cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1(host));
- cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2(host));
- cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3(host));
+ cmd->resp[3] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
+ cmd->resp[2] = readl(ssp->base + HW_SSP_SDRESP1(ssp));
+ cmd->resp[1] = readl(ssp->base + HW_SSP_SDRESP2(ssp));
+ cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP3(ssp));
} else {
- cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0(host));
+ cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
}
}
@@ -196,13 +196,14 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
struct mxs_mmc_host *host = dev_id;
struct mmc_command *cmd = host->cmd;
struct mmc_data *data = host->data;
+ struct mxs_ssp *ssp = &host->ssp;
u32 stat;
spin_lock(&host->lock);
- stat = readl(host->base + HW_SSP_CTRL1(host));
+ stat = readl(ssp->base + HW_SSP_CTRL1(ssp));
writel(stat & MXS_MMC_IRQ_BITS,
- host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
mmc_signal_sdio_irq(host->mmc);
@@ -366,6 +367,8 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
unsigned int data_size = 0, log2_blksz;
unsigned int blocks = data->blocks;
+ struct mxs_ssp *ssp = &host->ssp;
+
u32 ignore_crc, get_resp, long_resp, read;
u32 ctrl0, cmd0, cmd1, val;
@@ -408,15 +411,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
blocks = 1;
/* xfer count, block size and count need to be set differently */
- if (ssp_is_old(host)) {
+ if (ssp_is_old(ssp)) {
ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
} else {
- writel(data_size, host->base + HW_SSP_XFER_SIZE);
+ writel(data_size, ssp->base + HW_SSP_XFER_SIZE);
writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
- host->base + HW_SSP_BLOCK_SIZE);
+ ssp->base + HW_SSP_BLOCK_SIZE);
}
if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
@@ -431,11 +434,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
}
/* set the timeout count */
- timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
- val = readl(host->base + HW_SSP_TIMING(host));
+ timeout = mxs_ns_to_ssp_ticks(ssp->clk_rate, data->timeout_ns);
+ val = readl(ssp->base + HW_SSP_TIMING(ssp));
val &= ~(BM_SSP_TIMING_TIMEOUT);
val |= BF_SSP(timeout, TIMING_TIMEOUT);
- writel(val, host->base + HW_SSP_TIMING(host));
+ writel(val, ssp->base + HW_SSP_TIMING(ssp));
/* pio */
host->ssp_pio_words[0] = ctrl0;
@@ -500,11 +503,12 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
{
+ struct mxs_ssp *ssp = &host->ssp;
unsigned int ssp_clk, ssp_sck;
u32 clock_divide, clock_rate;
u32 val;
- ssp_clk = clk_get_rate(host->clk);
+ ssp_clk = clk_get_rate(ssp->clk);
for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
@@ -521,13 +525,13 @@ static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
- val = readl(host->base + HW_SSP_TIMING(host));
+ val = readl(ssp->base + HW_SSP_TIMING(ssp));
val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
- writel(val, host->base + HW_SSP_TIMING(host));
+ writel(val, ssp->base + HW_SSP_TIMING(ssp));
- host->clk_rate = ssp_sck;
+ ssp->clk_rate = ssp_sck;
dev_dbg(mmc_dev(host->mmc),
"%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
@@ -552,6 +556,7 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct mxs_mmc_host *host = mmc_priv(mmc);
+ struct mxs_ssp *ssp = &host->ssp;
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
@@ -560,19 +565,19 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
if (enable) {
writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
- host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
- host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
+ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
- if (readl(host->base + HW_SSP_STATUS(host)) &
+ if (readl(ssp->base + HW_SSP_STATUS(ssp)) &
BM_SSP_STATUS_SDIO_IRQ)
mmc_signal_sdio_irq(host->mmc);
} else {
writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
- host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
- host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
+ ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
}
spin_unlock_irqrestore(&host->lock, flags);
@@ -635,6 +640,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
dma_cap_mask_t mask;
struct regulator *reg_vmmc;
enum of_gpio_flags flags;
+ struct mxs_ssp *ssp;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -648,14 +654,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)
return -ENOMEM;
host = mmc_priv(mmc);
- host->base = devm_request_and_ioremap(&pdev->dev, iores);
- if (!host->base) {
+ ssp = &host->ssp;
+ ssp->dev = &pdev->dev;
+ ssp->base = devm_request_and_ioremap(&pdev->dev, iores);
+ if (!ssp->base) {
ret = -EADDRNOTAVAIL;
goto out_mmc_free;
}
if (np) {
- host->devid = (enum mxs_ssp_id) of_id->data;
+ ssp->devid = (enum mxs_ssp_id) of_id->data;
/*
* TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helpers get in.
@@ -668,7 +676,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
goto out_mmc_free;
}
} else {
- host->devid = pdev->id_entry->driver_data;
+ ssp->devid = pdev->id_entry->driver_data;
host->dma_channel = dmares->start;
}
@@ -691,12 +699,12 @@ static int mxs_mmc_probe(struct platform_device *pdev)
goto out_mmc_free;
}
- host->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(host->clk)) {
- ret = PTR_ERR(host->clk);
+ ssp->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ssp->clk)) {
+ ret = PTR_ERR(ssp->clk);
goto out_mmc_free;
}
- clk_prepare_enable(host->clk);
+ clk_prepare_enable(ssp->clk);
mxs_mmc_reset(host);
@@ -741,8 +749,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->max_segs = 52;
mmc->max_blk_size = 1 << 0xf;
- mmc->max_blk_count = (ssp_is_old(host)) ? 0xff : 0xffffff;
- mmc->max_req_size = (ssp_is_old(host)) ? 0xffff : 0xffffffff;
+ mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff;
+ mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff;
mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
platform_set_drvdata(pdev, mmc);
@@ -766,8 +774,8 @@ out_free_dma:
if (host->dmach)
dma_release_channel(host->dmach);
out_clk_put:
- clk_disable_unprepare(host->clk);
- clk_put(host->clk);
+ clk_disable_unprepare(ssp->clk);
+ clk_put(ssp->clk);
out_mmc_free:
mmc_free_host(mmc);
return ret;
@@ -777,6 +785,7 @@ static int mxs_mmc_remove(struct platform_device *pdev)
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct mxs_mmc_host *host = mmc_priv(mmc);
+ struct mxs_ssp *ssp = &host->ssp;
mmc_remove_host(mmc);
@@ -785,8 +794,8 @@ static int mxs_mmc_remove(struct platform_device *pdev)
if (host->dmach)
dma_release_channel(host->dmach);
- clk_disable_unprepare(host->clk);
- clk_put(host->clk);
+ clk_disable_unprepare(ssp->clk);
+ clk_put(ssp->clk);
mmc_free_host(mmc);
@@ -798,11 +807,12 @@ static int mxs_mmc_suspend(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
struct mxs_mmc_host *host = mmc_priv(mmc);
+ struct mxs_ssp *ssp = &host->ssp;
int ret = 0;
ret = mmc_suspend_host(mmc);
- clk_disable_unprepare(host->clk);
+ clk_disable_unprepare(ssp->clk);
return ret;
}
@@ -811,9 +821,10 @@ static int mxs_mmc_resume(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
struct mxs_mmc_host *host = mmc_priv(mmc);
+ struct mxs_ssp *ssp = &host->ssp;
int ret = 0;
- clk_prepare_enable(host->clk);
+ clk_prepare_enable(ssp->clk);
ret = mmc_resume_host(mmc);
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index b0a0335..0cb2767 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -128,4 +128,12 @@ enum mxs_ssp_id {
IMX28_SSP,
};
+struct mxs_ssp {
+ struct device *dev;
+ void __iomem *base;
+ struct clk *clk;
+ unsigned int clk_rate;
+ enum mxs_ssp_id devid;
+};
+
#endif /* __LINUX_SPI_MXS_SPI_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (3 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 04/10] mmc: spi: Pull out parts shared between MMC and SPI Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-17 13:39 ` Attila Kinali
2012-07-16 12:09 ` [PATCH 06/10] spi: Add SPI driver for mx233/mx28 Marek Vasut
` (4 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Pull out the MMC clock configuration function and make it
into SSP clock configuration function, so it can be used by
the SPI driver too.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/clk/mxs/Makefile | 2 +-
drivers/clk/mxs/clk-ssp.c | 61 +++++++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/mxs-mmc.c | 39 +--------------------------
include/linux/spi/mxs-spi.h | 2 ++
4 files changed, 65 insertions(+), 39 deletions(-)
create mode 100644 drivers/clk/mxs/clk-ssp.c
diff --git a/drivers/clk/mxs/Makefile b/drivers/clk/mxs/Makefile
index 7bedeec..a6a2223 100644
--- a/drivers/clk/mxs/Makefile
+++ b/drivers/clk/mxs/Makefile
@@ -2,7 +2,7 @@
# Makefile for mxs specific clk
#
-obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o
+obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o clk-ssp.o
obj-$(CONFIG_SOC_IMX23) += clk-imx23.o
obj-$(CONFIG_SOC_IMX28) += clk-imx28.o
diff --git a/drivers/clk/mxs/clk-ssp.c b/drivers/clk/mxs/clk-ssp.c
new file mode 100644
index 0000000..b3c1e16
--- /dev/null
+++ b/drivers/clk/mxs/clk-ssp.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 DENX Software Engineering, GmbH
+ *
+ * Pulled from code:
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/spi/mxs-spi.h>
+
+void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate)
+{
+ unsigned int ssp_clk, ssp_sck;
+ u32 clock_divide, clock_rate;
+ u32 val;
+
+ ssp_clk = clk_get_rate(ssp->clk);
+
+ for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
+ clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
+ clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
+ if (clock_rate <= 255)
+ break;
+ }
+
+ if (clock_divide > 254) {
+ dev_err(ssp->dev,
+ "%s: cannot set clock to %d\n", __func__, rate);
+ return;
+ }
+
+ ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
+
+ val = readl(ssp->base + HW_SSP_TIMING(ssp));
+ val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+ val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
+ val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
+ writel(val, ssp->base + HW_SSP_TIMING(ssp));
+
+ ssp->clk_rate = ssp_sck;
+
+ dev_dbg(ssp->dev,
+ "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
+ __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
+}
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 1ea1cba..3b1c99b 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -501,43 +501,6 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
mxs_mmc_start_cmd(host, mrq->cmd);
}
-static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
-{
- struct mxs_ssp *ssp = &host->ssp;
- unsigned int ssp_clk, ssp_sck;
- u32 clock_divide, clock_rate;
- u32 val;
-
- ssp_clk = clk_get_rate(ssp->clk);
-
- for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
- clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
- clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
- if (clock_rate <= 255)
- break;
- }
-
- if (clock_divide > 254) {
- dev_err(mmc_dev(host->mmc),
- "%s: cannot set clock to %d\n", __func__, rate);
- return;
- }
-
- ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
-
- val = readl(ssp->base + HW_SSP_TIMING(ssp));
- val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
- val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
- val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
- writel(val, ssp->base + HW_SSP_TIMING(ssp));
-
- ssp->clk_rate = ssp_sck;
-
- dev_dbg(mmc_dev(host->mmc),
- "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
- __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
-}
-
static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct mxs_mmc_host *host = mmc_priv(mmc);
@@ -550,7 +513,7 @@ static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
host->bus_width = 0;
if (ios->clock)
- mxs_mmc_set_clk_rate(host, ios->clock);
+ mxs_ssp_set_clk_rate(&host->ssp, ios->clock);
}
static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index 0cb2767..2bc8abb 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -136,4 +136,6 @@ struct mxs_ssp {
enum mxs_ssp_id devid;
};
+void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate);
+
#endif /* __LINUX_SPI_MXS_SPI_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 06/10] spi: Add SPI driver for mx233/mx28
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (4 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 07/10] mmc: spi: Pull out common DMA parts from MXS MMC Marek Vasut
` (3 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
This is slightly reworked version of the SPI driver.
Support for DT has been added and it's been converted
to queued API.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/spi/Kconfig | 7 +
drivers/spi/Makefile | 1 +
drivers/spi/spi-mxs.c | 427 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 435 insertions(+)
create mode 100644 drivers/spi/spi-mxs.c
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b7b99e7..bf131bc 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -364,6 +364,13 @@ config SPI_STMP3XXX
help
SPI driver for Freescale STMP37xx/378x SoC SSP interface
+config SPI_MXS
+ tristate "Freescale MXS SPI controller"
+ depends on ARCH_MXS
+ select STMP_DEVICE
+ help
+ SPI driver for Freescale MXS devices.
+
config SPI_TEGRA
tristate "Nvidia Tegra SPI controller"
depends on ARCH_TEGRA && (TEGRA_SYSTEM_DMA || TEGRA20_APB_DMA)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b5cbab2..e6a2ee4 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -36,6 +36,7 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o
obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
+obj-$(CONFIG_SPI_MXS) += spi-mxs.o
obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
obj-$(CONFIG_SPI_OMAP_UWIRE) += spi-omap-uwire.o
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
new file mode 100644
index 0000000..3c0b1ac
--- /dev/null
+++ b/drivers/spi/spi-mxs.c
@@ -0,0 +1,427 @@
+/*
+ * Freescale MXS SPI master driver
+ *
+ * Copyright 2012 DENX Software Engineering, GmbH.
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * Rework and transition to new API by:
+ * Marek Vasut <marex@denx.de>
+ *
+ * Based on previous attempt by:
+ * Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * Based on code from U-Boot bootloader by:
+ * Marek Vasut <marex@denx.de>
+ *
+ * Based on spi-stmp.c, which is:
+ * Author: Dmitry Pervushin <dimka@embeddedalley.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/module.h>
+#include <linux/fsl/mxs-dma.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/stmp_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/mxs-spi.h>
+
+#define DRIVER_NAME "mxs-spi"
+
+#define SSP_TIMEOUT 1000 /* 1000 ms */
+
+struct mxs_spi {
+ struct mxs_ssp ssp;
+};
+
+static int mxs_spi_setup_transfer(struct spi_device *dev,
+ struct spi_transfer *t)
+{
+ struct mxs_spi *spi = spi_master_get_devdata(dev->master);
+ struct mxs_ssp *ssp = &spi->ssp;
+ uint8_t bits_per_word;
+ uint32_t hz = 0;
+
+ bits_per_word = dev->bits_per_word;
+ if (t && t->bits_per_word)
+ bits_per_word = t->bits_per_word;
+
+ if (bits_per_word != 8) {
+ dev_err(&dev->dev, "%s, unsupported bits_per_word=%d\n",
+ __func__, bits_per_word);
+ return -EINVAL;
+ }
+
+ if (dev->max_speed_hz)
+ hz = dev->max_speed_hz;
+ if (t && t->speed_hz)
+ hz = t->speed_hz;
+ if (hz == 0) {
+ dev_err(&dev->dev, "Cannot continue with zero clock\n");
+ return -EINVAL;
+ }
+
+ mxs_ssp_set_clk_rate(ssp, hz);
+
+ writel(BF_SSP_CTRL1_SSP_MODE(BV_SSP_CTRL1_SSP_MODE__SPI) |
+ BF_SSP_CTRL1_WORD_LENGTH
+ (BV_SSP_CTRL1_WORD_LENGTH__EIGHT_BITS) |
+ ((dev->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) |
+ ((dev->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0),
+ ssp->base + HW_SSP_CTRL1(ssp));
+
+ writel(0x0, ssp->base + HW_SSP_CMD0);
+ writel(0x0, ssp->base + HW_SSP_CMD1);
+
+ return 0;
+}
+
+static void mxs_spi_cleanup(struct spi_device *dev)
+{
+ return;
+}
+
+static int mxs_spi_setup(struct spi_device *dev)
+{
+ int err = 0;
+
+ if (!dev->bits_per_word)
+ dev->bits_per_word = 8;
+
+ if (dev->mode & ~(SPI_CPOL | SPI_CPHA))
+ return -EINVAL;
+
+ err = mxs_spi_setup_transfer(dev, NULL);
+ if (err) {
+ dev_err(&dev->dev,
+ "Failed to setup transfer, error = %d\n", err);
+ }
+
+ return err;
+}
+
+static uint32_t mxs_spi_cs_to_reg(unsigned cs)
+{
+ uint32_t select = 0;
+
+ if (cs & 1)
+ select |= BM_SSP_CTRL0_WAIT_FOR_CMD;
+ if (cs & 2)
+ select |= BM_SSP_CTRL0_WAIT_FOR_IRQ;
+
+ return select;
+}
+
+static void mxs_spi_set_cs(struct mxs_spi *spi, unsigned cs)
+{
+ const uint32_t mask =
+ BM_SSP_CTRL0_WAIT_FOR_CMD | BM_SSP_CTRL0_WAIT_FOR_IRQ;
+ uint32_t select;
+ struct mxs_ssp *ssp = &spi->ssp;
+
+ writel(mask, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+ select = mxs_spi_cs_to_reg(cs);
+ writel(select, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+}
+
+static inline void mxs_spi_enable(struct mxs_spi *spi)
+{
+ struct mxs_ssp *ssp = &spi->ssp;
+
+ writel(BM_SSP_CTRL0_LOCK_CS,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+ writel(BM_SSP_CTRL0_IGNORE_CRC,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+}
+
+static inline void mxs_spi_disable(struct mxs_spi *spi)
+{
+ struct mxs_ssp *ssp = &spi->ssp;
+
+ writel(BM_SSP_CTRL0_LOCK_CS,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+ writel(BM_SSP_CTRL0_IGNORE_CRC,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+}
+
+static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(SSP_TIMEOUT);
+ struct mxs_ssp *ssp = &spi->ssp;
+ uint32_t reg;
+
+ while (1) {
+ reg = readl_relaxed(ssp->base + offset);
+
+ if (set && ((reg & mask) == mask))
+ break;
+
+ if (!set && ((~reg & mask) == mask))
+ break;
+
+ udelay(1);
+
+ if (time_after(jiffies, timeout))
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
+ unsigned char *buf, int len,
+ int *first, int *last, int write)
+{
+ struct mxs_ssp *ssp = &spi->ssp;
+
+ if (*first)
+ mxs_spi_enable(spi);
+
+ mxs_spi_set_cs(spi, cs);
+
+ while (len--) {
+ if (*last && len == 0)
+ mxs_spi_disable(spi);
+
+ if (ssp->devid == IMX23_SSP) {
+ writel(BM_SSP_CTRL0_XFER_COUNT,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+ writel(1,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+ } else {
+ writel(1, ssp->base + HW_SSP_XFER_SIZE);
+ }
+
+ if (write)
+ writel(BM_SSP_CTRL0_READ,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
+ else
+ writel(BM_SSP_CTRL0_READ,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+ writel(BM_SSP_CTRL0_RUN,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+ if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 1))
+ return -ETIMEDOUT;
+
+ if (write)
+ writel(*buf, ssp->base + HW_SSP_DATA);
+
+ writel(BM_SSP_CTRL0_DATA_XFER,
+ ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+ if (!write) {
+ if (mxs_ssp_wait(spi, HW_SSP_STATUS(ssp),
+ BM_SSP_STATUS_FIFO_EMPTY, 0))
+ return -ETIMEDOUT;
+
+ *buf = (readl(ssp->base + HW_SSP_DATA) & 0xff);
+ }
+
+ if (mxs_ssp_wait(spi, HW_SSP_CTRL0, BM_SSP_CTRL0_RUN, 0))
+ return -ETIMEDOUT;
+
+ buf++;
+ }
+
+ if (len <= 0)
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
+static int mxs_spi_transfer_one(struct spi_master *host, struct spi_message *m)
+{
+ struct mxs_spi *spi = spi_master_get_devdata(host);
+ struct mxs_ssp *ssp = &spi->ssp;
+ int first, last;
+ struct spi_transfer *t, *tmp_t;
+ int status = 0;
+ int cs;
+
+ first = last = 0;
+
+ cs = m->spi->chip_select;
+
+ list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) {
+
+ mxs_spi_setup_transfer(m->spi, t);
+
+ if (&t->transfer_list == m->transfers.next)
+ first = 1;
+ if (&t->transfer_list == m->transfers.prev)
+ last = 1;
+ if (t->rx_buf && t->tx_buf) {
+ dev_err(ssp->dev,
+ "Cannot send and receive simultaneously\n");
+ return -EINVAL;
+ }
+
+ if (t->tx_buf)
+ status = mxs_spi_txrx_pio(spi, cs, (void *)t->tx_buf,
+ t->len, &first, &last, 1);
+ if (t->rx_buf)
+ status = mxs_spi_txrx_pio(spi, cs, t->rx_buf,
+ t->len, &first, &last, 0);
+
+ m->actual_length += t->len;
+ if (status)
+ break;
+
+ first = last = 0;
+ }
+
+ m->status = 0;
+ spi_finalize_current_message(host);
+
+ return status;
+}
+
+static const struct of_device_id mxs_spi_dt_ids[] = {
+ { .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
+ { .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_spi_dt_ids);
+
+static int __devinit mxs_spi_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *of_id =
+ of_match_device(mxs_spi_dt_ids, &pdev->dev);
+ struct device_node *np = pdev->dev.of_node;
+ struct spi_master *host;
+ struct mxs_spi *spi;
+ struct mxs_ssp *ssp;
+ struct resource *iores;
+ struct pinctrl *pinctrl;
+ struct clk *clk;
+ void __iomem *base;
+ int devid;
+ int ret = 0;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -EINVAL;
+
+ base = devm_request_and_ioremap(&pdev->dev, iores);
+ if (!base)
+ return -EADDRNOTAVAIL;
+
+ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+ if (IS_ERR(pinctrl))
+ return PTR_ERR(pinctrl);
+
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ if (np)
+ devid = (enum mxs_ssp_id) of_id->data;
+ else
+ devid = pdev->id_entry->driver_data;
+
+ host = spi_alloc_master(&pdev->dev, sizeof(*spi));
+ if (!host)
+ return -ENOMEM;
+
+ host->transfer_one_message = mxs_spi_transfer_one;
+ host->setup = mxs_spi_setup;
+ host->cleanup = mxs_spi_cleanup;
+ host->mode_bits = SPI_CPOL | SPI_CPHA;
+ host->num_chipselect = 3;
+ host->dev.of_node = np;
+ host->flags = SPI_MASTER_HALF_DUPLEX;
+
+ spi = spi_master_get_devdata(host);
+ ssp = &spi->ssp;
+ ssp->dev = &pdev->dev;
+ ssp->clk = clk;
+ ssp->base = base;
+ ssp->devid = devid;
+
+ clk_prepare_enable(ssp->clk);
+ ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
+
+ stmp_reset_block(ssp->base);
+
+ platform_set_drvdata(pdev, host);
+
+ ret = spi_register_master(host);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
+ goto out_host_free;
+ }
+
+ return 0;
+
+out_host_free:
+ clk_disable_unprepare(ssp->clk);
+ spi_master_put(host);
+ kfree(host);
+ return ret;
+}
+
+static int __devexit mxs_spi_remove(struct platform_device *pdev)
+{
+ struct spi_master *host;
+ struct mxs_spi *spi;
+ struct mxs_ssp *ssp;
+
+ host = platform_get_drvdata(pdev);
+ spi = spi_master_get_devdata(host);
+ ssp = &spi->ssp;
+
+ spi_unregister_master(host);
+
+ platform_set_drvdata(pdev, NULL);
+
+ clk_disable_unprepare(ssp->clk);
+
+ spi_master_put(host);
+ kfree(host);
+
+ return 0;
+}
+
+static struct platform_driver mxs_spi_driver = {
+ .probe = mxs_spi_probe,
+ .remove = __devexit_p(mxs_spi_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mxs_spi_dt_ids,
+ },
+};
+
+module_platform_driver(mxs_spi_driver);
+
+MODULE_AUTHOR("Dmitry Pervushin <dimka@embeddedalley.com>");
+MODULE_DESCRIPTION("MXS SPI master driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-spi");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 07/10] mmc: spi: Pull out common DMA parts from MXS MMC
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (5 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 06/10] spi: Add SPI driver for mx233/mx28 Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 08/10] spi: Add DMA support into SPI driver Marek Vasut
` (2 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
These parts will be used by the MXS SPI driver too.
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/mmc/host/mxs-mmc.c | 88 +++++++++++++++++++++----------------------
drivers/spi/spi-mxs.c | 1 -
include/linux/spi/mxs-spi.h | 9 +++++
3 files changed, 51 insertions(+), 47 deletions(-)
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index 3b1c99b..c4be207 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -41,7 +41,6 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include <linux/fsl/mxs-dma.h>
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/mmc/mxs-mmc.h>
@@ -69,13 +68,6 @@ struct mxs_mmc_host {
struct mmc_command *cmd;
struct mmc_data *data;
- int dma_channel;
- struct dma_chan *dmach;
- struct mxs_dma_data dma_data;
- unsigned int dma_dir;
- enum dma_transfer_direction slave_dirn;
- u32 ssp_pio_words[SSP_PIO_NUM];
-
unsigned char bus_width;
spinlock_t lock;
int sdio_irq_en;
@@ -163,7 +155,7 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host)
if (data) {
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, host->dma_dir);
+ data->sg_len, ssp->dma_dir);
/*
* If there was an error on any block, we mark all
* data blocks as being in error.
@@ -232,6 +224,7 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
struct mxs_mmc_host *host, unsigned long flags)
{
+ struct mxs_ssp *ssp = &host->ssp;
struct dma_async_tx_descriptor *desc;
struct mmc_data *data = host->data;
struct scatterlist * sgl;
@@ -240,24 +233,24 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
if (data) {
/* data */
dma_map_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, host->dma_dir);
+ data->sg_len, ssp->dma_dir);
sgl = data->sg;
sg_len = data->sg_len;
} else {
/* pio */
- sgl = (struct scatterlist *) host->ssp_pio_words;
+ sgl = (struct scatterlist *) ssp->ssp_pio_words;
sg_len = SSP_PIO_NUM;
}
- desc = dmaengine_prep_slave_sg(host->dmach,
- sgl, sg_len, host->slave_dirn, flags);
+ desc = dmaengine_prep_slave_sg(ssp->dmach,
+ sgl, sg_len, ssp->slave_dirn, flags);
if (desc) {
desc->callback = mxs_mmc_dma_irq_callback;
desc->callback_param = host;
} else {
if (data)
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
- data->sg_len, host->dma_dir);
+ data->sg_len, ssp->dma_dir);
}
return desc;
@@ -265,6 +258,7 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
static void mxs_mmc_bc(struct mxs_mmc_host *host)
{
+ struct mxs_ssp *ssp = &host->ssp;
struct mmc_command *cmd = host->cmd;
struct dma_async_tx_descriptor *desc;
u32 ctrl0, cmd0, cmd1;
@@ -278,17 +272,17 @@ static void mxs_mmc_bc(struct mxs_mmc_host *host)
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
}
- host->ssp_pio_words[0] = ctrl0;
- host->ssp_pio_words[1] = cmd0;
- host->ssp_pio_words[2] = cmd1;
- host->dma_dir = DMA_NONE;
- host->slave_dirn = DMA_TRANS_NONE;
+ ssp->ssp_pio_words[0] = ctrl0;
+ ssp->ssp_pio_words[1] = cmd0;
+ ssp->ssp_pio_words[2] = cmd1;
+ ssp->dma_dir = DMA_NONE;
+ ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;
dmaengine_submit(desc);
- dma_async_issue_pending(host->dmach);
+ dma_async_issue_pending(ssp->dmach);
return;
out:
@@ -298,6 +292,7 @@ out:
static void mxs_mmc_ac(struct mxs_mmc_host *host)
{
+ struct mxs_ssp *ssp = &host->ssp;
struct mmc_command *cmd = host->cmd;
struct dma_async_tx_descriptor *desc;
u32 ignore_crc, get_resp, long_resp;
@@ -319,17 +314,17 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
}
- host->ssp_pio_words[0] = ctrl0;
- host->ssp_pio_words[1] = cmd0;
- host->ssp_pio_words[2] = cmd1;
- host->dma_dir = DMA_NONE;
- host->slave_dirn = DMA_TRANS_NONE;
+ ssp->ssp_pio_words[0] = ctrl0;
+ ssp->ssp_pio_words[1] = cmd0;
+ ssp->ssp_pio_words[2] = cmd1;
+ ssp->dma_dir = DMA_NONE;
+ ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, DMA_CTRL_ACK);
if (!desc)
goto out;
dmaengine_submit(desc);
- dma_async_issue_pending(host->dmach);
+ dma_async_issue_pending(ssp->dmach);
return;
out:
@@ -441,11 +436,11 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
writel(val, ssp->base + HW_SSP_TIMING(ssp));
/* pio */
- host->ssp_pio_words[0] = ctrl0;
- host->ssp_pio_words[1] = cmd0;
- host->ssp_pio_words[2] = cmd1;
- host->dma_dir = DMA_NONE;
- host->slave_dirn = DMA_TRANS_NONE;
+ ssp->ssp_pio_words[0] = ctrl0;
+ ssp->ssp_pio_words[1] = cmd0;
+ ssp->ssp_pio_words[2] = cmd1;
+ ssp->dma_dir = DMA_NONE;
+ ssp->slave_dirn = DMA_TRANS_NONE;
desc = mxs_mmc_prep_dma(host, 0);
if (!desc)
goto out;
@@ -453,14 +448,14 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
/* append data sg */
WARN_ON(host->data != NULL);
host->data = data;
- host->dma_dir = dma_data_dir;
- host->slave_dirn = slave_dirn;
+ ssp->dma_dir = dma_data_dir;
+ ssp->slave_dirn = slave_dirn;
desc = mxs_mmc_prep_dma(host, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc)
goto out;
dmaengine_submit(desc);
- dma_async_issue_pending(host->dmach);
+ dma_async_issue_pending(ssp->dmach);
return;
out:
dev_warn(mmc_dev(host->mmc),
@@ -557,14 +552,15 @@ static const struct mmc_host_ops mxs_mmc_ops = {
static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
{
struct mxs_mmc_host *host = param;
+ struct mxs_ssp *ssp = &host->ssp;
if (!mxs_dma_is_apbh(chan))
return false;
- if (chan->chan_id != host->dma_channel)
+ if (chan->chan_id != ssp->dma_channel)
return false;
- chan->private = &host->dma_data;
+ chan->private = &ssp->dma_data;
return true;
}
@@ -632,7 +628,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
* to use generic DMA binding later when the helpers get in.
*/
ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
- &host->dma_channel);
+ &ssp->dma_channel);
if (ret) {
dev_err(mmc_dev(host->mmc),
"failed to get dma channel\n");
@@ -640,7 +636,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
}
} else {
ssp->devid = pdev->id_entry->driver_data;
- host->dma_channel = dmares->start;
+ ssp->dma_channel = dmares->start;
}
host->mmc = mmc;
@@ -673,9 +669,9 @@ static int mxs_mmc_probe(struct platform_device *pdev)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- host->dma_data.chan_irq = irq_dma;
- host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
- if (!host->dmach) {
+ ssp->dma_data.chan_irq = irq_dma;
+ ssp->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+ if (!ssp->dmach) {
dev_err(mmc_dev(host->mmc),
"%s: failed to request dma\n", __func__);
goto out_clk_put;
@@ -714,7 +710,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
mmc->max_blk_size = 1 << 0xf;
mmc->max_blk_count = (ssp_is_old(ssp)) ? 0xff : 0xffffff;
mmc->max_req_size = (ssp_is_old(ssp)) ? 0xffff : 0xffffffff;
- mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+ mmc->max_seg_size = dma_get_max_seg_size(ssp->dmach->device->dev);
platform_set_drvdata(pdev, mmc);
@@ -734,8 +730,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
return 0;
out_free_dma:
- if (host->dmach)
- dma_release_channel(host->dmach);
+ if (ssp->dmach)
+ dma_release_channel(ssp->dmach);
out_clk_put:
clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
@@ -754,8 +750,8 @@ static int mxs_mmc_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
- if (host->dmach)
- dma_release_channel(host->dmach);
+ if (ssp->dmach)
+ dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk);
clk_put(ssp->clk);
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index 3c0b1ac..a7d2ebc 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -46,7 +46,6 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include <linux/fsl/mxs-dma.h>
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/spi/spi.h>
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index 2bc8abb..dd79f82 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -24,6 +24,8 @@
#ifndef __LINUX_SPI_MXS_SPI_H__
#define __LINUX_SPI_MXS_SPI_H__
+#include <linux/fsl/mxs-dma.h>
+
#define ssp_is_old(host) ((host)->devid == IMX23_SSP)
/* SSP registers */
@@ -134,6 +136,13 @@ struct mxs_ssp {
struct clk *clk;
unsigned int clk_rate;
enum mxs_ssp_id devid;
+
+ int dma_channel;
+ struct dma_chan *dmach;
+ struct mxs_dma_data dma_data;
+ unsigned int dma_dir;
+ enum dma_transfer_direction slave_dirn;
+ u32 ssp_pio_words[SSP_PIO_NUM];
};
void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 08/10] spi: Add DMA support into SPI driver
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (6 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 07/10] mmc: spi: Pull out common DMA parts from MXS MMC Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 09/10] spi: Add SSP/SPI device tree documentation Marek Vasut
2012-07-16 12:09 ` [PATCH 10/10] ARM: mx28: Add SPI pinmux into imx28.dtsi Marek Vasut
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
drivers/spi/spi-mxs.c | 230 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 215 insertions(+), 15 deletions(-)
diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c
index a7d2ebc..e90200f 100644
--- a/drivers/spi/spi-mxs.c
+++ b/drivers/spi/spi-mxs.c
@@ -55,8 +55,12 @@
#define SSP_TIMEOUT 1000 /* 1000 ms */
+#define SG_NUM 4
+#define SG_MAXLEN 0xff00
+
struct mxs_spi {
struct mxs_ssp ssp;
+ struct completion c;
};
static int mxs_spi_setup_transfer(struct spi_device *dev,
@@ -192,6 +196,115 @@ static int mxs_ssp_wait(struct mxs_spi *spi, int offset, int mask, bool set)
return 0;
}
+static void mxs_ssp_dma_irq_callback(void *param)
+{
+ struct mxs_spi *spi = param;
+ complete(&spi->c);
+}
+
+static irqreturn_t mxs_ssp_irq_handler(int irq, void *dev_id)
+{
+ struct mxs_ssp *ssp = dev_id;
+ dev_err(ssp->dev, "%s[%i] CTRL1=%08x STATUS=%08x\n",
+ __func__, __LINE__,
+ readl(ssp->base + HW_SSP_CTRL1(ssp)),
+ readl(ssp->base + HW_SSP_STATUS(ssp)));
+ return IRQ_HANDLED;
+}
+
+static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
+ unsigned char *buf, int len,
+ int *first, int *last, int write)
+{
+ struct mxs_ssp *ssp = &spi->ssp;
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist sg[SG_NUM];
+ int sg_count;
+ uint32_t pio = BM_SSP_CTRL0_DATA_XFER | mxs_spi_cs_to_reg(cs);
+ int ret;
+
+ if (len > SG_NUM * SG_MAXLEN) {
+ dev_err(ssp->dev, "Data chunk too big for DMA\n");
+ return -EINVAL;
+ }
+
+ init_completion(&spi->c);
+
+ if (*first)
+ pio |= BM_SSP_CTRL0_LOCK_CS;
+ if (*last)
+ pio |= BM_SSP_CTRL0_IGNORE_CRC;
+ if (!write)
+ pio |= BM_SSP_CTRL0_READ;
+
+ if (ssp->devid == IMX23_SSP)
+ pio |= len;
+ else
+ writel(len, ssp->base + HW_SSP_XFER_SIZE);
+
+ /* Queue the PIO register write transfer. */
+ desc = dmaengine_prep_slave_sg(ssp->dmach,
+ (struct scatterlist *)&pio,
+ 1, DMA_TRANS_NONE, 0);
+ if (!desc) {
+ dev_err(ssp->dev,
+ "Failed to get PIO reg. write descriptor.\n");
+ return -EINVAL;
+ }
+
+ /* Queue the DMA data transfer. */
+ sg_init_table(sg, (len / SG_MAXLEN) + 1);
+ sg_count = 0;
+ while (len) {
+ sg_set_buf(&sg[sg_count++], buf, min(len, SG_MAXLEN));
+ len -= min(len, SG_MAXLEN);
+ buf += min(len, SG_MAXLEN);
+ }
+ dma_map_sg(ssp->dev, sg, sg_count,
+ write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+
+ desc = dmaengine_prep_slave_sg(ssp->dmach, sg, sg_count,
+ write ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ if (!desc) {
+ dev_err(ssp->dev,
+ "Failed to get DMA data write descriptor.\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /*
+ * The last descriptor must have this callback,
+ * to finish the DMA transaction.
+ */
+ desc->callback = mxs_ssp_dma_irq_callback;
+ desc->callback_param = spi;
+
+ /* Start the transfer. */
+ dmaengine_submit(desc);
+ dma_async_issue_pending(ssp->dmach);
+
+ ret = wait_for_completion_timeout(&spi->c,
+ msecs_to_jiffies(SSP_TIMEOUT));
+
+ if (!ret) {
+ dev_err(ssp->dev, "DMA transfer timeout\n");
+ ret = -ETIMEDOUT;
+ goto err;
+ }
+
+ ret = 0;
+
+err:
+ for (--sg_count; sg_count >= 0; sg_count--) {
+ dma_unmap_sg(ssp->dev, &sg[sg_count], 1,
+ write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ }
+
+ return ret;
+}
+
static int mxs_spi_txrx_pio(struct mxs_spi *spi, int cs,
unsigned char *buf, int len,
int *first, int *last, int write)
@@ -276,18 +389,48 @@ static int mxs_spi_transfer_one(struct spi_master *host, struct spi_message *m)
first = 1;
if (&t->transfer_list == m->transfers.prev)
last = 1;
- if (t->rx_buf && t->tx_buf) {
+ if ((t->rx_buf && t->tx_buf) || (t->rx_dma && t->tx_dma)) {
dev_err(ssp->dev,
"Cannot send and receive simultaneously\n");
return -EINVAL;
}
- if (t->tx_buf)
- status = mxs_spi_txrx_pio(spi, cs, (void *)t->tx_buf,
- t->len, &first, &last, 1);
- if (t->rx_buf)
- status = mxs_spi_txrx_pio(spi, cs, t->rx_buf,
- t->len, &first, &last, 0);
+ /*
+ * Small blocks can be transfered via PIO.
+ * Measured by empiric means:
+ *
+ * dd if=/dev/mtdblock0 of=/dev/null bs=1024k count=1
+ *
+ * DMA only: 2.164808 seconds, 473.0KB/s
+ * Combined: 1.676276 seconds, 610.9KB/s
+ */
+ if (t->len <= 256) {
+ writel(BM_SSP_CTRL1_DMA_ENABLE,
+ ssp->base + HW_SSP_CTRL1(ssp) +
+ STMP_OFFSET_REG_CLR);
+
+ if (t->tx_buf)
+ status = mxs_spi_txrx_pio(spi, cs,
+ (void *)t->tx_buf,
+ t->len, &first, &last, 1);
+ if (t->rx_buf)
+ status = mxs_spi_txrx_pio(spi, cs,
+ t->rx_buf, t->len,
+ &first, &last, 0);
+ } else {
+ writel(BM_SSP_CTRL1_DMA_ENABLE,
+ ssp->base + HW_SSP_CTRL1(ssp) +
+ STMP_OFFSET_REG_SET);
+
+ if (t->tx_buf)
+ status = mxs_spi_txrx_dma(spi, cs,
+ (void *)t->tx_buf, t->len,
+ &first, &last, 1);
+ if (t->rx_buf)
+ status = mxs_spi_txrx_dma(spi, cs,
+ t->rx_buf, t->len,
+ &first, &last, 0);
+ }
m->actual_length += t->len;
if (status)
@@ -302,6 +445,21 @@ static int mxs_spi_transfer_one(struct spi_master *host, struct spi_message *m)
return status;
}
+static bool mxs_ssp_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct mxs_ssp *ssp = param;
+
+ if (!mxs_dma_is_apbh(chan))
+ return false;
+
+ if (chan->chan_id != ssp->dma_channel)
+ return false;
+
+ chan->private = &ssp->dma_data;
+
+ return true;
+}
+
static const struct of_device_id mxs_spi_dt_ids[] = {
{ .compatible = "fsl,imx23-spi", .data = (void *) IMX23_SSP, },
{ .compatible = "fsl,imx28-spi", .data = (void *) IMX28_SSP, },
@@ -317,15 +475,18 @@ static int __devinit mxs_spi_probe(struct platform_device *pdev)
struct spi_master *host;
struct mxs_spi *spi;
struct mxs_ssp *ssp;
- struct resource *iores;
+ struct resource *iores, *dmares;
struct pinctrl *pinctrl;
struct clk *clk;
void __iomem *base;
- int devid;
- int ret = 0;
+ int devid, dma_channel;
+ int ret = 0, irq_err, irq_dma;
+ dma_cap_mask_t mask;
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores)
+ irq_err = platform_get_irq(pdev, 0);
+ irq_dma = platform_get_irq(pdev, 1);
+ if (!iores || irq_err < 0 || irq_dma < 0)
return -EINVAL;
base = devm_request_and_ioremap(&pdev->dev, iores);
@@ -340,10 +501,26 @@ static int __devinit mxs_spi_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
- if (np)
+ if (np) {
devid = (enum mxs_ssp_id) of_id->data;
- else
+ /*
+ * TODO: This is a temporary solution and should be changed
+ * to use generic DMA binding later when the helpers get in.
+ */
+ ret = of_property_read_u32(np, "fsl,ssp-dma-channel",
+ &dma_channel);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to get DMA channel\n");
+ return -EINVAL;
+ }
+ } else {
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares)
+ return -EINVAL;
devid = pdev->id_entry->driver_data;
+ dma_channel = dmares->start;
+ }
host = spi_alloc_master(&pdev->dev, sizeof(*spi));
if (!host)
@@ -363,8 +540,28 @@ static int __devinit mxs_spi_probe(struct platform_device *pdev)
ssp->clk = clk;
ssp->base = base;
ssp->devid = devid;
+ ssp->dma_channel = dma_channel;
+
+ ret = devm_request_irq(&pdev->dev, irq_err, mxs_ssp_irq_handler, 0,
+ DRIVER_NAME, ssp);
+ if (ret)
+ goto out_host_free;
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ ssp->dma_data.chan_irq = irq_dma;
+ ssp->dmach = dma_request_channel(mask, mxs_ssp_dma_filter, ssp);
+ if (!ssp->dmach) {
+ dev_err(ssp->dev, "Failed to request DMA\n");
+ goto out_host_free;
+ }
+
+ /*
+ * Crank up the clock to 120MHz, this will be further divided onto a
+ * proper speed.
+ */
clk_prepare_enable(ssp->clk);
+ clk_set_rate(ssp->clk, 120 * 1000 * 1000);
ssp->clk_rate = clk_get_rate(ssp->clk) / 1000;
stmp_reset_block(ssp->base);
@@ -374,15 +571,18 @@ static int __devinit mxs_spi_probe(struct platform_device *pdev)
ret = spi_register_master(host);
if (ret) {
dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret);
- goto out_host_free;
+ goto out_free_dma;
}
return 0;
-out_host_free:
+out_free_dma:
+ dma_release_channel(ssp->dmach);
clk_disable_unprepare(ssp->clk);
+out_host_free:
spi_master_put(host);
kfree(host);
+
return ret;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 09/10] spi: Add SSP/SPI device tree documentation
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (7 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 08/10] spi: Add DMA support into SPI driver Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 10/10] ARM: mx28: Add SPI pinmux into imx28.dtsi Marek Vasut
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
Documentation/devicetree/bindings/spi/mxs-spi.txt | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/mxs-spi.txt
diff --git a/Documentation/devicetree/bindings/spi/mxs-spi.txt b/Documentation/devicetree/bindings/spi/mxs-spi.txt
new file mode 100644
index 0000000..f1263a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/mxs-spi.txt
@@ -0,0 +1,18 @@
+* Freescale MX233/MX28 SSP/SPI
+
+Required properties:
+- compatible: Should be "fsl,<soc>-spi", where soc is "imx23" or "imx28"
+- reg: Offset and length of the register set for the device
+- interrupts: Should contain SSP interrupts (error irq first, dma irq second)
+- fsl,ssp-dma-channel: APBX DMA channel for the SSP
+
+Example:
+
+ssp0: ssp at 80010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx28-spi";
+ reg = <0x80010000 2000>;
+ interrupts = <96 82>;
+ fsl,ssp-dma-channel = <0>;
+};
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 10/10] ARM: mx28: Add SPI pinmux into imx28.dtsi
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
` (8 preceding siblings ...)
2012-07-16 12:09 ` [PATCH 09/10] spi: Add SSP/SPI device tree documentation Marek Vasut
@ 2012-07-16 12:09 ` Marek Vasut
9 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-16 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Chris Ball <cjb@laptop.org>
Cc: Detlev Zundel <dzu@denx.de>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Rob Herring <rob.herring@calxeda.com>
CC: Shawn Guo <shawn.guo@linaro.org>
Cc: Stefano Babic <sbabic@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
---
arch/arm/boot/dts/imx28.dtsi | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index badc76a..4a0f12c 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -507,6 +507,45 @@
fsl,voltage = <1>;
fsl,pull-up = <0>;
};
+
+ spi0_pins_a: spi0 at 0 {
+ reg = <0>;
+ fsl,pinmux-ids =
+ <0x2000 0x2010 0x2020 0x2030
+ 0x2040 0x2050 0x2060 0x2070
+ 0x2080 0x2090 0x20a0>;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
+
+ spi1_pins_a: spi1 at 0 {
+ reg = <0>;
+ fsl,pinmux-ids =
+ <0x20c0 0x20d0 0x20e0 0x20f0>;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
+
+ spi2_pins_a: spi2 at 0 {
+ reg = <0>;
+ fsl,pinmux-ids =
+ <0x2100 0x2110 0x2120
+ 0x2130 0x2140 0x2150>;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
+
+ spi3_pins_a: spi3 at 0 {
+ reg = <0>;
+ fsl,pinmux-ids =
+ <0x2180 0x2190 0x21a0 0x21b0>;
+ fsl,drive-strength = <1>;
+ fsl,voltage = <1>;
+ fsl,pull-up = <1>;
+ };
};
digctl at 8001c000 {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function
2012-07-16 12:09 ` [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function Marek Vasut
@ 2012-07-17 13:39 ` Attila Kinali
2012-07-17 21:48 ` Marek Vasut
0 siblings, 1 reply; 15+ messages in thread
From: Attila Kinali @ 2012-07-17 13:39 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 16 Jul 2012 14:09:52 +0200
Marek Vasut <marex@denx.de> wrote:
> Pull out the MMC clock configuration function and make it
> into SSP clock configuration function, so it can be used by
> the SPI driver too.
> diff --git a/drivers/clk/mxs/clk-ssp.c b/drivers/clk/mxs/clk-ssp.c
> new file mode 100644
> index 0000000..b3c1e16
> --- /dev/null
> +++ b/drivers/clk/mxs/clk-ssp.c
> @@ -0,0 +1,61 @@
> +/*
> + * Copyright 2012 DENX Software Engineering, GmbH
> + *
> + * Pulled from code:
> + * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
> + * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
> + *
> + * Copyright 2008 Embedded Alley Solutions, Inc.
> + * Copyright 2009-2011 Freescale Semiconductor, Inc.
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/spi/mxs-spi.h>
> +
> +void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate)
> +{
> + unsigned int ssp_clk, ssp_sck;
> + u32 clock_divide, clock_rate;
> + u32 val;
> +
> + ssp_clk = clk_get_rate(ssp->clk);
> +
> + for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
> + clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
> + clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
> + if (clock_rate <= 255)
> + break;
> + }
> +
> + if (clock_divide > 254) {
> + dev_err(ssp->dev,
> + "%s: cannot set clock to %d\n", __func__, rate);
> + return;
> + }
> +
> + ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
> +
> + val = readl(ssp->base + HW_SSP_TIMING(ssp));
> + val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
> + val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
> + val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
> + writel(val, ssp->base + HW_SSP_TIMING(ssp));
> +
> + ssp->clk_rate = ssp_sck;
> +
> + dev_dbg(ssp->dev,
> + "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
> + __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
> +}
There is a EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate); missing here.
Attila Kinali
--
The trouble with you, Shev, is you don't say anything until you've saved
up a whole truckload of damned heavy brick arguments and then you dump
them all out and never look at the bleeding body mangled beneath the heap
-- Tirin, The Dispossessed, U. Le Guin
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function
2012-07-17 13:39 ` Attila Kinali
@ 2012-07-17 21:48 ` Marek Vasut
2012-07-18 6:07 ` Attila Kinali
0 siblings, 1 reply; 15+ messages in thread
From: Marek Vasut @ 2012-07-17 21:48 UTC (permalink / raw)
To: linux-arm-kernel
Dear Attila Kinali,
> On Mon, 16 Jul 2012 14:09:52 +0200
>
> Marek Vasut <marex@denx.de> wrote:
> > Pull out the MMC clock configuration function and make it
> > into SSP clock configuration function, so it can be used by
> > the SPI driver too.
> >
> > diff --git a/drivers/clk/mxs/clk-ssp.c b/drivers/clk/mxs/clk-ssp.c
> > new file mode 100644
> > index 0000000..b3c1e16
> > --- /dev/null
> > +++ b/drivers/clk/mxs/clk-ssp.c
> > @@ -0,0 +1,61 @@
> > +/*
> > + * Copyright 2012 DENX Software Engineering, GmbH
> > + *
> > + * Pulled from code:
> > + * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
> > + * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC
> > driver + *
> > + * Copyright 2008 Embedded Alley Solutions, Inc.
> > + * Copyright 2009-2011 Freescale Semiconductor, Inc.
> > + *
> > + * The code contained herein is licensed under the GNU General Public
> > + * License. You may obtain a copy of the GNU General Public License
> > + * Version 2 or later at the following locations:
> > + *
> > + * http://www.opensource.org/licenses/gpl-license.html
> > + * http://www.gnu.org/copyleft/gpl.html
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/init.h>
> > +#include <linux/clk.h>
> > +#include <linux/module.h>
> > +#include <linux/device.h>
> > +#include <linux/io.h>
> > +#include <linux/spi/mxs-spi.h>
> > +
> > +void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate)
> > +{
> > + unsigned int ssp_clk, ssp_sck;
> > + u32 clock_divide, clock_rate;
> > + u32 val;
> > +
> > + ssp_clk = clk_get_rate(ssp->clk);
> > +
> > + for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
> > + clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
> > + clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
> > + if (clock_rate <= 255)
> > + break;
> > + }
> > +
> > + if (clock_divide > 254) {
> > + dev_err(ssp->dev,
> > + "%s: cannot set clock to %d\n", __func__, rate);
> > + return;
> > + }
> > +
> > + ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
> > +
> > + val = readl(ssp->base + HW_SSP_TIMING(ssp));
> > + val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
> > + val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
> > + val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
> > + writel(val, ssp->base + HW_SSP_TIMING(ssp));
> > +
> > + ssp->clk_rate = ssp_sck;
> > +
> > + dev_dbg(ssp->dev,
> > + "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d,
> > rate_requested %d\n", + __func__, clock_divide, clock_rate,
ssp_clk,
> > ssp_sck, rate);
> > +}
>
> There is a EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate); missing here.
What for?
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function
2012-07-17 21:48 ` Marek Vasut
@ 2012-07-18 6:07 ` Attila Kinali
2012-07-18 8:40 ` Marek Vasut
0 siblings, 1 reply; 15+ messages in thread
From: Attila Kinali @ 2012-07-18 6:07 UTC (permalink / raw)
To: linux-arm-kernel
Good morning Marek,
On Tue, 17 Jul 2012 23:48:34 +0200
Marek Vasut <marex@denx.de> wrote:
> > There is a EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate); missing here.
>
> What for?
To be able to compile mxs-mmc as a module
Attila Kinali
--
Why does it take years to find the answers to
the questions one should have asked long ago?
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function
2012-07-18 6:07 ` Attila Kinali
@ 2012-07-18 8:40 ` Marek Vasut
0 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-07-18 8:40 UTC (permalink / raw)
To: linux-arm-kernel
Dear Attila Kinali,
> Good morning Marek,
>
> On Tue, 17 Jul 2012 23:48:34 +0200
>
> Marek Vasut <marex@denx.de> wrote:
> > > There is a EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate); missing here.
> >
> > What for?
>
> To be able to compile mxs-mmc as a module
Argh, good point.
> Attila Kinali
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file
2012-08-03 15:26 [PATCH 00/10 V3] MXS SPI driver Marek Vasut
@ 2012-08-03 15:26 ` Marek Vasut
0 siblings, 0 replies; 15+ messages in thread
From: Marek Vasut @ 2012-08-03 15:26 UTC (permalink / raw)
To: linux-arm-kernel
Move the definitions into separate file so separate SPI driver can be
implemented. The SSP controller in MXS can act both as a MMC host and
as a SPI host.
Based on previous attempt by:
Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Attila Kinali <attila@kinali.ch>
Cc: Chris Ball <cjb@laptop.org>
CC: Dong Aisheng <b29396@freescale.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linux ARM kernel <linux-arm-kernel@lists.infradead.org>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
CC: Shawn Guo <shawn.guo@linaro.org>
---
drivers/mmc/host/mxs-mmc.c | 87 ++--------------------------------
include/linux/spi/mxs-spi.h | 109 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 84 deletions(-)
create mode 100644 include/linux/spi/mxs-spi.h
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index a51f930..26c95dc 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -45,87 +45,10 @@
#include <linux/pinctrl/consumer.h>
#include <linux/stmp_device.h>
#include <linux/mmc/mxs-mmc.h>
+#include <linux/spi/mxs-spi.h>
#define DRIVER_NAME "mxs-mmc"
-/* card detect polling timeout */
-#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
-
-#define ssp_is_old(host) ((host)->devid == IMX23_MMC)
-
-/* SSP registers */
-#define HW_SSP_CTRL0 0x000
-#define BM_SSP_CTRL0_RUN (1 << 29)
-#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28)
-#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26)
-#define BM_SSP_CTRL0_READ (1 << 25)
-#define BM_SSP_CTRL0_DATA_XFER (1 << 24)
-#define BP_SSP_CTRL0_BUS_WIDTH (22)
-#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22)
-#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
-#define BM_SSP_CTRL0_LONG_RESP (1 << 19)
-#define BM_SSP_CTRL0_GET_RESP (1 << 17)
-#define BM_SSP_CTRL0_ENABLE (1 << 16)
-#define BP_SSP_CTRL0_XFER_COUNT (0)
-#define BM_SSP_CTRL0_XFER_COUNT (0xffff)
-#define HW_SSP_CMD0 0x010
-#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25)
-#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22)
-#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21)
-#define BM_SSP_CMD0_APPEND_8CYC (1 << 20)
-#define BP_SSP_CMD0_BLOCK_SIZE (16)
-#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16)
-#define BP_SSP_CMD0_BLOCK_COUNT (8)
-#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8)
-#define BP_SSP_CMD0_CMD (0)
-#define BM_SSP_CMD0_CMD (0xff)
-#define HW_SSP_CMD1 0x020
-#define HW_SSP_XFER_SIZE 0x030
-#define HW_SSP_BLOCK_SIZE 0x040
-#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT (4)
-#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4)
-#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0)
-#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf)
-#define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070)
-#define BP_SSP_TIMING_TIMEOUT (16)
-#define BM_SSP_TIMING_TIMEOUT (0xffff << 16)
-#define BP_SSP_TIMING_CLOCK_DIVIDE (8)
-#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8)
-#define BP_SSP_TIMING_CLOCK_RATE (0)
-#define BM_SSP_TIMING_CLOCK_RATE (0xff)
-#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080)
-#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31)
-#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30)
-#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29)
-#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28)
-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27)
-#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26)
-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25)
-#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24)
-#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23)
-#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22)
-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21)
-#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20)
-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17)
-#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16)
-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15)
-#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14)
-#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13)
-#define BM_SSP_CTRL1_POLARITY (1 << 9)
-#define BP_SSP_CTRL1_WORD_LENGTH (4)
-#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4)
-#define BP_SSP_CTRL1_SSP_MODE (0)
-#define BM_SSP_CTRL1_SSP_MODE (0xf)
-#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0)
-#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0)
-#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0)
-#define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0)
-#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100)
-#define BM_SSP_STATUS_CARD_DETECT (1 << 28)
-#define BM_SSP_STATUS_SDIO_IRQ (1 << 17)
-
-#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field)
-
#define MXS_MMC_IRQ_BITS (BM_SSP_CTRL1_SDIO_IRQ | \
BM_SSP_CTRL1_RESP_ERR_IRQ | \
BM_SSP_CTRL1_RESP_TIMEOUT_IRQ | \
@@ -135,12 +58,8 @@
BM_SSP_CTRL1_RECV_TIMEOUT_IRQ | \
BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
-#define SSP_PIO_NUM 3
-
-enum mxs_mmc_id {
- IMX23_MMC,
- IMX28_MMC,
-};
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT (HZ/2)
struct mxs_mmc_host {
struct mmc_host *mmc;
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
new file mode 100644
index 0000000..b7ccd57
--- /dev/null
+++ b/include/linux/spi/mxs-spi.h
@@ -0,0 +1,109 @@
+/*
+ * include/linux/spi/mxs-spi.h
+ *
+ * Freescale i.MX233/i.MX28 SPI controller register definition
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __LINUX_SPI_MXS_SPI_H__
+#define __LINUX_SPI_MXS_SPI_H__
+
+#define ssp_is_old(host) ((host)->devid == IMX23_MMC)
+
+/* SSP registers */
+#define HW_SSP_CTRL0 0x000
+#define BM_SSP_CTRL0_RUN (1 << 29)
+#define BM_SSP_CTRL0_SDIO_IRQ_CHECK (1 << 28)
+#define BM_SSP_CTRL0_IGNORE_CRC (1 << 26)
+#define BM_SSP_CTRL0_READ (1 << 25)
+#define BM_SSP_CTRL0_DATA_XFER (1 << 24)
+#define BP_SSP_CTRL0_BUS_WIDTH 22
+#define BM_SSP_CTRL0_BUS_WIDTH (0x3 << 22)
+#define BM_SSP_CTRL0_WAIT_FOR_IRQ (1 << 21)
+#define BM_SSP_CTRL0_LONG_RESP (1 << 19)
+#define BM_SSP_CTRL0_GET_RESP (1 << 17)
+#define BM_SSP_CTRL0_ENABLE (1 << 16)
+#define BP_SSP_CTRL0_XFER_COUNT 0
+#define BM_SSP_CTRL0_XFER_COUNT 0xffff
+#define HW_SSP_CMD0 0x010
+#define BM_SSP_CMD0_DBL_DATA_RATE_EN (1 << 25)
+#define BM_SSP_CMD0_SLOW_CLKING_EN (1 << 22)
+#define BM_SSP_CMD0_CONT_CLKING_EN (1 << 21)
+#define BM_SSP_CMD0_APPEND_8CYC (1 << 20)
+#define BP_SSP_CMD0_BLOCK_SIZE 16
+#define BM_SSP_CMD0_BLOCK_SIZE (0xf << 16)
+#define BP_SSP_CMD0_BLOCK_COUNT 8
+#define BM_SSP_CMD0_BLOCK_COUNT (0xff << 8)
+#define BP_SSP_CMD0_CMD 0
+#define BM_SSP_CMD0_CMD 0xff
+#define HW_SSP_CMD1 0x020
+#define HW_SSP_XFER_SIZE 0x030
+#define HW_SSP_BLOCK_SIZE 0x040
+#define BP_SSP_BLOCK_SIZE_BLOCK_COUNT 4
+#define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4)
+#define BP_SSP_BLOCK_SIZE_BLOCK_SIZE 0
+#define BM_SSP_BLOCK_SIZE_BLOCK_SIZE 0xf
+#define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070)
+#define BP_SSP_TIMING_TIMEOUT 16
+#define BM_SSP_TIMING_TIMEOUT (0xffff << 16)
+#define BP_SSP_TIMING_CLOCK_DIVIDE 8
+#define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8)
+#define BP_SSP_TIMING_CLOCK_RATE 0
+#define BM_SSP_TIMING_CLOCK_RATE 0xff
+#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080)
+#define BM_SSP_CTRL1_SDIO_IRQ (1 << 31)
+#define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30)
+#define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29)
+#define BM_SSP_CTRL1_RESP_ERR_IRQ_EN (1 << 28)
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ (1 << 27)
+#define BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN (1 << 26)
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ (1 << 25)
+#define BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN (1 << 24)
+#define BM_SSP_CTRL1_DATA_CRC_IRQ (1 << 23)
+#define BM_SSP_CTRL1_DATA_CRC_IRQ_EN (1 << 22)
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ (1 << 21)
+#define BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN (1 << 20)
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ (1 << 17)
+#define BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN (1 << 16)
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ (1 << 15)
+#define BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN (1 << 14)
+#define BM_SSP_CTRL1_DMA_ENABLE (1 << 13)
+#define BM_SSP_CTRL1_POLARITY (1 << 9)
+#define BP_SSP_CTRL1_WORD_LENGTH 4
+#define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4)
+#define BP_SSP_CTRL1_SSP_MODE 0
+#define BM_SSP_CTRL1_SSP_MODE 0xf
+#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100)
+#define BM_SSP_STATUS_CARD_DETECT (1 << 28)
+#define BM_SSP_STATUS_SDIO_IRQ (1 << 17)
+
+#define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define SSP_PIO_NUM 3
+
+enum mxs_mmc_id {
+ IMX23_MMC,
+ IMX28_MMC,
+};
+
+#endif /* __LINUX_SPI_MXS_SPI_H__ */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 15+ messages in thread
end of thread, other threads:[~2012-08-03 15:26 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1342440597-8395-1-git-send-email-marex@denx.de>
2012-07-16 12:09 ` [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file Marek Vasut
2012-07-16 12:09 ` [PATCH 02/10] mmc: spi: Rename IMX2[38]_MMC to IMX2[38]_SSP Marek Vasut
2012-07-16 12:09 ` [PATCH 03/10] mmc: spi: Add necessary bits into mxs-spi.h Marek Vasut
2012-07-16 12:09 ` [PATCH 04/10] mmc: spi: Pull out parts shared between MMC and SPI Marek Vasut
2012-07-16 12:09 ` [PATCH 05/10] mmc: spi: Pull out the SSP clock configuration function Marek Vasut
2012-07-17 13:39 ` Attila Kinali
2012-07-17 21:48 ` Marek Vasut
2012-07-18 6:07 ` Attila Kinali
2012-07-18 8:40 ` Marek Vasut
2012-07-16 12:09 ` [PATCH 06/10] spi: Add SPI driver for mx233/mx28 Marek Vasut
2012-07-16 12:09 ` [PATCH 07/10] mmc: spi: Pull out common DMA parts from MXS MMC Marek Vasut
2012-07-16 12:09 ` [PATCH 08/10] spi: Add DMA support into SPI driver Marek Vasut
2012-07-16 12:09 ` [PATCH 09/10] spi: Add SSP/SPI device tree documentation Marek Vasut
2012-07-16 12:09 ` [PATCH 10/10] ARM: mx28: Add SPI pinmux into imx28.dtsi Marek Vasut
2012-08-03 15:26 [PATCH 00/10 V3] MXS SPI driver Marek Vasut
2012-08-03 15:26 ` [PATCH 01/10] mmc: spi: Move SSP register definitions into separate file Marek Vasut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).