From c321c217836fb08e31b026035a71b8ddad513a52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=B6rg=20Krause?= <joerg.krause@embedded.rocks>
Date: Tue, 1 Nov 2016 18:02:46 +0100
Subject: [PATCH] mmc: mxs-mmc: use PIO mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Jörg Krause <joerg.krause@embedded.rocks>
---
 drivers/mmc/host/mxs-mmc.c  | 365 ++++++++++++++++++++++++++++++++++----------
 include/linux/spi/mxs-spi.h |  12 ++
 2 files changed, 300 insertions(+), 77 deletions(-)

diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index d839147..958c073 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -47,14 +47,22 @@
 
 #define DRIVER_NAME	"mxs-mmc"
 
-#define MXS_MMC_IRQ_BITS	(BM_SSP_CTRL1_SDIO_IRQ		| \
-				 BM_SSP_CTRL1_RESP_ERR_IRQ	| \
-				 BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
-				 BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	| \
-				 BM_SSP_CTRL1_DATA_CRC_IRQ	| \
-				 BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	| \
-				 BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
-				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+#define MXS_MMC_ERR_IRQ_BITS  (BM_SSP_CTRL1_RESP_ERR_IRQ	| \
+				BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
+				BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	| \
+				BM_SSP_CTRL1_DATA_CRC_IRQ	| \
+				BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	| \
+				BM_SSP_CTRL1_RECV_TIMEOUT_IRQ   | \
+				BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+
+#define MXS_MMC_IRQ_BITS  (BM_SSP_CTRL1_SDIO_IRQ		| \
+				MXS_MMC_ERR_IRQ_BITS)
+
+#define MXS_MMC_ERR_BITS (BM_SSP_CTRL1_RESP_ERR_IRQ       	| \
+				BM_SSP_CTRL1_RESP_TIMEOUT_IRQ   | \
+				BM_SSP_CTRL1_DATA_TIMEOUT_IRQ   | \
+				BM_SSP_CTRL1_DATA_CRC_IRQ       | \
+				BM_SSP_CTRL1_RECV_TIMEOUT_IRQ)
 
 /* card detect polling timeout */
 #define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
@@ -71,6 +79,10 @@ struct mxs_mmc_host {
 	spinlock_t			lock;
 	int				sdio_irq_en;
 	bool				broken_cd;
+
+	u32				status;
+	int				pio_size;
+	struct completion		dma_done;
 };
 
 static int mxs_mmc_get_cd(struct mmc_host *mmc)
@@ -256,38 +268,81 @@ static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
 	return desc;
 }
 
+/*
+ * Check for MMC command errors
+ * Returns error code or zero if no errors
+ */
+static inline int mxs_mmc_cmd_error(u32 status)
+{
+	int err = 0;
+
+	if (status & BM_SSP_STATUS_TIMEOUT)
+		err = -ETIMEDOUT;
+	else if (status & BM_SSP_STATUS_RESP_TIMEOUT)
+		err = -ETIMEDOUT;
+	else if (status & BM_SSP_STATUS_RESP_CRC_ERR)
+		err = -EILSEQ;
+	else if (status & BM_SSP_STATUS_RESP_ERR)
+		err = -EIO;
+
+	return err;
+}
+
 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;
+	u32 ctrl0, ctrl1, cmd0, cmd1, c1;
 
 	ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC;
+	ctrl1 = BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
 	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC;
-	cmd1 = cmd->arg;
+	cmd1 = BF_SSP(cmd->arg, CMD1_CMD);
 
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
 	}
 
