mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/4] Add MCI over SPI support
@ 2011-11-23 21:12 franck.jullien
  2011-11-23 21:12 ` [PATCH 1/4] crypto: Add crc7 function franck.jullien
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: franck.jullien @ 2011-11-23 21:12 UTC (permalink / raw)
  To: barebox

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

This series adds MCI over SPI support to barebox.

It also makes small changes to nios2 in order to get
this thing to works. As a matter of fact, SPI master
drivers needs to support cs_change is you want to use
MCI over SPI.

Franck Jullien (4):
  crypto: Add crc7 function
  mci: Add MCI over SPI support
  nios2: Include asm/unaligned.h
  spi/altera_spi: Add cs_change support

 arch/nios2/include/asm/spi.h       |    1 +
 arch/nios2/include/asm/unaligned.h |   15 ++
 crypto/Kconfig                     |    3 +
 crypto/Makefile                    |    1 +
 crypto/crc7.c                      |   63 ++++++
 drivers/mci/Kconfig                |   17 ++
 drivers/mci/Makefile               |    1 +
 drivers/mci/mci-core.c             |   67 +++++--
 drivers/mci/mci_spi.c              |  431 ++++++++++++++++++++++++++++++++++++
 drivers/spi/altera_spi.c           |   27 +++-
 include/crc7.h                     |   14 ++
 include/mci.h                      |   14 ++
 12 files changed, 637 insertions(+), 17 deletions(-)
 create mode 100644 arch/nios2/include/asm/unaligned.h
 create mode 100644 crypto/crc7.c
 create mode 100644 drivers/mci/mci_spi.c
 create mode 100644 include/crc7.h

-- 
1.7.7


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

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

* [PATCH 1/4] crypto: Add crc7 function
  2011-11-23 21:12 [PATCH 0/4] Add MCI over SPI support franck.jullien
@ 2011-11-23 21:12 ` franck.jullien
  2011-11-23 21:12 ` [PATCH 2/4] mci: Add MCI over SPI support franck.jullien
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: franck.jullien @ 2011-11-23 21:12 UTC (permalink / raw)
  To: barebox

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

This function in used by the MCI over SPI driver.

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 crypto/Kconfig  |    3 ++
 crypto/Makefile |    1 +
 crypto/crc7.c   |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/crc7.h  |   14 ++++++++++++
 4 files changed, 81 insertions(+), 0 deletions(-)
 create mode 100644 crypto/crc7.c
 create mode 100644 include/crc7.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a391ae6..a6fc1b8 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -4,6 +4,9 @@ config CRC32
 config CRC16
 	bool
 
+config CRC7
+	bool
+
 menuconfig DIGEST
 	bool "Digest                        "
 
diff --git a/crypto/Makefile b/crypto/Makefile
index 955a66d..7c5b035 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_CRC16)	+= crc16.o
+obj-$(CONFIG_CRC7)	+= crc7.o
 obj-$(CONFIG_MD5)	+= md5.o
 obj-$(CONFIG_SHA1)	+= sha1.o
 obj-$(CONFIG_SHA224)	+= sha2.o
diff --git a/crypto/crc7.c b/crypto/crc7.c
new file mode 100644
index 0000000..8022199
--- /dev/null
+++ b/crypto/crc7.c
@@ -0,0 +1,63 @@
+/*
+ *      crc7.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <common.h>
+#include <crc7.h>
+
+
+/* Table for CRC-7 (polynomial x^7 + x^3 + 1) */
+const u8 crc7_syndrome_table[256] = {
+	0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+	0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+	0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+	0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+	0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+	0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+	0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+	0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+	0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+	0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+	0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+	0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+	0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+	0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+	0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+	0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+	0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+	0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+	0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+	0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+	0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+	0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+	0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+	0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+	0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+	0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+	0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+	0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+	0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+	0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+	0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+	0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+
+/**
+ * crc7 - update the CRC7 for the data buffer
+ * @crc:     previous CRC7 value
+ * @buffer:  data pointer
+ * @len:     number of bytes in the buffer
+ * Context: any
+ *
+ * Returns the updated CRC7 value.
+ */
+u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+	while (len--)
+		crc = crc7_byte(crc, *buffer++);
+	return crc;
+}
+EXPORT_SYMBOL(crc7);
diff --git a/include/crc7.h b/include/crc7.h
new file mode 100644
index 0000000..0c41cc3
--- /dev/null
+++ b/include/crc7.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_CRC7_H
+#define _LINUX_CRC7_H
+#include <common.h>
+
+extern const u8 crc7_syndrome_table[256];
+
+static inline u8 crc7_byte(u8 crc, u8 data)
+{
+	return crc7_syndrome_table[(crc << 1) ^ data];
+}
+
+extern u8 crc7(u8 crc, const u8 *buffer, size_t len);
+
+#endif
-- 
1.7.7


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

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

* [PATCH 2/4] mci: Add MCI over SPI support
  2011-11-23 21:12 [PATCH 0/4] Add MCI over SPI support franck.jullien
  2011-11-23 21:12 ` [PATCH 1/4] crypto: Add crc7 function franck.jullien
@ 2011-11-23 21:12 ` franck.jullien
  2011-11-24  9:17   ` Sascha Hauer
  2011-11-23 21:12 ` [PATCH 3/4] nios2: Include asm/unaligned.h franck.jullien
  2011-11-23 21:12 ` [PATCH 4/4] spi/altera_spi: Add cs_change support franck.jullien
  3 siblings, 1 reply; 7+ messages in thread
From: franck.jullien @ 2011-11-23 21:12 UTC (permalink / raw)
  To: barebox

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

This patch adds MMC over SPI support to mci-core.c and
mci_spi.c driver.

This driver is useful when SOC doesn't have built-in MCI
component. Tested with nios, 2Go SD-CARD and FAT file system.

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 drivers/mci/Kconfig    |   17 ++
 drivers/mci/Makefile   |    1 +
 drivers/mci/mci-core.c |   67 ++++++--
 drivers/mci/mci_spi.c  |  431 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/mci.h          |   14 ++
 5 files changed, 514 insertions(+), 16 deletions(-)
 create mode 100644 drivers/mci/mci_spi.c

diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 0d5a0e0..ed88abb 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -80,4 +80,21 @@ config MCI_ATMEL
 	  Enable this entry to add support to read and write SD cards on a
 	  Atmel AT91.
 
+config MCI_SPI
+	bool "MMC/SD over SPI"
+	help
+	  Some systems access MMC/SD/SDIO cards using a SPI controller
+	  instead of using a "native" MMC/SD/SDIO controller.  This has a
+	  disadvantage of being relatively high overhead, but a compensating
+	  advantage of working on many systems without dedicated MMC/SD/SDIO
+	  controllers.
+
+config MMC_SPI_CRC_ON
+	bool "Enable CRC protection for transferts"
+	select CRC7
+	select CRC16
+	depends on MCI_SPI
+	help
+	  EEnable CRC protection for transferts
+
 endif
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index 4fc0046..d7482dc 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_MCI_IMX) += imx.o
 obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o
 obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o
 obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o
+obj-$(CONFIG_MCI_SPI) += mci_spi.o
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 09f7e29..849c088 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -218,6 +218,7 @@ static int sd_send_op_cond(struct device_d *mci_dev)
 	int timeout = 1000;
 	int err;
 	unsigned voltages;
