]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
COMMON: Implement common bounce buffer
authorMarek Vasut <marex@denx.de>
Sun, 26 Aug 2012 15:19:06 +0000 (15:19 +0000)
committerAndy Fleming <afleming@freescale.com>
Mon, 22 Oct 2012 07:53:35 +0000 (02:53 -0500)
Implement common bounce buffer to be used on a less capable hardware.
That includes hardware that can not do DMA from any address or such.

Signed-off-by: Marek Vasut <marex@denx.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: Andy Fleming <afleming@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
common/Makefile
common/bouncebuf.c [new file with mode: 0644]
include/bouncebuf.h [new file with mode: 0644]

index fdfead79c27b952f4cde380e201c95ae85a7363c..2e3b22311d4061c53680f54d9b8b430e83e9c958 100644 (file)
@@ -204,6 +204,7 @@ COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_common.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += env_nowhere.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o
 endif
+COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += image.o
diff --git a/common/bouncebuf.c b/common/bouncebuf.c
new file mode 100644 (file)
index 0000000..4f827f8
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Generic bounce buffer implementation
+ *
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <malloc.h>
+#include <errno.h>
+#include <bouncebuf.h>
+
+static int addr_aligned(void *data, size_t len)
+{
+       const ulong align_mask = ARCH_DMA_MINALIGN - 1;
+
+       /* Check if start is aligned */
+       if ((ulong)data & align_mask) {
+               debug("Unaligned start address %p\n", data);
+               return 0;
+       }
+
+       data += len;
+
+       /* Check if end is aligned */
+       if ((ulong)data & align_mask) {
+               debug("Unaligned end address %p\n", data);
+               return 0;
+       }
+
+       /* Aligned */
+       return 1;
+}
+
+int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags)
+{
+       void *tmp;
+       size_t alen;
+
+       if (addr_aligned(*data, len)) {
+               *backup = NULL;
+               return 0;
+       }
+
+       alen = roundup(len, ARCH_DMA_MINALIGN);
+       tmp = memalign(ARCH_DMA_MINALIGN, alen);
+
+       if (!tmp)
+               return -ENOMEM;
+
+       if (flags & GEN_BB_READ)
+               memcpy(tmp, *data, len);
+
+       *backup = *data;
+       *data = tmp;
+
+       return 0;
+}
+
+int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags)
+{
+       void *tmp = *data;
+
+       /* The buffer was already aligned, since "backup" is NULL. */
+       if (!*backup)
+               return 0;
+
+       if (flags & GEN_BB_WRITE)
+               memcpy(*backup, *data, len);
+
+       *data = *backup;
+       free(tmp);
+
+       return 0;
+}
diff --git a/include/bouncebuf.h b/include/bouncebuf.h
new file mode 100644 (file)
index 0000000..31021c5
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Generic bounce buffer implementation
+ *
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#ifndef __INCLUDE_BOUNCEBUF_H__
+#define __INCLUDE_BOUNCEBUF_H__
+
+/*
+ * GEN_BB_READ -- Data are read from the buffer eg. by DMA hardware.
+ * The source buffer is copied into the bounce buffer (if unaligned, otherwise
+ * the source buffer is used directly) upon start() call, then the operation
+ * requiring the aligned transfer happens, then the bounce buffer is lost upon
+ * stop() call.
+ */
+#define GEN_BB_READ    (1 << 0)
+/*
+ * GEN_BB_WRITE -- Data are written into the buffer eg. by DMA hardware.
+ * The source buffer starts in an undefined state upon start() call, then the
+ * operation requiring the aligned transfer happens, then the bounce buffer is
+ * copied into the destination buffer (if unaligned, otherwise destination
+ * buffer is used directly) upon stop() call.
+ */
+#define GEN_BB_WRITE   (1 << 1)
+/*
+ * GEN_BB_RW -- Data are read and written into the buffer eg. by DMA hardware.
+ * The source buffer is copied into the bounce buffer (if unaligned, otherwise
+ * the source buffer is used directly) upon start() call, then the  operation
+ * requiring the aligned transfer happens, then the bounce buffer is  copied
+ * into the destination buffer (if unaligned, otherwise destination buffer is
+ * used directly) upon stop() call.
+ */
+#define GEN_BB_RW      (GEN_BB_READ | GEN_BB_WRITE)
+
+#ifdef CONFIG_BOUNCE_BUFFER
+/**
+ * bounce_buffer_start() -- Start the bounce buffer session
+ * data:       pointer to buffer to be aligned
+ * len:                length of the buffer
+ * backup:     pointer to backup buffer (the original value is stored here if
+ *              needed
+ * flags:      flags describing the transaction, see above.
+ */
+int bounce_buffer_start(void **data, size_t len, void **backup, uint8_t flags);
+/**
+ * bounce_buffer_stop() -- Finish the bounce buffer session
+ * data:       pointer to buffer that was aligned
+ * len:                length of the buffer
+ * backup:     pointer to backup buffer (the original value is stored here if
+ *              needed
+ * flags:      flags describing the transaction, see above.
+ */
+int bounce_buffer_stop(void **data, size_t len, void **backup, uint8_t flags);
+#else
+static inline int bounce_buffer_start(void **data, size_t len, void **backup,
+                                       uint8_t flags)
+{
+       return 0;
+}
+
+static inline int bounce_buffer_stop(void **data, size_t len, void **backup,
+                                       uint8_t flags)
+{
+       return 0;
+}
+#endif
+
+#endif