-	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(ssp->dmach);
-	return;
-
-out:
-	dev_warn(mmc_dev(host->mmc),
-		 "%s: failed to prep dma\n", __func__);
+	/* following IO operations */
+	writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+	writel(cmd0, ssp->base + HW_SSP_CMD0);
+	writel(cmd1, ssp->base + HW_SSP_CMD1);
+
+	/* clear these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+	init_completion(&host->dma_done);
+	writel(BM_SSP_CTRL0_RUN,
+	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+	/* wait here as long as SSP is running and busy */
+	while (readl(ssp->base + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN)
+		continue;
+	while (readl(ssp->base + HW_SSP_STATUS(ssp)) & BM_SSP_STATUS_BUSY)
+		continue;
+
+	host->status = readl(ssp->base + HW_SSP_STATUS(ssp));
+	c1 = readl(ssp->base + HW_SSP_CTRL1(ssp));
+
+	/* reset interrupt request status bits */
+	writel(c1 & MXS_MMC_ERR_IRQ_BITS,
+	       ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+
+	/* reenable these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
+	/* end IO operations */
+
+	cmd->error = mxs_mmc_cmd_error(host->status);
+
+	if (cmd->error) {
+		dev_warn(mmc_dev(host->mmc), "BC command error %d\n", cmd->error);
+	}
 }
 
 static void mxs_mmc_ac(struct mxs_mmc_host *host)
@@ -296,7 +351,7 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
 	struct mmc_command *cmd = host->cmd;
 	struct dma_async_tx_descriptor *desc;
 	u32 ignore_crc, get_resp, long_resp;
-	u32 ctrl0, cmd0, cmd1;
+	u32 ctrl0, ctrl1, cmd0, cmd1, c1;
 
 	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
 			0 : BM_SSP_CTRL0_IGNORE_CRC;
@@ -306,30 +361,76 @@ static void mxs_mmc_ac(struct mxs_mmc_host *host)
 			BM_SSP_CTRL0_LONG_RESP : 0;
 
 	ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
+	ctrl1 = BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
 	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
-	cmd1 = cmd->arg;
+	cmd1 = BF_SSP(cmd->arg, CMD1_CMD);
 
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
 	}
 
-	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(ssp->dmach);
-	return;
-
-out:
-	dev_warn(mmc_dev(host->mmc),
-		 "%s: failed to prep dma\n", __func__);
+	/* following IO operations */
+	writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+	writel(cmd0, ssp->base + HW_SSP_CMD0);
+	writel(cmd1, ssp->base + HW_SSP_CMD1);
+
+	/* clear these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+	init_completion(&host->dma_done);
+	writel(BM_SSP_CTRL0_RUN,
+	       ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+	/* wait here as long as SSP is running and busy */
+	while (readl(ssp->base + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN)
+		continue;
+	while (readl(ssp->base + HW_SSP_STATUS(ssp)) & BM_SSP_STATUS_BUSY)
+		continue;
+
+	host->status = readl(ssp->base + HW_SSP_STATUS(ssp));
+	c1 = readl(ssp->base + HW_SSP_CTRL1(ssp));
+
+	/* reset interrupt request status bits */
+	writel(c1 & MXS_MMC_ERR_IRQ_BITS,
+	       ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+
+	/* reenable these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
+	/* end IO operations */
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		while (readl(ssp->base + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN)
+			continue;
+		break;
+	case MMC_RSP_R1:
+	case MMC_RSP_R1B:
+	case MMC_RSP_R3:
+		cmd->resp[0] = readl(ssp->base + HW_SSP_SDRESP0(ssp));
+		break;
+	case MMC_RSP_R2:
+		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));
+		break;
+	default:
+		dev_warn(mmc_dev(host->mmc), "Unsupported response type 0x%x\n",
+			 mmc_resp_type(cmd));
+		BUG();
+		break;
+	}
+
+	cmd->error = mxs_mmc_cmd_error(host->status);
+
+	if (cmd->error) {
+		dev_warn(mmc_dev(host->mmc), "AC command error %d\n", cmd->error);
+	}
 }
 
 static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns)
@@ -357,6 +458,15 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 	unsigned int sg_len = data->sg_len;
 	unsigned int i;
 
+	int is_reading = 0;
+	int index = 0;
+	int len;
+	struct scatterlist *_sg;
+	int size;
+	char *sgbuf;
+	u8 *p;
+	u32 _data, status;
+
 	unsigned short dma_data_dir, timeout;
 	enum dma_transfer_direction slave_dirn;
 	unsigned int data_size = 0, log2_blksz;