+	unsigned busy;
 
 	/*
 	 * Most cards do not answer if some reserved bits
@@ -237,7 +238,7 @@ static int sd_send_op_cond(struct device_d *mci_dev)
 		}
 
 		mci_setup_cmd(&cmd, SD_CMD_APP_SEND_OP_COND,
-			voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0),
+			mmc_host_is_spi(host) ? 0 : (voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0)),
 			MMC_RSP_R3);
 		err = mci_send_cmd(mci_dev, &cmd, NULL);
 		if (err) {
@@ -245,7 +246,13 @@ static int sd_send_op_cond(struct device_d *mci_dev)
 			return err;
 		}
 		udelay(1000);
-	} while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
+
+		if (mmc_host_is_spi(host))
+			busy = cmd.response[0] & R1_SPI_IDLE;
+		else
+			busy = !(cmd.response[0] & OCR_BUSY);
+
+	} while (busy && timeout--);
 
 	if (timeout <= 0) {
 		pr_debug("SD operation condition set timed out\n");
@@ -255,6 +262,13 @@ static int sd_send_op_cond(struct device_d *mci_dev)
 	if (mci->version != SD_VERSION_2)
 		mci->version = SD_VERSION_1_0;
 
+	if (mmc_host_is_spi(host)) { /* read OCR for spi */
+		mci_setup_cmd(&cmd, MMC_CMD_SPI_READ_OCR, 0, MMC_RSP_R3);
+		err = mci_send_cmd(mci_dev, &cmd, NULL);
+		if (err)
+			return err;
+	}
+
 	mci->ocr = cmd.response[0];
 
 	mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS);
@@ -451,6 +465,7 @@ static int sd_switch(struct device_d *mci_dev, unsigned mode, unsigned group,
 static int sd_change_freq(struct device_d *mci_dev)
 {
 	struct mci *mci = GET_MCI_DATA(mci_dev);
+	struct mci_host *host = GET_MCI_PDATA(mci_dev);
 	struct mci_cmd cmd;
 	struct mci_data data;
 	uint32_t *switch_status = sector_buf;
@@ -458,6 +473,9 @@ static int sd_change_freq(struct device_d *mci_dev)
 	int timeout;
 	int err;
 
+	if (mmc_host_is_spi(host))
+		return 0;
+
 	pr_debug("Changing transfer frequency\n");
 	mci->card_caps = 0;
 
@@ -748,10 +766,23 @@ static int mci_startup(struct device_d *mci_dev)
 	struct mci_cmd cmd;
 	int err;
 
+#ifdef CONFIG_MMC_SPI_CRC_ON
+	if (mmc_host_is_spi(host)) { /* enable CRC check for spi */
+
+		mci_setup_cmd(&cmd, MMC_CMD_SPI_CRC_ON_OFF, 1, MMC_RSP_R1);
+		err = mci_send_cmd(mci_dev, &cmd, NULL);
+
+		if (err) {
+			pr_debug("Can't enable CRC check : %d\n", err);
+			return err;
+		}
+	}
+#endif
+
 	pr_debug("Put the Card in Identify Mode\n");
 
 	/* Put the Card in Identify Mode */
-	mci_setup_cmd(&cmd, MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2);
+	mci_setup_cmd(&cmd, mmc_host_is_spi(host) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2);
 	err = mci_send_cmd(mci_dev, &cmd, NULL);
 	if (err) {
 		pr_debug("Can't bring card into identify mode: %d\n", err);
@@ -768,12 +799,14 @@ static int mci_startup(struct device_d *mci_dev)
 	 * For SD cards, get the Relatvie Address.
 	 * This also puts the cards into Standby State
 	 */
-	pr_debug("Get/Set relative address\n");
-	mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6);
-	err = mci_send_cmd(mci_dev, &cmd, NULL);
-	if (err) {
-		pr_debug("Get/Set relative address failed: %d\n", err);
-		return err;
+	if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */
+		pr_debug("Get/Set relative address\n");
+		mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6);
+		err = mci_send_cmd(mci_dev, &cmd, NULL);
+		if (err) {
+			pr_debug("Get/Set relative address failed: %d\n", err);
+			return err;
+		}
 	}
 
 	if (IS_SD(mci))
@@ -814,13 +847,15 @@ static int mci_startup(struct device_d *mci_dev)
 	pr_debug("Read block length: %u, Write block length: %u\n",
 		mci->read_bl_len, mci->write_bl_len);
 
-	pr_debug("Select the card, and put it into Transfer Mode\n");
-	/* Select the card, and put it into Transfer Mode */
-	mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b);
-	err = mci_send_cmd(mci_dev, &cmd, NULL);
-	if (err) {
-		pr_debug("Putting in transfer mode failed: %d\n", err);
-		return err;
+	if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */
+		pr_debug("Select the card, and put it into Transfer Mode\n");
+		/* Select the card, and put it into Transfer Mode */
+		mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b);
+		err = mci_send_cmd(mci_dev, &cmd, NULL);
+		if (err) {
+			pr_debug("Putting in transfer mode failed: %d\n", err);
+			return err;
+		}
 	}
 
 	if (IS_SD(mci))
diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c
new file mode 100644
index 0000000..663db89
--- /dev/null
+++ b/drivers/mci/mci_spi.c
@@ -0,0 +1,431 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * This code was inspired from u-boot mmc_spi.c:
+ * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * and linux mmc_spi.c:
+ * (C) Copyright 2005, Intec Automation,
+ *              Mike Lavender (mike@steroidmicros)
+ * (C) Copyright 2006-2007, David Brownell
+ * (C) Copyright 2007, Axis Communications,
+ *              Hans-Peter Nilsson (hp@axis.com)
+ * (C) Copyright 2007, ATRON electronic GmbH,
+ *              Jan Nikitenko <jan.nikitenko@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <errno.h>
+#include <clock.h>
+#include <asm/io.h>
+#include <driver.h>
+#include <spi/spi.h>
+#include <mci.h>
+#include <crc.h>
+#ifdef CONFIG_MMC_SPI_CRC_ON
+#include <crc7.h>
+#endif
+
+#define to_spi_host(mci) container_of(mci, struct mmc_spi_host, mci)
+#define spi_setup(spi) spi->master->setup(spi)
+
+/* Response tokens used to ack each block written: */
+#define SPI_MMC_RESPONSE_CODE(x)	((x) & 0x1f)
+#define SPI_RESPONSE_ACCEPTED		((2 << 1)|1)
+
+/* Read and write blocks start with these tokens and end with crc;
+ * on error, read tokens act like a subset of R2_SPI_* values.
+ */
+#define SPI_TOKEN_SINGLE	0xFE	/* single block r/w, multiblock read */
+#define SPI_TOKEN_MULTI_WRITE	0xFC	/* multiblock write */
+#define SPI_TOKEN_STOP_TRAN	0xFD	/* terminate multiblock write */
+
+/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
+#define MMC_SPI_CMD(x) (0x40 | (x & 0x3F))
+
+#define MMC_SPI_BLOCKSIZE       512
+
+/* timeout value */
+#define CTOUT 8
+#define RTOUT 3000000 /* 1 sec */
+#define WTOUT 3000000 /* 1 sec */
+
+#ifndef CONFIG_MMC_SPI_CRC_ON
+/* Note that while the CRC, in general, is ignored in SPI mode, the very first
+command must be followed by a valid CRC, since the card is not yet in SPI mode.
+The CRC byte for a CMD0 command with a zero argument is a constant 0x95. For
+simplicity, this CRC byte is always sent with every command. */
+
+static inline u8 crc7(u8 crc, const u8 *buffer, size_t len)
+{
+	return 0x4A;
+}
+#endif
+
+struct mmc_spi_host {
+	struct mci_host	mci;
+	struct spi_device	*spi;
+	struct device_d	*dev;
+
+	/* for bulk data transfers */
+	struct spi_transfer	t_tx;
+	struct spi_message	m_tx;
+
+	/* for status readback */
+	struct spi_transfer	t_rx;
+	struct spi_message	m_rx;
+
+	void			*ones;
+};
+
+static char *maptype(struct mci_cmd *cmd)
+{
+	switch (cmd->resp_type) {
+	case MMC_RSP_NONE:	return "NONE";
+	case MMC_RSP_R1:	return "R1";
+	case MMC_RSP_R1b:	return "R1B";
+	case MMC_RSP_R2:	return "R2/R5";
+	case MMC_RSP_R3:	return "R3/R4/R7";
+	default:		return "?";
+	}
+}
+
+static inline int mmc_cs_off(struct mmc_spi_host *host)
+{
+	/* chipselect will always be inactive after setup() */
+	return spi_setup(host->spi);
+}
+
+static int
+mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len, void *data)
+{
+	int status;
+
+	host->t_rx.len = len;
+	host->t_rx.rx_buf = data;
+
+	status = spi_sync(host->spi, &host->m_rx);
+
+	return status;
+}
+
+static int
+mmc_spi_writebytes(struct mmc_spi_host *host, unsigned len, void *data)
+{
+	int status;
+
+	host->t_tx.len = len;
+	host->t_tx.tx_buf = data;
+
+	status = spi_sync(host->spi, &host->m_tx);
+
+	return status;
+}
+
+static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd)
+{
+	uint8_t r1;
+	uint8_t command[7];
+	int i;
+
+	command[0] = 0xff;
+	command[1] = MMC_SPI_CMD(cmd->cmdidx);
+	command[2] = cmd->cmdarg >> 24;
+	command[3] = cmd->cmdarg >> 16;
+	command[4] = cmd->cmdarg >> 8;
+	command[5] = cmd->cmdarg;
+	command[6] = (crc7(0, &command[1], 5) << 1) | 0x01;
+
+	mmc_spi_writebytes(host, 7, command);
+
+	for (i = 0; i < CTOUT; i++) {
+		mmc_spi_readbytes(host, 1, &r1);
+		if (i && ((r1 & 0x80) == 0)) {  /* r1 response */
+			dev_dbg(host->dev, "%s: CMD%d, TRY %d, RESP %x\n", __func__, cmd->cmdidx, i, r1);
+			break;
+		}
+	}
+
+	return r1;
+}
+
+static uint mmc_spi_readdata(struct mmc_spi_host *host, void *xbuf,
+				uint32_t bcnt, uint32_t bsize)
+{
+	uint8_t *buf = xbuf;
+	uint8_t r1;
+	uint16_t crc;
+	int i;
+
+	while (bcnt--) {
+		for (i = 0; i < RTOUT; i++) {
+			mmc_spi_readbytes(host, 1, &r1);
+			if (r1 != 0xff) /* data token */
+				break;
+		}
+		if (r1 == SPI_TOKEN_SINGLE) {
+			mmc_spi_readbytes(host, bsize, buf);
+			mmc_spi_readbytes(host, 2, &crc);
+#ifdef CONFIG_MMC_SPI_CRC_ON
+			if (swab16(cyg_crc16(buf, bsize)) != crc) {
+				dev_dbg(host->dev, "%s: CRC error\n", __func__);
+				r1 = R1_SPI_COM_CRC;
+				break;
+			}
+#endif
+			r1 = 0;
+		} else {
+			r1 = R1_SPI_ERROR;
+			break;
+		}
+		buf += bsize;
+	}
+
+	return r1;
+}
+
+static uint mmc_spi_writedata(struct mmc_spi_host *host, const void *xbuf,
+			      uint32_t bcnt, uint32_t bsize, int multi)
+{
+	const uint8_t *buf = xbuf;
+	uint8_t r1;
+	uint16_t crc;
+	uint8_t tok[2];
+	int i;
+
+	tok[0] = 0xff;
+	tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
+
+	while (bcnt--) {
+#ifdef CONFIG_MMC_SPI_CRC_ON
+		crc = swab16(cyg_crc16((u8 *)buf, bsize));
+#endif
+		mmc_spi_writebytes(host, 2, tok);
+		mmc_spi_writebytes(host, bsize, (void *)buf);
+		mmc_spi_writebytes(host, 2, &crc);
+
+		for (i = 0; i < CTOUT; i++) {
+			mmc_spi_readbytes(host, 1, &r1);
+			if ((r1 & 0x11) == 0x01) /* response token */
+				break;
+		}
+
+		dev_dbg(host->dev,"%s   : TOKEN%d RESP 0x%X\n", __func__, i, r1);
+		if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
+			for (i = 0; i < WTOUT; i++) { /* wait busy */
+				mmc_spi_readbytes(host, 1, &r1);
+				if (i && r1 == 0xff) {
+					r1 = 0;
+					break;
+				}
+			}
+			if (i == WTOUT) {
+				dev_dbg(host->dev, "%s: wtout %x\n", __func__, r1);
+				r1 = R1_SPI_ERROR;
+				break;
+			}
+		} else {
+			dev_dbg(host->dev, "%s: err %x\n", __func__, r1);
+			r1 = R1_SPI_COM_CRC;
+			break;
+		}
+		buf += bsize;
+	}
+
+	if (multi && bcnt == -1) { /* stop multi write */
+		tok[1] = SPI_TOKEN_STOP_TRAN;
+		mmc_spi_writebytes(host, 2, tok);
+		for (i = 0; i < WTOUT; i++) { /* wait busy */
+			mmc_spi_readbytes(host, 1, &r1);
+			if (i && r1 == 0xff) {
+				r1 = 0;
+				break;
+			}
+		}
+		if (i == WTOUT) {
+			dev_dbg(host->dev, "%s: wstop %x\n", __func__, r1);
+			r1 = R1_SPI_ERROR;
+		}
+	}
+return r1;
+}
+
+static int mmc_spi_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
+{
+	struct mmc_spi_host	*host = to_spi_host(mci);
+	uint8_t r1;
+	int i;
+	int ret = 0;
+
+	dev_dbg(host->dev, "%s     : CMD%02d, RESP %s, ARG 0x%X\n", __func__,
+	      cmd->cmdidx, maptype(cmd), cmd->cmdarg);
+
+	r1 = mmc_spi_command_send(host, cmd);
+
+	cmd->response[0] = r1;
+
+	if (r1 == 0xff) { /* no response */
+		ret = -ETIME;
+		goto done;
+	} else if (r1 & R1_SPI_COM_CRC) {
+		ret = -ECOMM;
+		goto done;
+	} else if (r1 & ~R1_SPI_IDLE) { /* other errors */
+		ret = -ETIME;
+		goto done;
+	} else if (cmd->resp_type == MMC_RSP_R2) {
+		r1 = mmc_spi_readdata(host, cmd->response, 1, 16);
+		for (i = 0; i < 4; i++)
+			cmd->response[i] = swab32(cmd->response[i]);
+		dev_dbg(host->dev, "MMC_RSP_R2 -> %x %x %x %x\n", cmd->response[0], cmd->response[1],
+		      cmd->response[2], cmd->response[3]);
+	} else if (!data) {
+		switch (cmd->cmdidx) {
+		case SD_CMD_SEND_IF_COND:
+		case MMC_CMD_SPI_READ_OCR:
+			mmc_spi_readbytes(host, 4, cmd->response);
+			cmd->response[0] = swab32(cmd->response[0]);
+			break;
+		}
+	} else {
+		if (data->flags == MMC_DATA_READ) {
+			dev_dbg(host->dev, "%s     : DATA READ, %x blocks, bsize = 0x%X\n", __func__,
+			      data->blocks, data->blocksize);
+			r1 = mmc_spi_readdata(host, data->dest,
+				data->blocks, data->blocksize);
+		} else if  (data->flags == MMC_DATA_WRITE) {
+			dev_dbg(host->dev, "%s     : DATA WRITE, %x blocks, bsize = 0x%X\n", __func__,
+			      data->blocks, data->blocksize);
+			r1 = mmc_spi_writedata(host, data->src,
+				data->blocks, data->blocksize,
+				(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
+		}
+		if (r1 & R1_SPI_COM_CRC)
+			ret = -ECOMM;
+		else if (r1) 
+			ret = -ETIME;
+	}
+
+done:
+	mmc_cs_off(host);
+	return ret;
+
+return  0;
+
+}
+
+static void mmc_spi_set_ios(struct mci_host *mci, struct device_d *mci_dev,
+			unsigned bus_width, unsigned clock)
+{
+	struct mmc_spi_host	*host = to_spi_host(mci);
+
+	spi_setup(host->spi);
+}
+
+static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev)
+{
+	struct mmc_spi_host	*host = to_spi_host(mci);
+	mmc_spi_readbytes(host, 10, NULL);
+
+	/*
+	 * Do a burst with chipselect active-high.  We need to do this to
+	 * meet the requirement of 74 clock cycles with both chipselect
+	 * and CMD (MOSI) high before CMD0 ... after the card has been
+	 * powered up to Vdd(min), and so is ready to take commands.
+	 *
+	 * Some cards are particularly needy of this (e.g. Viking "SD256")
+	 * while most others don't seem to care.
+	 *
+	 * Note that this is one of the places MMC/SD plays games with the
+	 * SPI protocol.  Another is that when chipselect is released while
+	 * the card returns BUSY status, the clock must issue several cycles
+	 * with chipselect high before the card will stop driving its output.
+	 */
+
+	host->spi->mode |= SPI_CS_HIGH;
+	if (spi_setup(host->spi) != 0) {
+		/* Just warn; most cards work without it. */
+		dev_warn(&host->spi->dev,
+				"can't change chip-select polarity\n");
+		host->spi->mode &= ~SPI_CS_HIGH;
+	} else {
+		mmc_spi_readbytes(host, 18, NULL);
+
+		host->spi->mode &= ~SPI_CS_HIGH;
+		if (spi_setup(host->spi) != 0) {
+			/* Wot, we can't get the same setup we had before? */
+			dev_err(&host->spi->dev,
+					"can't restore chip-select polarity\n");
+		}
+	}
+
+	return 0;
+}
+
+static int spi_mci_probe(struct device_d *dev)
+{
+	struct spi_device	*spi = (struct spi_device *)dev->type_data;
+	struct mmc_spi_host	*host;
+	void			*ones;
+
+	host = xzalloc(sizeof(*host));
+	host->mci.send_cmd = mmc_spi_request;
+	host->mci.set_ios = mmc_spi_set_ios;
+	host->mci.init = mmc_spi_init;
+
+	host->dev = dev;
+	host->spi = spi;
+	dev->priv = host;
+
+	ones = xmalloc(MMC_SPI_BLOCKSIZE);
+	memset(ones, 0xff, MMC_SPI_BLOCKSIZE);
+
+	host->ones = ones;
+
+	spi_message_init(&host->m_tx);
+	spi_message_init(&host->m_rx);
+
+	spi_message_add_tail(&host->t_tx, &host->m_tx);
+	spi_message_add_tail(&host->t_rx, &host->m_rx);
+
+	host->t_rx.tx_buf = host->ones;
+	host->t_rx.cs_change = 1;
+
+	host->t_tx.cs_change = 1;
+
+	host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	host->mci.host_caps = MMC_CAP_SPI;
+
+	mci_register(&host->mci);
+
+	return 0;
+}
+
+static struct driver_d spi_mci_driver = {
+	.name	= "spi_mci",
+	.probe	= spi_mci_probe,
+};
+
+static int spi_mci_init_driver(void)
+{
+	register_driver(&spi_mci_driver);
+	return 0;
+}
+
+device_initcall(spi_mci_init_driver);
diff --git a/include/mci.h b/include/mci.h
index 69cffe8..ed54e14 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -49,6 +49,7 @@
 
 #define MMC_MODE_HS		0x001
 #define MMC_MODE_HS_52MHz	0x010
+#define MMC_CAP_SPI		0x020
 #define MMC_MODE_4BIT		0x100
 #define MMC_MODE_8BIT		0x200
 
@@ -56,6 +57,8 @@
 
 #define IS_SD(x) (x->version & SD_VERSION_SD)
 
+#define mmc_host_is_spi(host)	((host)->host_caps & MMC_CAP_SPI)
+
 #define MMC_DATA_READ		1
 #define MMC_DATA_WRITE		2
 
@@ -78,6 +81,8 @@
 #define MMC_CMD_WRITE_SINGLE_BLOCK	24
 #define MMC_CMD_WRITE_MULTIPLE_BLOCK	25
 #define MMC_CMD_APP_CMD			55
+#define MMC_CMD_SPI_READ_OCR		58
+#define MMC_CMD_SPI_CRC_ON_OFF		59
 
 #define SD_CMD_SEND_RELATIVE_ADDR	3
 #define SD_CMD_SWITCH_FUNC		6
@@ -155,6 +160,15 @@
 #define R1_ILLEGAL_COMMAND		(1 << 22)
 #define R1_APP_CMD			(1 << 5)
 
+#define R1_SPI_IDLE		(1 << 0)
+#define R1_SPI_ERASE_RESET	(1 << 1)
+#define R1_SPI_ILLEGAL_COMMAND	(1 << 2)
+#define R1_SPI_COM_CRC		(1 << 3)
+#define R1_SPI_ERASE_SEQ	(1 << 4)
+#define R1_SPI_ADDRESS		(1 << 5)
+#define R1_SPI_PARAMETER	(1 << 6)
+#define R1_SPI_ERROR		(1 << 7)
+
 /* response types */
 #define MMC_RSP_PRESENT (1 << 0)
 #define MMC_RSP_136     (1 << 1)                /* 136 bit response */
-- 
1.7.7


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

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

* [PATCH 3/4] nios2: Include asm/unaligned.h
  2011-11-23 21:12 [PATCH 0/4] Add MCI over SPI support franck.jullien
  2011-11-23 21:12 ` [PATCH 1/4] crypto: Add crc7 function franck.jullien
  2011-11-23 21:12 ` [PATCH 2/4] mci: Add MCI over SPI support franck.jullien
@ 2011-11-23 21:12 ` franck.jullien
  2011-11-24  9:36   ` Sascha Hauer
  2011-11-23 21:12 ` [PATCH 4/4] spi/altera_spi: Add cs_change support franck.jullien
  3 siblings, 1 reply; 7+ messages in thread
From: franck.jullien @ 2011-11-23 21:12 UTC (permalink / raw)
  To: barebox

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

drivers/ata/disk_drive.c needs it....

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 arch/nios2/include/asm/unaligned.h |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
 create mode 100644 arch/nios2/include/asm/unaligned.h

diff --git a/arch/nios2/include/asm/unaligned.h b/arch/nios2/include/asm/unaligned.h
new file mode 100644
index 0000000..7615e8a
--- /dev/null
+++ b/arch/nios2/include/asm/unaligned.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_NIOS_UNALIGNED_H
+#define _ASM_NIOS_UNALIGNED_H
+
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/unaligned/be_byteshift.h>
+#include <linux/unaligned/generic.h>
+
+/*
+ * Select endianness
+ */
+
+#define get_unaligned	__get_unaligned_le
+#define put_unaligned	__put_unaligned_le
+
+#endif /* _ASM_NIOS_UNALIGNED_H */
-- 
1.7.7


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

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

* [PATCH 4/4] spi/altera_spi: Add cs_change support
  2011-11-23 21:12 [PATCH 0/4] Add MCI over SPI support franck.jullien
                   ` (2 preceding siblings ...)
  2011-11-23 21:12 ` [PATCH 3/4] nios2: Include asm/unaligned.h franck.jullien
@ 2011-11-23 21:12 ` franck.jullien
  3 siblings, 0 replies; 7+ messages in thread
From: franck.jullien @ 2011-11-23 21:12 UTC (permalink / raw)
  To: barebox

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

The Linux kernel says (spi.h) :

* All SPI transfers start with the relevant chipselect active.  Normally
* it stays selected until after the last transfer in a message.  Drivers
* can affect the chipselect signal using cs_change.
*
* (i) If the transfer isn't the last one in the message, this flag is
* used to make the chipselect briefly go inactive in the middle of the
* message.  Toggling chipselect in this way may be needed to terminate
* a chip command, letting a single spi_message perform all of group of
* chip transactions together.
*
* (ii) When the transfer is the last one in the message, the chip may
* stay selected until the next transfer.  On multi-device SPI busses
* with nothing blocking messages going to other devices, this is just
* a performance hint; starting a message to another device deselects
* this one.  But in other cases, this can be used to ensure correctness.
* Some devices need protocol transactions to be built from a series of
* spi_message submissions, where the content of one message is
* determined by the results of previous messages and where the whole
* transaction
* ends when the chipselect goes intactive.

In other words, cs_change changes the default chipselect *behavior*.

Support of cs_change is necessary to implement the mci spi driver.

This patch also fix few things:

Passing the bus number to the brand new master device.
Disable chipselect during master->setup.

Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
---
 arch/nios2/include/asm/spi.h |    1 +
 drivers/spi/altera_spi.c     |   27 ++++++++++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/arch/nios2/include/asm/spi.h b/arch/nios2/include/asm/spi.h
index 4e576b9..6c5740c 100644
--- a/arch/nios2/include/asm/spi.h
+++ b/arch/nios2/include/asm/spi.h
@@ -8,6 +8,7 @@ struct spi_altera_master {
 	int	spi_mode;
 	int	databits;
 	int	speed;
+	int	bus_num;
 };
 
 struct altera_spi {
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
index 4fd82fb..d63dce3 100644
--- a/drivers/spi/altera_spi.c
+++ b/drivers/spi/altera_spi.c
@@ -25,6 +25,9 @@
 #include <io.h>
 #include <asm/spi.h>
 #include <asm/nios2-io.h>
+#include <clock.h>
+
+static void altera_spi_cs_inactive(struct spi_device *spi);
 
 static int altera_spi_setup(struct spi_device *spi)
 {
@@ -49,6 +52,8 @@ static int altera_spi_setup(struct spi_device *spi)
 		return -1;
 	}
 
+	altera_spi_cs_inactive(spi);
+
 	dev_dbg(master->dev, " mode 0x%08x, bits_per_word: %d, speed: %d\n",
 		spi->mode, spi->bits_per_word, altera_spi->speed);
 
@@ -167,19 +172,38 @@ static int altera_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
 	struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
 	struct nios_spi *nios_spi = altera_spi->regs;
 	struct spi_transfer *t;
+	unsigned int cs_change;
+	const int nsecs = 50;
 
 	altera_spi_cs_active(spi);
 
+	cs_change = 0;
+
 	mesg->actual_length = 0;
 
 	list_for_each_entry(t, &mesg->transfers, transfer_list) {
+
+		if (cs_change) {
+			ndelay(nsecs);
+			altera_spi_cs_inactive(spi);
+			ndelay(nsecs);
+			altera_spi_cs_active(spi);
+		}
+
+		cs_change = t->cs_change;
+
 		mesg->actual_length += altera_spi_do_xfer(spi, t);
+
+		if (cs_change) {
+			altera_spi_cs_active(spi);
+		}
 	}
 
 	/* Wait the end of any pending transfer */
 	while ((readl(&nios_spi->status) & NIOS_SPI_TMT) == 0);
 
-	altera_spi_cs_inactive(spi);
+	if(!cs_change)
+		altera_spi_cs_inactive(spi);
 
 	return 0;
 }
@@ -199,6 +223,7 @@ static int altera_spi_probe(struct device_d *dev)
 	master->setup = altera_spi_setup;
 	master->transfer = altera_spi_transfer;
 	master->num_chipselect = pdata->num_chipselect;
+	master->bus_num = pdata->bus_num;
 
 	altera_spi->regs = dev_request_mem_region(dev, 0);
 	altera_spi->databits = pdata->databits;
-- 
1.7.7


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

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

* Re: [PATCH 2/4] mci: Add MCI over SPI support
  2011-11-23 21:12 ` [PATCH 2/4] mci: Add MCI over SPI support franck.jullien
@ 2011-11-24  9:17   ` Sascha Hauer
  0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2011-11-24  9:17 UTC (permalink / raw)
  To: franck.jullien; +Cc: barebox

Hi Franck,

Nice to see this driver. Some comments inline.


On Wed, Nov 23, 2011 at 10:12:26PM +0100, franck.jullien@gmail.com wrote:
> From: Franck Jullien <franck.jullien@gmail.com>
> 
> This patch adds MMC over SPI support to mci-core.c and
> mci_spi.c driver.
> 
> This driver is useful when SOC doesn't have built-in MCI
> component. Tested with nios, 2Go SD-CARD and FAT file system.
> 
> Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
> ---
>  drivers/mci/Kconfig    |   17 ++
>  drivers/mci/Makefile   |    1 +
>  drivers/mci/mci-core.c |   67 ++++++--
>  drivers/mci/mci_spi.c  |  431 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/mci.h          |   14 ++
>  5 files changed, 514 insertions(+), 16 deletions(-)
>  create mode 100644 drivers/mci/mci_spi.c
> 
> diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
> index 0d5a0e0..ed88abb 100644
> --- a/drivers/mci/Kconfig
> +++ b/drivers/mci/Kconfig
> @@ -80,4 +80,21 @@ config MCI_ATMEL
>  	  Enable this entry to add support to read and write SD cards on a
>  	  Atmel AT91.
>  
> +config MCI_SPI
> +	bool "MMC/SD over SPI"
> +	help
> +	  Some systems access MMC/SD/SDIO cards using a SPI controller
> +	  instead of using a "native" MMC/SD/SDIO controller.  This has a
> +	  disadvantage of being relatively high overhead, but a compensating
> +	  advantage of working on many systems without dedicated MMC/SD/SDIO
> +	  controllers.
> +
> +config MMC_SPI_CRC_ON
> +	bool "Enable CRC protection for transferts"

s/transferts/transfers/

> +	select CRC7
> +	select CRC16
> +	depends on MCI_SPI
> +	help
> +	  EEnable CRC protection for transferts

s/EEnable/Enable/

> +
>  endif
> diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
> index 4fc0046..d7482dc 100644
> --- a/drivers/mci/Makefile
> +++ b/drivers/mci/Makefile
> @@ -5,3 +5,4 @@ obj-$(CONFIG_MCI_IMX) += imx.o
>  obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o
>  obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o
>  obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o
> +obj-$(CONFIG_MCI_SPI) += mci_spi.o
> diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
> index 09f7e29..849c088 100644
> --- a/drivers/mci/mci-core.c
> +++ b/drivers/mci/mci-core.c
> @@ -218,6 +218,7 @@ static int sd_send_op_cond(struct device_d *mci_dev)
>  	int timeout = 1000;
>  	int err;
>  	unsigned voltages;
> +	unsigned busy;
>  
>  	/*
>  	 * Most cards do not answer if some reserved bits
> @@ -237,7 +238,7 @@ static int sd_send_op_cond(struct device_d *mci_dev)
>  		}
>  
>  		mci_setup_cmd(&cmd, SD_CMD_APP_SEND_OP_COND,
> -			voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0),
> +			mmc_host_is_spi(host) ? 0 : (voltages | (mci->version == SD_VERSION_2 ? OCR_HCS : 0)),
>  			MMC_RSP_R3);
>  		err = mci_send_cmd(mci_dev, &cmd, NULL);
>  		if (err) {
> @@ -245,7 +246,13 @@ static int sd_send_op_cond(struct device_d *mci_dev)
>  			return err;
>  		}
>  		udelay(1000);
> -	} while ((!(cmd.response[0] & OCR_BUSY)) && timeout--);
> +
> +		if (mmc_host_is_spi(host))
> +			busy = cmd.response[0] & R1_SPI_IDLE;
> +		else
> +			busy = !(cmd.response[0] & OCR_BUSY);
> +
> +	} while (busy && timeout--);
>  
>  	if (timeout <= 0) {
>  		pr_debug("SD operation condition set timed out\n");
> @@ -255,6 +262,13 @@ static int sd_send_op_cond(struct device_d *mci_dev)
>  	if (mci->version != SD_VERSION_2)
>  		mci->version = SD_VERSION_1_0;
>  
> +	if (mmc_host_is_spi(host)) { /* read OCR for spi */
> +		mci_setup_cmd(&cmd, MMC_CMD_SPI_READ_OCR, 0, MMC_RSP_R3);
> +		err = mci_send_cmd(mci_dev, &cmd, NULL);
> +		if (err)
> +			return err;
> +	}
> +
>  	mci->ocr = cmd.response[0];
>  
>  	mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS);
> @@ -451,6 +465,7 @@ static int sd_switch(struct device_d *mci_dev, unsigned mode, unsigned group,
>  static int sd_change_freq(struct device_d *mci_dev)
>  {
>  	struct mci *mci = GET_MCI_DATA(mci_dev);
> +	struct mci_host *host = GET_MCI_PDATA(mci_dev);
>  	struct mci_cmd cmd;
>  	struct mci_data data;
>  	uint32_t *switch_status = sector_buf;
> @@ -458,6 +473,9 @@ static int sd_change_freq(struct device_d *mci_dev)
>  	int timeout;
>  	int err;
>  
> +	if (mmc_host_is_spi(host))
> +		return 0;
> +
>  	pr_debug("Changing transfer frequency\n");
>  	mci->card_caps = 0;
>  
> @@ -748,10 +766,23 @@ static int mci_startup(struct device_d *mci_dev)
>  	struct mci_cmd cmd;
>  	int err;
>  
> +#ifdef CONFIG_MMC_SPI_CRC_ON
> +	if (mmc_host_is_spi(host)) { /* enable CRC check for spi */
> +
> +		mci_setup_cmd(&cmd, MMC_CMD_SPI_CRC_ON_OFF, 1, MMC_RSP_R1);
> +		err = mci_send_cmd(mci_dev, &cmd, NULL);
> +
> +		if (err) {
> +			pr_debug("Can't enable CRC check : %d\n", err);
> +			return err;
> +		}
> +	}
> +#endif
> +
>  	pr_debug("Put the Card in Identify Mode\n");
>  
>  	/* Put the Card in Identify Mode */
> -	mci_setup_cmd(&cmd, MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2);
> +	mci_setup_cmd(&cmd, mmc_host_is_spi(host) ? MMC_CMD_SEND_CID : MMC_CMD_ALL_SEND_CID, 0, MMC_RSP_R2);
>  	err = mci_send_cmd(mci_dev, &cmd, NULL);
>  	if (err) {
>  		pr_debug("Can't bring card into identify mode: %d\n", err);
> @@ -768,12 +799,14 @@ static int mci_startup(struct device_d *mci_dev)
>  	 * For SD cards, get the Relatvie Address.
>  	 * This also puts the cards into Standby State
>  	 */
> -	pr_debug("Get/Set relative address\n");
> -	mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6);
> -	err = mci_send_cmd(mci_dev, &cmd, NULL);
> -	if (err) {
> -		pr_debug("Get/Set relative address failed: %d\n", err);
> -		return err;
> +	if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */
> +		pr_debug("Get/Set relative address\n");
> +		mci_setup_cmd(&cmd, SD_CMD_SEND_RELATIVE_ADDR, mci->rca << 16, MMC_RSP_R6);
> +		err = mci_send_cmd(mci_dev, &cmd, NULL);
> +		if (err) {
> +			pr_debug("Get/Set relative address failed: %d\n", err);
> +			return err;
> +		}
>  	}
>  
>  	if (IS_SD(mci))
> @@ -814,13 +847,15 @@ static int mci_startup(struct device_d *mci_dev)
>  	pr_debug("Read block length: %u, Write block length: %u\n",
>  		mci->read_bl_len, mci->write_bl_len);
>  
> -	pr_debug("Select the card, and put it into Transfer Mode\n");
> -	/* Select the card, and put it into Transfer Mode */
> -	mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b);
> -	err = mci_send_cmd(mci_dev, &cmd, NULL);
> -	if (err) {
> -		pr_debug("Putting in transfer mode failed: %d\n", err);
> -		return err;
> +	if (!mmc_host_is_spi(host)) { /* cmd not supported in spi */
> +		pr_debug("Select the card, and put it into Transfer Mode\n");
> +		/* Select the card, and put it into Transfer Mode */
> +		mci_setup_cmd(&cmd, MMC_CMD_SELECT_CARD, mci->rca << 16, MMC_RSP_R1b);
> +		err = mci_send_cmd(mci_dev, &cmd, NULL);
> +		if (err) {
> +			pr_debug("Putting in transfer mode failed: %d\n", err);
> +			return err;
> +		}
>  	}
>  
>  	if (IS_SD(mci))
> diff --git a/drivers/mci/mci_spi.c b/drivers/mci/mci_spi.c
> new file mode 100644
> index 0000000..663db89
> --- /dev/null
> +++ b/drivers/mci/mci_spi.c
> @@ -0,0 +1,431 @@
> +/*
> + * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
> + *
> + * This code was inspired from u-boot mmc_spi.c:
> + * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
> + *
> + * and linux mmc_spi.c:
> + * (C) Copyright 2005, Intec Automation,
> + *              Mike Lavender (mike@steroidmicros)
> + * (C) Copyright 2006-2007, David Brownell
> + * (C) Copyright 2007, Axis Communications,
> + *              Hans-Peter Nilsson (hp@axis.com)
> + * (C) Copyright 2007, ATRON electronic GmbH,
> + *              Jan Nikitenko <jan.nikitenko@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <errno.h>
> +#include <clock.h>
> +#include <asm/io.h>
> +#include <driver.h>
> +#include <spi/spi.h>
> +#include <mci.h>
> +#include <crc.h>
> +#ifdef CONFIG_MMC_SPI_CRC_ON
> +#include <crc7.h>
> +#endif

Please do not ifdef includes.

> +
> +#define to_spi_host(mci) container_of(mci, struct mmc_spi_host, mci)
> +#define spi_setup(spi) spi->master->setup(spi)
> +
> +/* Response tokens used to ack each block written: */
> +#define SPI_MMC_RESPONSE_CODE(x)	((x) & 0x1f)
> +#define SPI_RESPONSE_ACCEPTED		((2 << 1)|1)
> +
> +/* Read and write blocks start with these tokens and end with crc;
> + * on error, read tokens act like a subset of R2_SPI_* values.
> + */
> +#define SPI_TOKEN_SINGLE	0xFE	/* single block r/w, multiblock read */
> +#define SPI_TOKEN_MULTI_WRITE	0xFC	/* multiblock write */
> +#define SPI_TOKEN_STOP_TRAN	0xFD	/* terminate multiblock write */
> +
> +/* MMC SPI commands start with a start bit "0" and a transmit bit "1" */
> +#define MMC_SPI_CMD(x) (0x40 | (x & 0x3F))
> +
> +#define MMC_SPI_BLOCKSIZE       512
> +
> +/* timeout value */
> +#define CTOUT 8
> +#define RTOUT 3000000 /* 1 sec */
> +#define WTOUT 3000000 /* 1 sec */
> +
> +#ifndef CONFIG_MMC_SPI_CRC_ON
> +/* Note that while the CRC, in general, is ignored in SPI mode, the very first
> +command must be followed by a valid CRC, since the card is not yet in SPI mode.
> +The CRC byte for a CMD0 command with a zero argument is a constant 0x95. For
> +simplicity, this CRC byte is always sent with every command. */
> +
> +static inline u8 crc7(u8 crc, const u8 *buffer, size_t len)
> +{
> +	return 0x4A;
> +}
> +#endif

Is it 0x4a or 0x95? While it's good to have a comment for this the
difference in the values is a bit confusing.

/*
 * Multi line comments
 * like this please
 */

> +
> +struct mmc_spi_host {
> +	struct mci_host	mci;
> +	struct spi_device	*spi;
> +	struct device_d	*dev;
> +
> +	/* for bulk data transfers */
> +	struct spi_transfer	t_tx;
> +	struct spi_message	m_tx;
> +
> +	/* for status readback */
> +	struct spi_transfer	t_rx;
> +	struct spi_message	m_rx;
> +
> +	void			*ones;
> +};
> +
> +static char *maptype(struct mci_cmd *cmd)
> +{
> +	switch (cmd->resp_type) {
> +	case MMC_RSP_NONE:	return "NONE";
> +	case MMC_RSP_R1:	return "R1";
> +	case MMC_RSP_R1b:	return "R1B";
> +	case MMC_RSP_R2:	return "R2/R5";
> +	case MMC_RSP_R3:	return "R3/R4/R7";
> +	default:		return "?";
> +	}
> +}
> +
> +static inline int mmc_cs_off(struct mmc_spi_host *host)
> +{
> +	/* chipselect will always be inactive after setup() */
> +	return spi_setup(host->spi);
> +}
> +
> +static int
> +mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len, void *data)
> +{
> +	int status;
> +
> +	host->t_rx.len = len;
> +	host->t_rx.rx_buf = data;
> +
> +	status = spi_sync(host->spi, &host->m_rx);
> +
> +	return status;
> +}
> +
> +static int
> +mmc_spi_writebytes(struct mmc_spi_host *host, unsigned len, void *data)
> +{
> +	int status;
> +
> +	host->t_tx.len = len;
> +	host->t_tx.tx_buf = data;
> +
> +	status = spi_sync(host->spi, &host->m_tx);
> +
> +	return status;
> +}
> +
> +static int mmc_spi_command_send(struct mmc_spi_host *host, struct mci_cmd *cmd)
> +{
> +	uint8_t r1;
> +	uint8_t command[7];
> +	int i;
> +
> +	command[0] = 0xff;
> +	command[1] = MMC_SPI_CMD(cmd->cmdidx);
> +	command[2] = cmd->cmdarg >> 24;
> +	command[3] = cmd->cmdarg >> 16;
> +	command[4] = cmd->cmdarg >> 8;
> +	command[5] = cmd->cmdarg;
> +	command[6] = (crc7(0, &command[1], 5) << 1) | 0x01;
> +
> +	mmc_spi_writebytes(host, 7, command);
> +
> +	for (i = 0; i < CTOUT; i++) {
> +		mmc_spi_readbytes(host, 1, &r1);
> +		if (i && ((r1 & 0x80) == 0)) {  /* r1 response */
> +			dev_dbg(host->dev, "%s: CMD%d, TRY %d, RESP %x\n", __func__, cmd->cmdidx, i, r1);
> +			break;
> +		}
> +	}
> +
> +	return r1;
> +}
> +
> +static uint mmc_spi_readdata(struct mmc_spi_host *host, void *xbuf,
> +				uint32_t bcnt, uint32_t bsize)
> +{
> +	uint8_t *buf = xbuf;
> +	uint8_t r1;
> +	uint16_t crc;
> +	int i;
> +
> +	while (bcnt--) {
> +		for (i = 0; i < RTOUT; i++) {
> +			mmc_spi_readbytes(host, 1, &r1);
> +			if (r1 != 0xff) /* data token */
> +				break;
> +		}
> +		if (r1 == SPI_TOKEN_SINGLE) {
> +			mmc_spi_readbytes(host, bsize, buf);
> +			mmc_spi_readbytes(host, 2, &crc);
> +#ifdef CONFIG_MMC_SPI_CRC_ON
> +			if (swab16(cyg_crc16(buf, bsize)) != crc) {
> +				dev_dbg(host->dev, "%s: CRC error\n", __func__);
> +				r1 = R1_SPI_COM_CRC;
> +				break;
> +			}
> +#endif
> +			r1 = 0;
> +		} else {
> +			r1 = R1_SPI_ERROR;
> +			break;
> +		}
> +		buf += bsize;
> +	}
> +
> +	return r1;
> +}
> +
> +static uint mmc_spi_writedata(struct mmc_spi_host *host, const void *xbuf,
> +			      uint32_t bcnt, uint32_t bsize, int multi)
> +{
> +	const uint8_t *buf = xbuf;
> +	uint8_t r1;
> +	uint16_t crc;
> +	uint8_t tok[2];
> +	int i;
> +
> +	tok[0] = 0xff;
> +	tok[1] = multi ? SPI_TOKEN_MULTI_WRITE : SPI_TOKEN_SINGLE;
> +
> +	while (bcnt--) {
> +#ifdef CONFIG_MMC_SPI_CRC_ON
> +		crc = swab16(cyg_crc16((u8 *)buf, bsize));
> +#endif
> +		mmc_spi_writebytes(host, 2, tok);
> +		mmc_spi_writebytes(host, bsize, (void *)buf);
> +		mmc_spi_writebytes(host, 2, &crc);

Without CONFIG_MMC_SPI_CRC_ON you write an unitialized variable out to
the device. It's probably ignored anyway then, but it's nicer to
initialize it.

> +
> +		for (i = 0; i < CTOUT; i++) {
> +			mmc_spi_readbytes(host, 1, &r1);
> +			if ((r1 & 0x11) == 0x01) /* response token */
> +				break;
> +		}
> +
> +		dev_dbg(host->dev,"%s   : TOKEN%d RESP 0x%X\n", __func__, i, r1);
> +		if (SPI_MMC_RESPONSE_CODE(r1) == SPI_RESPONSE_ACCEPTED) {
> +			for (i = 0; i < WTOUT; i++) { /* wait busy */
> +				mmc_spi_readbytes(host, 1, &r1);
> +				if (i && r1 == 0xff) {
> +					r1 = 0;
> +					break;
> +				}
> +			}
> +			if (i == WTOUT) {
> +				dev_dbg(host->dev, "%s: wtout %x\n", __func__, r1);
> +				r1 = R1_SPI_ERROR;
> +				break;
> +			}
> +		} else {
> +			dev_dbg(host->dev, "%s: err %x\n", __func__, r1);
> +			r1 = R1_SPI_COM_CRC;
> +			break;
> +		}
> +		buf += bsize;
> +	}
> +
> +	if (multi && bcnt == -1) { /* stop multi write */
> +		tok[1] = SPI_TOKEN_STOP_TRAN;
> +		mmc_spi_writebytes(host, 2, tok);
> +		for (i = 0; i < WTOUT; i++) { /* wait busy */
> +			mmc_spi_readbytes(host, 1, &r1);
> +			if (i && r1 == 0xff) {
> +				r1 = 0;
> +				break;
> +			}
> +		}
> +		if (i == WTOUT) {
> +			dev_dbg(host->dev, "%s: wstop %x\n", __func__, r1);
> +			r1 = R1_SPI_ERROR;
> +		}
> +	}
> +return r1;

missing \t

> +}
> +
> +static int mmc_spi_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
> +{
> +	struct mmc_spi_host	*host = to_spi_host(mci);
> +	uint8_t r1;
> +	int i;
> +	int ret = 0;
> +
> +	dev_dbg(host->dev, "%s     : CMD%02d, RESP %s, ARG 0x%X\n", __func__,
> +	      cmd->cmdidx, maptype(cmd), cmd->cmdarg);
> +
> +	r1 = mmc_spi_command_send(host, cmd);
> +
> +	cmd->response[0] = r1;
> +
> +	if (r1 == 0xff) { /* no response */
> +		ret = -ETIME;
> +		goto done;
> +	} else if (r1 & R1_SPI_COM_CRC) {
> +		ret = -ECOMM;
> +		goto done;
> +	} else if (r1 & ~R1_SPI_IDLE) { /* other errors */
> +		ret = -ETIME;
> +		goto done;
> +	} else if (cmd->resp_type == MMC_RSP_R2) {
> +		r1 = mmc_spi_readdata(host, cmd->response, 1, 16);
> +		for (i = 0; i < 4; i++)
> +			cmd->response[i] = swab32(cmd->response[i]);
> +		dev_dbg(host->dev, "MMC_RSP_R2 -> %x %x %x %x\n", cmd->response[0], cmd->response[1],
> +		      cmd->response[2], cmd->response[3]);
> +	} else if (!data) {
> +		switch (cmd->cmdidx) {
> +		case SD_CMD_SEND_IF_COND:
> +		case MMC_CMD_SPI_READ_OCR:
> +			mmc_spi_readbytes(host, 4, cmd->response);
> +			cmd->response[0] = swab32(cmd->response[0]);
> +			break;
> +		}
> +	} else {
> +		if (data->flags == MMC_DATA_READ) {
> +			dev_dbg(host->dev, "%s     : DATA READ, %x blocks, bsize = 0x%X\n", __func__,
> +			      data->blocks, data->blocksize);
> +			r1 = mmc_spi_readdata(host, data->dest,
> +				data->blocks, data->blocksize);
> +		} else if  (data->flags == MMC_DATA_WRITE) {
> +			dev_dbg(host->dev, "%s     : DATA WRITE, %x blocks, bsize = 0x%X\n", __func__,
> +			      data->blocks, data->blocksize);
> +			r1 = mmc_spi_writedata(host, data->src,
> +				data->blocks, data->blocksize,
> +				(cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK));
> +		}
> +		if (r1 & R1_SPI_COM_CRC)
> +			ret = -ECOMM;
> +		else if (r1) 
> +			ret = -ETIME;
> +	}
> +
> +done:
> +	mmc_cs_off(host);
> +	return ret;
> +
> +return  0;
> +
> +}
> +
> +static void mmc_spi_set_ios(struct mci_host *mci, struct device_d *mci_dev,
> +			unsigned bus_width, unsigned clock)
> +{
> +	struct mmc_spi_host	*host = to_spi_host(mci);
> +
> +	spi_setup(host->spi);
> +}
> +
> +static int mmc_spi_init(struct mci_host *mci, struct device_d *mci_dev)
> +{
> +	struct mmc_spi_host	*host = to_spi_host(mci);
> +	mmc_spi_readbytes(host, 10, NULL);
> +
> +	/*
> +	 * Do a burst with chipselect active-high.  We need to do this to
> +	 * meet the requirement of 74 clock cycles with both chipselect
> +	 * and CMD (MOSI) high before CMD0 ... after the card has been
> +	 * powered up to Vdd(min), and so is ready to take commands.
> +	 *
> +	 * Some cards are particularly needy of this (e.g. Viking "SD256")
> +	 * while most others don't seem to care.
> +	 *
> +	 * Note that this is one of the places MMC/SD plays games with the
> +	 * SPI protocol.  Another is that when chipselect is released while
> +	 * the card returns BUSY status, the clock must issue several cycles
> +	 * with chipselect high before the card will stop driving its output.
> +	 */
> +
> +	host->spi->mode |= SPI_CS_HIGH;
> +	if (spi_setup(host->spi) != 0) {
> +		/* Just warn; most cards work without it. */
> +		dev_warn(&host->spi->dev,
> +				"can't change chip-select polarity\n");
> +		host->spi->mode &= ~SPI_CS_HIGH;
> +	} else {
> +		mmc_spi_readbytes(host, 18, NULL);
> +
> +		host->spi->mode &= ~SPI_CS_HIGH;
> +		if (spi_setup(host->spi) != 0) {
> +			/* Wot, we can't get the same setup we had before? */
> +			dev_err(&host->spi->dev,
> +					"can't restore chip-select polarity\n");
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static int spi_mci_probe(struct device_d *dev)
> +{
> +	struct spi_device	*spi = (struct spi_device *)dev->type_data;
> +	struct mmc_spi_host	*host;
> +	void			*ones;
> +
> +	host = xzalloc(sizeof(*host));
> +	host->mci.send_cmd = mmc_spi_request;
> +	host->mci.set_ios = mmc_spi_set_ios;
> +	host->mci.init = mmc_spi_init;
> +
> +	host->dev = dev;
> +	host->spi = spi;
> +	dev->priv = host;
> +
> +	ones = xmalloc(MMC_SPI_BLOCKSIZE);
> +	memset(ones, 0xff, MMC_SPI_BLOCKSIZE);
> +
> +	host->ones = ones;
> +
> +	spi_message_init(&host->m_tx);
> +	spi_message_init(&host->m_rx);
> +
> +	spi_message_add_tail(&host->t_tx, &host->m_tx);
> +	spi_message_add_tail(&host->t_rx, &host->m_rx);
> +
> +	host->t_rx.tx_buf = host->ones;
> +	host->t_rx.cs_change = 1;
> +
> +	host->t_tx.cs_change = 1;
> +
> +	host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
> +	host->mci.host_caps = MMC_CAP_SPI;
> +
> +	mci_register(&host->mci);
> +
> +	return 0;
> +}
> +
> +static struct driver_d spi_mci_driver = {
> +	.name	= "spi_mci",
> +	.probe	= spi_mci_probe,
> +};
> +
> +static int spi_mci_init_driver(void)
> +{
> +	register_driver(&spi_mci_driver);
> +	return 0;
> +}
> +
> +device_initcall(spi_mci_init_driver);
> diff --git a/include/mci.h b/include/mci.h
> index 69cffe8..ed54e14 100644
> --- a/include/mci.h
> +++ b/include/mci.h
> @@ -49,6 +49,7 @@
>  
>  #define MMC_MODE_HS		0x001
>  #define MMC_MODE_HS_52MHz	0x010
> +#define MMC_CAP_SPI		0x020
>  #define MMC_MODE_4BIT		0x100
>  #define MMC_MODE_8BIT		0x200
>  
> @@ -56,6 +57,8 @@
>  
>  #define IS_SD(x) (x->version & SD_VERSION_SD)
>  
> +#define mmc_host_is_spi(host)	((host)->host_caps & MMC_CAP_SPI)

You could lower the impact of spimmc on non spimmc enabled builds
a bit by doing:

#ifdef CONFIG_MCI_SPI
#define mmc_host_is_spi(host)		((host)->host_caps & MMC_CAP_SPI)
#else
#define mmc_host_is_spi(host)		0
#endif

Sascha

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

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

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

* Re: [PATCH 3/4] nios2: Include asm/unaligned.h
  2011-11-23 21:12 ` [PATCH 3/4] nios2: Include asm/unaligned.h franck.jullien
@ 2011-11-24  9:36   ` Sascha Hauer
  0 siblings, 0 replies; 7+ messages in thread
From: Sascha Hauer @ 2011-11-24  9:36 UTC (permalink / raw)
  To: franck.jullien; +Cc: barebox

On Wed, Nov 23, 2011 at 10:12:27PM +0100, franck.jullien@gmail.com wrote:
> From: Franck Jullien <franck.jullien@gmail.com>

Applied this one to master.

Sascha

> 
> drivers/ata/disk_drive.c needs it....
> 
> Signed-off-by: Franck Jullien <franck.jullien@gmail.com>
> ---
>  arch/nios2/include/asm/unaligned.h |   15 +++++++++++++++
>  1 files changed, 15 insertions(+), 0 deletions(-)
>  create mode 100644 arch/nios2/include/asm/unaligned.h
> 
> diff --git a/arch/nios2/include/asm/unaligned.h b/arch/nios2/include/asm/unaligned.h
> new file mode 100644
> index 0000000..7615e8a
> --- /dev/null
> +++ b/arch/nios2/include/asm/unaligned.h
> @@ -0,0 +1,15 @@
> +#ifndef _ASM_NIOS_UNALIGNED_H
> +#define _ASM_NIOS_UNALIGNED_H
> +
> +#include <linux/unaligned/le_byteshift.h>
> +#include <linux/unaligned/be_byteshift.h>
> +#include <linux/unaligned/generic.h>
> +
> +/*
> + * Select endianness
> + */
> +
> +#define get_unaligned	__get_unaligned_le
> +#define put_unaligned	__put_unaligned_le
> +
> +#endif /* _ASM_NIOS_UNALIGNED_H */
> -- 
> 1.7.7
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

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

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

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

end of thread, other threads:[~2011-11-24  9:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-23 21:12 [PATCH 0/4] Add MCI over SPI support franck.jullien
2011-11-23 21:12 ` [PATCH 1/4] crypto: Add crc7 function franck.jullien
2011-11-23 21:12 ` [PATCH 2/4] mci: Add MCI over SPI support franck.jullien
2011-11-24  9:17   ` Sascha Hauer
2011-11-23 21:12 ` [PATCH 3/4] nios2: Include asm/unaligned.h franck.jullien
2011-11-24  9:36   ` Sascha Hauer
2011-11-23 21:12 ` [PATCH 4/4] spi/altera_spi: Add cs_change support franck.jullien

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