@@ -365,7 +475,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 	struct mxs_ssp *ssp = &host->ssp;
 
 	u32 ignore_crc, get_resp, long_resp, read;
-	u32 ctrl0, cmd0, cmd1, val;
+	u32 ctrl0, ctrl1, cmd0, cmd1, val, c1;
 
 	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
 			0 : BM_SSP_CTRL0_IGNORE_CRC;
@@ -378,10 +488,12 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 		dma_data_dir = DMA_TO_DEVICE;
 		slave_dirn = DMA_MEM_TO_DEV;
 		read = 0;
+		is_reading = 0;
 	} else {
 		dma_data_dir = DMA_FROM_DEVICE;
 		slave_dirn = DMA_DEV_TO_MEM;
 		read = BM_SSP_CTRL0_READ;
+		is_reading = 1;
 	}
 
 	ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
@@ -428,38 +540,129 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host)
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
 	}
 
-	/* set the timeout count */
-	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, ssp->base + HW_SSP_TIMING(ssp));
-
-	/* pio */
-	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;
-
-	/* append data sg */
-	WARN_ON(host->data != NULL);
-	host->data = data;
-	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(ssp->dmach);
-	return;
-out:
-	dev_warn(mmc_dev(host->mmc),
-		 "%s: failed to prep dma\n", __func__);
+	data_size = cmd->data->blksz * cmd->data->blocks;
+	u32 transfer_size = data_size;
+
+	_sg = host->cmd->data->sg;
+	len = host->cmd->data->sg_len;
+
+	ctrl1 =	BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
+
+	writel(ctrl0, ssp->base + HW_SSP_CTRL0);
+	writel(cmd0, ssp->base + HW_SSP_CMD0);
+	writel(cmd1, ssp->base + HW_SSP_CMD1);
+	/* clear these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+	init_completion(&host->dma_done);
+	writel(BM_SSP_CTRL0_RUN, ssp->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
+
+	while (readl(ssp->base + HW_SSP_CTRL0) & BM_SSP_STATUS_CMD_BUSY)
+		continue;
+
+	while (transfer_size) {
+		sgbuf = kmap_atomic(sg_page(&_sg[index])) + _sg[index].offset;
+
+		p = (u8 *)sgbuf;
+		size = transfer_size < _sg[index].length ? transfer_size : _sg[index].length;
+
+		if (is_reading) {
+			while (size) {
+				status = readl(ssp->base + HW_SSP_STATUS(ssp));
+				if (status & BM_SSP_STATUS_FIFO_EMPTY)
+					continue;
+				_data = readl(ssp->base + HW_SSP_DATA(ssp));
+				if ((u32)p & 0x3) {
+					*p++ = _data & 0xff;
+					*p++ = (_data >> 8) & 0xff;
+					*p++ = (_data >> 16) & 0xff;
+					*p++ = (_data >> 24) & 0xff;
+				} else {
+					*(u32 *)p = _data;
+					p += 4;
+				}
+				transfer_size -= 4;
+				size -= 4;
+			}
+		} else {
+			while (size) {
+				status = readl(ssp->base + HW_SSP_STATUS(ssp));
+				if (status & BM_SSP_STATUS_FIFO_FULL)
+					continue;
+				if ((u32)p & 0x3)
+					_data = p[0] | \
+						(p[1] << 8) | \
+						(p[2] << 16) | \
+						(p[3] << 24);
+				else
+					_data = *(u32 *)p;
+
+				writel(_data, ssp->base + HW_SSP_DATA(ssp));
+				transfer_size -= 4;
+				size -= 4;
+				p += 4;
+			}
+		}
+		kunmap_atomic(sgbuf);
+		index++;
+	}
+
+	while (readl(ssp->base + HW_SSP_STATUS(ssp)) & (BM_SSP_STATUS_BUSY |
+						   BM_SSP_STATUS_DATA_BUSY |
+						   BM_SSP_STATUS_CMD_BUSY))
+		continue;
+
+	cmd->data->bytes_xfered = data_size;
+
+	host->status = readl(ssp->base + HW_SSP_STATUS(ssp));
+
+	c1 = readl(ssp->base + HW_SSP_CTRL1(ssp));
+
+	/* reset interrupt request status bits */
+	writel(c1 & MXS_MMC_ERR_IRQ_BITS,
+	       ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_CLR);
+
+	/* reenable these bits */
+	writel(ctrl1, ssp->base + HW_SSP_CTRL1(ssp) + STMP_OFFSET_REG_SET);
+	/* end IO operations */
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE:
+		break;
+	case MMC_RSP_R1:
+	case MMC_RSP_R3:
+		cmd->resp[0] =
+		    readl(ssp->base + HW_SSP_SDRESP0(ssp));
+		break;
+	case MMC_RSP_R2:
+		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));
+		break;
+	default:
+		dev_warn(mmc_dev(host->mmc), "Unsupported response type 0x%x\n",
+			 mmc_resp_type(cmd));
+		BUG();
+		break;
+	}
+
+	cmd->error = mxs_mmc_cmd_error(host->status);
+
+	if (cmd->error) {
+		dev_warn(mmc_dev(host->mmc), "ADTC command error %d\n", cmd->error);
+	} else {
+		dev_dbg(mmc_dev(host->mmc), "Transferred %u bytes\n",
+			cmd->data->bytes_xfered);
+	}
 }
 
 static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
@@ -489,11 +692,18 @@ static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
 
 static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
+	int done;
 	struct mxs_mmc_host *host = mmc_priv(mmc);
 
 	WARN_ON(host->mrq != NULL);
 	host->mrq = mrq;
 	mxs_mmc_start_cmd(host, mrq->cmd);
+
+	if (mrq->data && mrq->data->stop)
+		mxs_mmc_start_cmd(host, mrq->data->stop);
+
+	host->mrq = NULL;
+	mmc_request_done(mmc, mrq);
 }
 
 static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
@@ -603,6 +813,7 @@ static int mxs_mmc_probe(struct platform_device *pdev)
 
 	host->mmc = mmc;
 	host->sdio_irq_en = 0;
+	host->pio_size = 0;
 
 	reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc");
 	if (!IS_ERR(reg_vmmc)) {
diff --git a/include/linux/spi/mxs-spi.h b/include/linux/spi/mxs-spi.h
index 381d368..903c1c7 100644
--- a/include/linux/spi/mxs-spi.h
+++ b/include/linux/spi/mxs-spi.h
@@ -53,6 +53,8 @@
 #define  BP_SSP_CMD0_CMD			0
 #define  BM_SSP_CMD0_CMD			0xff
 #define HW_SSP_CMD1				0x020
+#define  BP_SSP_CMD1_CMD			0
+#define  BM_SSP_CMD1_CMD			0xFFFFFFFF
 #define HW_SSP_XFER_SIZE			0x030
 #define HW_SSP_BLOCK_SIZE			0x040
 #define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		4
@@ -116,6 +118,16 @@
 #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  BM_SSP_STATUS_RESP_CRC_ERR		0x00010000
+#define  BM_SSP_STATUS_RESP_ERR			0x00008000
+#define  BM_SSP_STATUS_RESP_TIMEOUT		0x00004000
+#define  BM_SSP_STATUS_DATA_CRC_ERR		0x00002000
+#define  BM_SSP_STATUS_TIMEOUT			0x00001000
+#define  BM_SSP_STATUS_FIFO_FULL		0x00000100
+#define  BM_SSP_STATUS_CMD_BUSY			0x00000008
+#define  BM_SSP_STATUS_DATA_BUSY		0x00000004
+#define  BM_SSP_STATUS_RSVD0			0x00000002
+#define  BM_SSP_STATUS_BUSY			0x00000001
 
 #define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
 
-- 
2.10.2

