mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 5/5] fs: squashfs: append linux rootarg for ubi volume
From: Enrico Jorns @ 2016-10-04 10:10 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Jorns
In-Reply-To: <20161004101048.12970-1-ejo@pengutronix.de>

If squashfs runs from an ubi volume, append appropriate root kernel
options.

Note that ubiblock support is required in the kernel for that.

Signed-off-by: Enrico Jorns <ejo@pengutronix.de>
---
 fs/squashfs/squashfs.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/fs/squashfs/squashfs.c b/fs/squashfs/squashfs.c
index 6d04681..c4d0bac 100644
--- a/fs/squashfs/squashfs.c
+++ b/fs/squashfs/squashfs.c
@@ -9,12 +9,16 @@
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/pagemap.h>
+#include <linux/mtd/ubi.h>
+#include <linux/mtd/mtd.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
 #include "squashfs_fs_i.h"
 #include "squashfs.h"
 
+struct ubi_volume_desc;
+
 char *squashfs_devread(struct squashfs_sb_info *fs, int byte_offset,
 		int byte_len)
 {
@@ -108,6 +112,31 @@ static struct inode *squashfs_findfile(struct super_block *sb,
 	return NULL;
 }
 
+void squashfs_set_rootarg(struct squashfs_priv *priv, struct fs_device_d *fsdev)
+{
+	struct ubi_volume_desc *ubi_vol;
+	struct ubi_volume_info vi = {};
+	struct ubi_device_info di = {};
+	struct mtd_info *mtd;
+	char *str;
+
+	ubi_vol = ubi_open_volume_cdev(fsdev->cdev, UBI_READONLY);
+
+	if (IS_ERR(ubi_vol))
+		return;
+
+	ubi_get_volume_info(ubi_vol, &vi);
+	ubi_get_device_info(vi.ubi_num, &di);
+	mtd = di.mtd;
+
+	str = basprintf("root=/dev/ubiblock%d_%d ubi.mtd=%s ubi.block=%d,%d rootfstype=squashfs",
+			vi.ubi_num, vi.vol_id, mtd->cdev.partname, vi.ubi_num, vi.vol_id);
+
+	fsdev_set_linux_rootarg(fsdev, str);
+
+	free(str);
+}
+
 static int squashfs_probe(struct device_d *dev)
 {
 	struct fs_device_d *fsdev;
@@ -130,6 +159,8 @@ static int squashfs_probe(struct device_d *dev)
 		goto err_out;
 	}
 
+	squashfs_set_rootarg(priv, fsdev);
+
 	return 0;
 
 err_out:
-- 
2.9.3


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

^ permalink raw reply related

* [PATCH 3/5] fs: squashfs: port zlib compression support from kernel
From: Enrico Jorns @ 2016-10-04 10:10 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Jorns
In-Reply-To: <20161004101048.12970-1-ejo@pengutronix.de>

As this is the default compression method for squashfs, make this the
default in kconfig selection, too

Signed-off-by: Enrico Jorns <ejo@pengutronix.de>
---
 fs/squashfs/Kconfig        |  20 ++++++-
 fs/squashfs/Makefile       |   1 +
 fs/squashfs/zlib_wrapper.c | 132 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 fs/squashfs/zlib_wrapper.c

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index d2de168..1cb1ac5 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -17,6 +17,19 @@ menuconfig FS_SQUASHFS
 	  embedded systems where low overhead is needed.  Further information
 	  and tools are available from http://squashfs.sourceforge.net.
 
+config SQUASHFS_ZLIB
+	bool "Include support for ZLIB compressed file systems"
+	depends on FS_SQUASHFS
+	select ZLIB
+	default y
+	help
+	  ZLIB compression is the standard compression used by Squashfs
+	  file systems.  It offers a good trade-off between compression
+	  achieved and the amount of CPU time and memory necessary to
+	  compress and decompress.
+
+	  If unsure, say Y.
+
 config SQUASHFS_LZ4
 	bool "Include support for LZ4 compressed file systems"
 	depends on FS_SQUASHFS
@@ -30,9 +43,10 @@ config SQUASHFS_LZ4
 	  LZ4 is not the standard compression used in Squashfs and so most
 	  file systems will be readable without selecting this option.
 
+	  If unsure, say N.
+
 config SQUASHFS_LZO
 	bool "Include support for LZO compressed file systems"
-	default y
 	depends on FS_SQUASHFS
 	select LZO_DECOMPRESS
 	help
@@ -44,6 +58,8 @@ config SQUASHFS_LZO
 	  LZO is not the standard compression used in Squashfs and so most
 	  file systems will be readable without selecting this option.
 
+	  If unsure, say N.
+
 config SQUASHFS_XZ
 	bool "Include support for XZ compressed file systems"
 	default y
@@ -57,3 +73,5 @@ config SQUASHFS_XZ
 
 	  XZ is not the standard compression used in Squashfs and so most
 	  file systems will be readable without selecting this option.
+
+	  If unsure, say N.
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index 8590b09..7976e3f 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -13,3 +13,4 @@ obj-y	+= super.o
 obj-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
 obj-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
 obj-$(CONFIG_SQUASHFS_LZ4) += lz4_wrapper.o
+obj-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
new file mode 100644
index 0000000..f422515
--- /dev/null
+++ b/fs/squashfs/zlib_wrapper.c
@@ -0,0 +1,132 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ * Phillip Lougher <phillip@squashfs.org.uk>
+ *
+ * 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,
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * zlib_wrapper.c
+ */
+
+
+#include <linux/mutex.h>
+#include <linux/zlib.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs.h"
+#include "decompressor.h"
+#include "page_actor.h"
+
+static void *zlib_init(struct squashfs_sb_info *dummy, void *buff)
+{
+	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+	if (stream == NULL)
+		goto failed;
+	stream->workspace = vmalloc(zlib_inflate_workspacesize());
+	if (stream->workspace == NULL)
+		goto failed;
+
+	return stream;
+
+failed:
+	ERROR("Failed to allocate zlib workspace\n");
+	kfree(stream);
+	return ERR_PTR(-ENOMEM);
+}
+
+
+static void zlib_free(void *strm)
+{
+	z_stream *stream = strm;
+
+	if (stream)
+		vfree(stream->workspace);
+	kfree(stream);
+}
+
+
+static int zlib_uncompress(struct squashfs_sb_info *msblk, void *strm,
+	char **bh, int b, int offset, int length,
+	struct squashfs_page_actor *output)
+{
+	int zlib_err, zlib_init = 0, k = 0;
+	z_stream *stream = strm;
+
+	stream->avail_out = PAGE_CACHE_SIZE;
+	stream->next_out = squashfs_first_page(output);
+	stream->avail_in = 0;
+
+	do {
+		if (stream->avail_in == 0 && k < b) {
+			int avail = min(length, msblk->devblksize - offset);
+			length -= avail;
+			stream->next_in = bh[k] + offset;
+			stream->avail_in = avail;
+			offset = 0;
+		}
+
+		if (stream->avail_out == 0) {
+			stream->next_out = squashfs_next_page(output);
+			if (stream->next_out != NULL)
+				stream->avail_out = PAGE_CACHE_SIZE;
+		}
+
+		if (!zlib_init) {
+			zlib_err = zlib_inflateInit(stream);
+			if (zlib_err != Z_OK) {
+				squashfs_finish_page(output);
+				goto out;
+			}
+			zlib_init = 1;
+		}
+
+		zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
+
+		if (stream->avail_in == 0 && k < b)
+			kfree(bh[k++]);
+	} while (zlib_err == Z_OK);
+
+	squashfs_finish_page(output);
+
+	if (zlib_err != Z_STREAM_END)
+		goto out;
+
+	zlib_err = zlib_inflateEnd(stream);
+	if (zlib_err != Z_OK)
+		goto out;
+
+	if (k < b)
+		goto out;
+
+	return stream->total_out;
+
+out:
+	for (; k < b; k++)
+		kfree(bh[k]);
+
+	return -EIO;
+}
+
+const struct squashfs_decompressor squashfs_zlib_comp_ops = {
+	.init = zlib_init,
+	.free = zlib_free,
+	.decompress = zlib_uncompress,
+	.id = ZLIB_COMPRESSION,
+	.name = "zlib",
+	.supported = 1
+};
+
-- 
2.9.3


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

^ permalink raw reply related

* [PATCH 4/5] Add filetype and detection for squashfs images
From: Enrico Jorns @ 2016-10-04 10:10 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Jorns
In-Reply-To: <20161004101048.12970-1-ejo@pengutronix.de>

This adds `filetype_squashfs` to the list of known filetypes and adds a
detection for squashfs files to file_detect_type(). This currently
matches on the `hsqs` start sequence of an image file.

Additionally, the newly introduced filetype is registered as the type of
the squashfs_driver which allows, for example, to mount squashfs without
the need to specify a type parameter.

This changes enable booting a squashfs with the simple `boot` command
pointing to the location (device) that holds the squashfs.

Note that booting with blspec is limited as the current squashfs driver
is not capable of handling symbolic links.

Signed-off-by: Enrico Jorns <ejo@pengutronix.de>
---
 common/filetype.c      | 4 ++++
 fs/squashfs/squashfs.c | 1 +
 include/filetype.h     | 1 +
 3 files changed, 6 insertions(+)

diff --git a/common/filetype.c b/common/filetype.c
index 4728f87..8d72933 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -40,6 +40,7 @@ static const struct filetype_str filetype_str[] = {
 	[filetype_uimage] = { "U-Boot uImage", "u-boot" },
 	[filetype_ubi] = { "UBI image", "ubi" },
 	[filetype_jffs2] = { "JFFS2 image", "jffs2" },
+	[filetype_squashfs] = { "Squashfs image", "squashfs" },
 	[filetype_gzip] = { "GZIP compressed", "gzip" },
 	[filetype_bzip2] = { "BZIP2 compressed", "bzip2" },
 	[filetype_oftree] = { "open firmware Device Tree flattened Binary", "dtb" },
@@ -278,6 +279,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
 	if (buf8[0] == 0xfd && buf8[1] == 0x37 && buf8[2] == 0x7a &&
 			buf8[3] == 0x58 && buf8[4] == 0x5a && buf8[5] == 0x00)
 		return filetype_xz_compressed;
+	if (buf8[0] == 'h' && buf8[1] == 's' && buf8[2] == 'q' &&
+			buf8[3] == 's')
+		return filetype_squashfs;
 	if (buf[0] == be32_to_cpu(0xd00dfeed))
 		return filetype_oftree;
 	if (strncmp(buf8, "ANDROID!", 8) == 0)
diff --git a/fs/squashfs/squashfs.c b/fs/squashfs/squashfs.c
index d00dee6..6d04681 100644
--- a/fs/squashfs/squashfs.c
+++ b/fs/squashfs/squashfs.c
@@ -353,6 +353,7 @@ static struct fs_driver_d squashfs_driver = {
 	.readdir	= squashfs_readdir,
 	.closedir	= squashfs_closedir,
 	.stat		= squashfs_stat,
+	.type		= filetype_squashfs,
 	.drv = {
 		.probe = squashfs_probe,
 		.remove = squashfs_remove,
diff --git a/include/filetype.h b/include/filetype.h
index cde73c1..65bd6ef 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -16,6 +16,7 @@ enum filetype {
 	filetype_uimage,
 	filetype_ubi,
 	filetype_jffs2,
+	filetype_squashfs,
 	filetype_gzip,
 	filetype_bzip2,
 	filetype_oftree,
-- 
2.9.3


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

^ permalink raw reply related

* [PATCH 1/5] fs: squashfs: port lzo compression support from kernel
From: Enrico Jorns @ 2016-10-04 10:10 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Jorns
In-Reply-To: <20161004101048.12970-1-ejo@pengutronix.de>

This ports lzo_wrapper from kernel code and adds some minimal adaptions
to make squashfs lzo compression work in barebox.

Signed-off-by: Enrico Jorns <ejo@pengutronix.de>
---
 fs/squashfs/Kconfig       |  14 +++++
 fs/squashfs/Makefile      |   1 +
 fs/squashfs/lzo_wrapper.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/lzo.h       |  47 +++++++++++++++++
 4 files changed, 190 insertions(+)
 create mode 100644 fs/squashfs/lzo_wrapper.c
 create mode 100644 include/linux/lzo.h

diff --git a/fs/squashfs/Kconfig b/fs/squashfs/Kconfig
index dc25d93..d8ee554 100644
--- a/fs/squashfs/Kconfig
+++ b/fs/squashfs/Kconfig
@@ -17,6 +17,20 @@ menuconfig FS_SQUASHFS
 	  embedded systems where low overhead is needed.  Further information
 	  and tools are available from http://squashfs.sourceforge.net.
 
+config SQUASHFS_LZO
+	bool "Include support for LZO compressed file systems"
+	default y
+	depends on FS_SQUASHFS
+	select LZO_DECOMPRESS
+	help
+	  Saying Y here includes support for reading Squashfs file systems
+	  compressed with LZO compression.  LZO compression is mainly
+	  aimed at embedded systems with slower CPUs where the overheads
+	  of zlib are too high.
+
+	  LZO is not the standard compression used in Squashfs and so most
+	  file systems will be readable without selecting this option.
+
 config SQUASHFS_XZ
 	bool "Include support for XZ compressed file systems"
 	default y
diff --git a/fs/squashfs/Makefile b/fs/squashfs/Makefile
index c0d024c..447e15e 100644
--- a/fs/squashfs/Makefile
+++ b/fs/squashfs/Makefile
@@ -11,3 +11,4 @@ obj-y	+= inode.o
 obj-y	+= namei.o
 obj-y	+= super.o
 obj-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
+obj-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
diff --git a/fs/squashfs/lzo_wrapper.c b/fs/squashfs/lzo_wrapper.c
new file mode 100644
index 0000000..b457955
--- /dev/null
+++ b/fs/squashfs/lzo_wrapper.c
@@ -0,0 +1,128 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2010 LG Electronics
+ * Chan Jeong <chan.jeong@lge.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,
+ * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * lzo_wrapper.c
+ */
+
+#include <linux/mutex.h>
+#include <linux/lzo.h>
+#include <types.h>
+
+#include "squashfs_fs.h"
+#include "squashfs_fs_sb.h"
+#include "squashfs.h"
+#include "decompressor.h"
+#include "page_actor.h"
+
+struct squashfs_lzo {
+	void	*input;
+	void	*output;
+};
+
+static void *lzo_init(struct squashfs_sb_info *msblk, void *buff)
+{
+	int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE);
+
+	struct squashfs_lzo *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (stream == NULL)
+		goto failed;
+	stream->input = vmalloc(block_size);
+	if (stream->input == NULL)
+		goto failed;
+	stream->output = vmalloc(block_size);
+	if (stream->output == NULL)
+		goto failed2;
+
+	return stream;
+
+failed2:
+	vfree(stream->input);
+failed:
+	ERROR("Failed to allocate lzo workspace\n");
+	kfree(stream);
+	return ERR_PTR(-ENOMEM);
+}
+
+
+static void lzo_free(void *strm)
+{
+	struct squashfs_lzo *stream = strm;
+
+	if (stream) {
+		vfree(stream->input);
+		vfree(stream->output);
+	}
+	kfree(stream);
+}
+
+
+static int lzo_uncompress(struct squashfs_sb_info *msblk, void *strm,
+	char **bh, int b, int offset, int length,
+	struct squashfs_page_actor *output)
+{
+	struct squashfs_lzo *stream = strm;
+	void *buff = stream->input, *data;
+	int avail, i, bytes = length, res;
+	size_t out_len = output->length;
+
+	for (i = 0; i < b; i++) {
+		avail = min(bytes, msblk->devblksize - offset);
+		memcpy(buff, bh[i] + offset, avail);
+		buff += avail;
+		bytes -= avail;
+		offset = 0;
+		kfree(bh[i]);
+	}
+
+	res = lzo1x_decompress_safe(stream->input, (size_t)length,
+					stream->output, &out_len);
+	if (res != LZO_E_OK)
+		goto failed;
+
+	res = bytes = (int)out_len;
+	data = squashfs_first_page(output);
+	buff = stream->output;
+	while (data) {
+		if (bytes <= PAGE_CACHE_SIZE) {
+			memcpy(data, buff, bytes);
+			break;
+		} else {
+			memcpy(data, buff, PAGE_CACHE_SIZE);
+			buff += PAGE_CACHE_SIZE;
+			bytes -= PAGE_CACHE_SIZE;
+			data = squashfs_next_page(output);
+		}
+	}
+	squashfs_finish_page(output);
+
+	return res;
+
+failed:
+	return -EIO;
+}
+
+const struct squashfs_decompressor squashfs_lzo_comp_ops = {
+	.init = lzo_init,
+	.free = lzo_free,
+	.decompress = lzo_uncompress,
+	.id = LZO_COMPRESSION,
+	.name = "lzo",
+	.supported = 1
+};
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
new file mode 100644
index 0000000..ae52d79
--- /dev/null
+++ b/include/linux/lzo.h
@@ -0,0 +1,47 @@
+#ifndef __LZO_H__
+#define __LZO_H__
+/*
+ *  LZO Public Kernel Interface
+ *  A mini subset of the LZO real-time data compression library
+ *
+ *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ *  The full LZO package can be found at:
+ *  http://www.oberhumer.com/opensource/lzo/
+ *
+ *  Changed for Linux kernel use by:
+ *  Nitin Gupta <nitingupta910@gmail.com>
+ *  Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <types.h>
+
+#define LZO1X_1_MEM_COMPRESS	(8192 * sizeof(unsigned short))
+#define LZO1X_MEM_COMPRESS	LZO1X_1_MEM_COMPRESS
+
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
+
+/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
+int lzo1x_1_compress(const unsigned char *src, size_t src_len,
+		     unsigned char *dst, size_t *dst_len, void *wrkmem);
+
+/* safe decompression with overrun testing */
+int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
+			  unsigned char *dst, size_t *dst_len);
+
+/*
+ * Return values (< 0 = Error)
+ */
+#define LZO_E_OK			0
+#define LZO_E_ERROR			(-1)
+#define LZO_E_OUT_OF_MEMORY		(-2)
+#define LZO_E_NOT_COMPRESSIBLE		(-3)
+#define LZO_E_INPUT_OVERRUN		(-4)
+#define LZO_E_OUTPUT_OVERRUN		(-5)
+#define LZO_E_LOOKBEHIND_OVERRUN	(-6)
+#define LZO_E_EOF_NOT_FOUND		(-7)
+#define LZO_E_INPUT_NOT_CONSUMED	(-8)
+#define LZO_E_NOT_YET_IMPLEMENTED	(-9)
+#define LZO_E_INVALID_ARGUMENT		(-10)
+
+#endif
-- 
2.9.3


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

^ permalink raw reply related

* [PATCH 0/5] Extend squashfs support
From: Enrico Jorns @ 2016-10-04 10:10 UTC (permalink / raw)
  To: barebox; +Cc: Enrico Jorns

This adds missing compression methods: lz4, lzo, zlib

It also creates missing links in driver and detection code in order to allow
using squashfs with those nice barebox autodetection features and especially
for bootspec booting.

The appendroot mechanism currently (only) supports booting form an ubi volume.

Enrico Jorns (5):
  fs: squashfs: port lzo compression support from kernel
  fs: squashfs: port lz4 compression support from kernel
  fs: squashfs: port zlib compression support from kernel
  Add filetype and detection for squashfs images
  fs: squashfs: append linux rootarg for ubi volume

 common/filetype.c          |   4 ++
 fs/squashfs/Kconfig        |  45 +++++++++++++++
 fs/squashfs/Makefile       |   3 +
 fs/squashfs/lz4_wrapper.c  | 140 +++++++++++++++++++++++++++++++++++++++++++++
 fs/squashfs/lzo_wrapper.c  | 128 +++++++++++++++++++++++++++++++++++++++++
 fs/squashfs/squashfs.c     |  32 +++++++++++
 fs/squashfs/zlib_wrapper.c | 132 ++++++++++++++++++++++++++++++++++++++++++
 include/filetype.h         |   1 +
 include/linux/lzo.h        |  47 +++++++++++++++
 9 files changed, 532 insertions(+)
 create mode 100644 fs/squashfs/lz4_wrapper.c
 create mode 100644 fs/squashfs/lzo_wrapper.c
 create mode 100644 fs/squashfs/zlib_wrapper.c
 create mode 100644 include/linux/lzo.h

-- 
2.9.3


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

^ permalink raw reply

* Re: [PATCH] pinctrl: mvebu: armada-370 fix gpio name for mpp63
From: Sascha Hauer @ 2016-10-04  7:29 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: barebox
In-Reply-To: <20161004070633.19328-1-u.kleine-koenig@pengutronix.de>

On Tue, Oct 04, 2016 at 09:06:33AM +0200, Uwe Kleine-König wrote:
> It was found that pin 63 also works as input and so the respective function
> is renamed from "gpo" to "gpio". The respective commit in Linux is:
> 
> 	a526973e0291 ("pinctrl: mvebu: Fix mapping of pin 63 (gpo -> gpio)")
> 
> which appeared in v4.1-rc3. The devicetrees are fixed accordingly since
> commit
> 
> 	ce5cad51f381 ("ARM: dts: armada-370: Update the mpp63 function in the device tree on Armada 370")
> 
> which appeared in v4.6-rc1.
> 
> This fixes a runtime warning on the affected machines
> (globalscale-mirabox and netgear-rn104) and makes the pin functional
> again.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pinctrl/mvebu/armada-370.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

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

* Re: [PATCH 14/20] i.MX: i2c-imx: Add Vybrid support
From: Sascha Hauer @ 2016-10-04  7:20 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-15-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:51AM -0700, Andrey Smirnov wrote:
> Vybrid flavour of the I2C controller requires some additional quirks on
> part of the driver. This commit ports those quirks code from analogous
> Linux kernel driver.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  drivers/i2c/busses/i2c-imx.c | 215 ++++++++++++++++++++++++++++++++-----------
>  1 file changed, 160 insertions(+), 55 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index e407896..dbc76c2 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -43,6 +43,7 @@
> +static inline void fsl_i2c_write_reg(unsigned int val,
> +				     struct fsl_i2c_struct *i2c_fsl,
> +				     unsigned int reg)
> +{
> +	writeb(val, i2c_fsl->base + (reg << i2c_fsl->hwdata->regshift));
> +}
> +
> +static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c_struct *i2c_fsl,
> +					     unsigned int reg)
> +{
> +	return readb(i2c_fsl->base + (reg << i2c_fsl->hwdata->regshift));
> +}

Can we have the introduction of the read/write accessor functions as a
separate patch (with regshift hardcoded to 0)? This would make reviewing
the rest easier.

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

* Re: [PATCH 13/20] i.MX: Add 'lpuart' serial driver
From: Sascha Hauer @ 2016-10-04  7:13 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-14-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:50AM -0700, Andrey Smirnov wrote:
> Add 'lpuart' serial driver, based on analogous driver from U-Boot
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  drivers/serial/Kconfig         |   4 +
>  drivers/serial/Makefile        |   1 +
>  drivers/serial/serial_lpuart.c | 217 +++++++++++++++++++++++++++++++++++++++++
>  include/serial/lpuart.h        |  28 ++++--
>  4 files changed, 244 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/serial/serial_lpuart.c
> 
> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
> index 146bf1e..02e869a 100644
> --- a/drivers/serial/Kconfig
> +++ b/drivers/serial/Kconfig
> @@ -137,4 +137,8 @@ config DRIVER_SERIAL_DIGIC
>  	bool "Canon DIGIC serial driver"
>  	depends on ARCH_DIGIC
>  
> +config DRIVER_SERIAL_LPUART
> +	depends on ARCH_IMX
> +	bool "LPUART serial driver"
> +
>  endmenu
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index 189e777..7d1bae1 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -20,3 +20,4 @@ obj-$(CONFIG_DRIVER_SERIAL_AUART)		+= serial_auart.o
>  obj-$(CONFIG_DRIVER_SERIAL_CADENCE)		+= serial_cadence.o
>  obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO)		+= efi-stdio.o
>  obj-$(CONFIG_DRIVER_SERIAL_DIGIC)		+= serial_digic.o
> +obj-$(CONFIG_DRIVER_SERIAL_LPUART)		+= serial_lpuart.o
> diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
> new file mode 100644
> index 0000000..52fb6d3
> --- /dev/null
> +++ b/drivers/serial/serial_lpuart.c
> @@ -0,0 +1,217 @@
> +/*
> + * Copyright (c) 2016 Zodiac Inflight Innovation
> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
> + *
> + * Based on analogous driver from U-Boot
> + *
> + * 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 version 2
> + * as published by the Free Software Foundation.
> + *
> + * 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 <common.h>
> +#include <driver.h>
> +#include <init.h>
> +#include <malloc.h>
> +#include <notifier.h>
> +#include <io.h>
> +#include <of.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <serial/lpuart.h>
> +
> +struct lpuart {
> +	struct console_device cdev;
> +	int baudrate;
> +	int dte_mode;
> +	struct notifier_block notify;
> +	struct resource *io;
> +	void __iomem *base;
> +	struct clk *clk;
> +};
> +
> +static struct lpuart *cdev_to_lpuart(struct console_device *cdev)
> +{
> +	return container_of(cdev, struct lpuart, cdev);
> +}
> +
> +static struct lpuart *nb_to_lpuart(struct notifier_block *nb)
> +{
> +	return container_of(nb, struct lpuart, notify);
> +}
> +
> +static void lpuart_enable(struct lpuart *lpuart, bool on)
> +{
> +	u8 ctrl;
> +
> +	ctrl = readb(lpuart->base + UARTCR2);
> +	if (on)
> +		ctrl |= UARTCR2_TE | UARTCR2_RE;
> +	else
> +		ctrl &= ~(UARTCR2_TE | UARTCR2_RE);
> +	writeb(ctrl, lpuart->base + UARTCR2);
> +}
> +
> +static int lpuart_serial_setbaudrate(struct console_device *cdev,
> +				     int baudrate)
> +{
> +	struct lpuart *lpuart = cdev_to_lpuart(cdev);
> +
> +	lpuart_enable(lpuart, false);
> +
> +	lpuart_setbrg(lpuart->base,
> +		      clk_get_rate(lpuart->clk),
> +		      baudrate);
> +
> +	lpuart_enable(lpuart, true);
> +
> +	lpuart->baudrate = baudrate;
> +
> +	return 0;
> +}
> +
> +static int lpuart_serial_getc(struct console_device *cdev)
> +{
> +	bool ready;
> +	struct lpuart *lpuart = cdev_to_lpuart(cdev);
> +
> +	do {
> +		const u8 sr1 = readb(lpuart->base + UARTSR1);
> +		ready = !!(sr1 & (UARTSR1_OR | UARTSR1_RDRF));
> +	} while (!ready);
> +
> +	return readb(lpuart->base + UARTDR);
> +}
> +
> +static void lpuart_serial_putc(struct console_device *cdev, char c)
> +{
> +	lpuart_putc(cdev_to_lpuart(cdev)->base, c);
> +}
> +
> +/* Test whether a character is in the RX buffer */
> +static int lpuart_serial_tstc(struct console_device *cdev)
> +{
> +	return !!readb(cdev_to_lpuart(cdev)->base + UARTRCFIFO);
> +}
> +
> +static void lpuart_serial_flush(struct console_device *cdev)
> +{
> +	bool tx_empty;
> +	struct lpuart *lpuart = cdev_to_lpuart(cdev);
> +
> +	do {
> +		const u8 sr1 = readb(lpuart->base + UARTSR1);
> +		tx_empty = !!(sr1 & UARTSR1_TDRE);
> +	} while (!tx_empty);
> +}
> +
> +static int lpuart_clocksource_clock_change(struct notifier_block *nb,
> +					   unsigned long event, void *data)
> +{
> +	struct lpuart *lpuart = nb_to_lpuart(nb);
> +
> +	return lpuart_serial_setbaudrate(&lpuart->cdev, lpuart->baudrate);
> +}

This doesn't make sense in this form. I introduced this code in the i.MX
uart driver since I had the need to change PLL rates while the uart is
active. When this happens I had to adjust the dividers for the new uart
base clock. The code above doesn't react to base clock changes though,
it takes the old rate stored in lpuart->baudrate.

If you don't have to adjust PLL rates while the uart is active then I
suggest that you just remove this code.

> @@ -225,25 +225,35 @@ static inline void lpuart_setbrg(void __iomem *base,
>  				 unsigned int refclock,
>  				 unsigned int baudrate)
>  {
> +	unsigned int bfra;
>  	u16 sbr;
> +
>  	sbr = (u16) (refclock / (16 * baudrate));
>  
>  	writeb(sbr >> 8,   base + UARTBDH);
>  	writeb(sbr & 0xff, base + UARTBDL);
> +
> +	bfra  = DIV_ROUND_UP(2 * refclock, baudrate) - 32 * sbr;
> +	bfra &= UARTCR4_BRFA_MASK;
> +	writeb(bfra, base + UARTCR4);
>  }
>  
> -static inline void lpuart_setup(void __iomem *base,
> -				unsigned int refclock)
> +static inline void lpuart_setup_with_fifo(void __iomem *base,
> +					  unsigned int refclock,
> +					  unsigned int twfifo)
>  {
> -
>  	/* Disable UART */
>  	writeb(0, base + UARTCR2);
>  	writeb(0, base + UARTMODEM);
>  	writeb(0, base + UARTCR1);
>  
> -	/* Disable FIFOs */
> -	writeb(0, base + UARTPFIFO);
> -	writeb(0, base + UARTTWFIFO);
> +	if (twfifo) {
> +		writeb(UARTPFIFO_TXFE | UARTPFIFO_RXFE, base + UARTPFIFO);
> +		writeb((u8)twfifo, base + UARTTWFIFO);
> +	} else {
> +		writeb(0, base + UARTPFIFO);
> +		writeb(0, base + UARTTWFIFO);
> +	}
>  	writeb(1, base + UARTRWFIFO);
>  	writeb(UARTCFIFO_RXFLUSH | UARTCFIFO_TXFLUSH, base + UARTCFIFO);
>  
> @@ -252,6 +262,12 @@ static inline void lpuart_setup(void __iomem *base,
>  	writeb(UARTCR2_TE | UARTCR2_RE, base + UARTCR2);
>  }
>  
> +static inline void lpuart_setup(void __iomem *base,
> +				unsigned int refclock)
> +{
> +	lpuart_setup_with_fifo(base, refclock, 0x00);
> +}
> +
>  static inline void lpuart_putc(void __iomem *base, int c)
>  {
>  	if (!(readb(base + UARTCR2) & UARTCR2_TE))

This was introduced earlier with this series. No need to change it, just
create it correctly in the first place.

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

* [PATCH] pinctrl: mvebu: armada-370 fix gpio name for mpp63
From: Uwe Kleine-König @ 2016-10-04  7:06 UTC (permalink / raw)
  To: barebox

It was found that pin 63 also works as input and so the respective function
is renamed from "gpo" to "gpio". The respective commit in Linux is:

	a526973e0291 ("pinctrl: mvebu: Fix mapping of pin 63 (gpo -> gpio)")

which appeared in v4.1-rc3. The devicetrees are fixed accordingly since
commit

	ce5cad51f381 ("ARM: dts: armada-370: Update the mpp63 function in the device tree on Armada 370")

which appeared in v4.6-rc1.

This fixes a runtime warning on the affected machines
(globalscale-mirabox and netgear-rn104) and makes the pin functional
again.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pinctrl/mvebu/armada-370.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/mvebu/armada-370.c b/drivers/pinctrl/mvebu/armada-370.c
index 1c79bd62af92..c2c1a0fa6399 100644
--- a/drivers/pinctrl/mvebu/armada-370.c
+++ b/drivers/pinctrl/mvebu/armada-370.c
@@ -362,7 +362,7 @@ static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
 	   MPP_FUNCTION(0x5, "audio", "mclk"),
 	   MPP_FUNCTION(0x6, "uart0", "cts")),
 	MPP_MODE(63, "mpp63", armada_370_mpp_ctrl,
-	   MPP_FUNCTION(0x0, "gpo", NULL),
+	   MPP_FUNCTION(0x0, "gpio", NULL),
 	   MPP_FUNCTION(0x1, "spi0", "sck"),
 	   MPP_FUNCTION(0x2, "tclk", NULL)),
 	MPP_MODE(64, "mpp64", armada_370_mpp_ctrl,
-- 
2.9.3


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

^ permalink raw reply related

* Re: [PATCH 11/20] i.MX: Add VF610 clock tree initialization code
From: Sascha Hauer @ 2016-10-04  6:58 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-12-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:48AM -0700, Andrey Smirnov wrote:
> Based on analogous code from Linux kernel
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  drivers/clk/imx/Makefile    |    1 +
>  drivers/clk/imx/clk-vf610.c | 1224 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 1225 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-vf610.c
> 
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index 0303c0b..2665f49 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -1 +1,2 @@
>  obj-y += clk.o
> +obj-$(CONFIG_ARCH_VF610) += clk-vf610.o
> +static struct clk *clk[VF610_CLK_END];
> +struct clk_onecell_data clk_data;
> +
> +static struct clk * __init vf610_get_fixed_clock(struct device_node *np,
> +						 const char *name)
> +{
> +	struct clk *clk = of_clk_get_by_name(np, name);
> +
> +	/* Backward compatibility if device tree is missing clks assignments */
> +	if (IS_ERR(clk))
> +		clk = imx_obtain_fixed_clock(name, 0);

Ah, that explains it. No, we don't need this since we are compiling the
device trees into barebox and can make sure they are compatible with our
code.

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

* Re: [PATCH 10/20] i.MX: clk: Port imx_check_clocks() and imx_obtain_fixed_clock()
From: Sascha Hauer @ 2016-10-04  6:49 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-11-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:47AM -0700, Andrey Smirnov wrote:
> Port imx_check_clocks() and imx_obtain_fixed_clock() from Linux kernel.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  arch/arm/mach-imx/clk.h  |  4 ++++
>  drivers/clk/Makefile     |  1 +
>  drivers/clk/imx/Makefile |  1 +
>  drivers/clk/imx/clk.c    | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 55 insertions(+)
>  create mode 100644 drivers/clk/imx/Makefile
>  create mode 100644 drivers/clk/imx/clk.c
> 
> diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
> index 35e480f..f96e5d2 100644
> --- a/arch/arm/mach-imx/clk.h
> +++ b/arch/arm/mach-imx/clk.h
> @@ -109,4 +109,8 @@ static inline struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg,
>  struct clk *imx_clk_gate_exclusive(const char *name, const char *parent,
>  		void __iomem *reg, u8 shift, u32 exclusive_mask);
>  
> +void imx_check_clocks(struct clk *clks[], unsigned int count);
> +struct clk * __init imx_obtain_fixed_clock(const char *name, unsigned long rate);
> +
> +
>  #endif /* __IMX_CLK_H */
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 0fe8f1e..6dc82ea 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_ROCKCHIP)	+= rockchip/
>  obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
>  obj-$(CONFIG_CLK_SOCFPGA)	+= socfpga.o
>  obj-$(CONFIG_MACH_MIPS_ATH79)	+= clk-ar933x.o
> +obj-$(CONFIG_COMMON_CLK)	+= imx/
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> new file mode 100644
> index 0000000..0303c0b
> --- /dev/null
> +++ b/drivers/clk/imx/Makefile
> @@ -0,0 +1 @@
> +obj-y += clk.o
> diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
> new file mode 100644
> index 0000000..0357048
> --- /dev/null
> +++ b/drivers/clk/imx/clk.c

We currently have the i.MX clock support in arch/arm/mach-imx/. This may
or may not be changed, but until it is, other i.MX clock support code
should go to arch/arm/mach-imx/ aswell.

> @@ -0,0 +1,49 @@
> +#include <common.h>
> +#include <init.h>
> +#include <driver.h>
> +#include <linux/clk.h>
> +#include <io.h>
> +#include <of.h>
> +#include <linux/clkdev.h>
> +#include <linux/err.h>
> +
> +#include "../../../arch/arm/mach-imx/clk.h"

#include <mach/clk.h>

> +
> +void __init imx_check_clocks(struct clk *clks[], unsigned int count)
> +{
> +	unsigned i;
> +
> +	for (i = 0; i < count; i++)
> +		if (IS_ERR(clks[i]))
> +			pr_err("i.MX clk %u: register failed with %ld\n",
> +			       i, PTR_ERR(clks[i]));
> +}
> +
> +static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
> +{
> +	struct of_phandle_args phandle;
> +	struct clk *clk = ERR_PTR(-ENODEV);
> +	char *path;
> +
> +	path = basprintf("/clocks/%s", name);
> +	if (!path)
> +		return ERR_PTR(-ENOMEM);
> +
> +	phandle.np = of_find_node_by_path(path);
> +	kfree(path);
> +
> +	if (phandle.np)
> +		clk = of_clk_get_from_provider(&phandle);
> +
> +	return clk;
> +}

Do we need this anyway? We already have clk providers for fixed-clock.
Hm, looking further, maybe a later patch explains.

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

* Re: [PATCH 07/20] clk: Port of_clk_set_defautls()
From: Sascha Hauer @ 2016-10-04  6:38 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-8-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:44AM -0700, Andrey Smirnov wrote:
> Port of_clk_set_defautls() from Linux kernel in order to support DT
> configurations that require it (e. g. Vybrid).

s/of_clk_set_defautls/of_clk_set_defaults/ here and in the subject.

> diff --git a/include/linux/clk/clk-conf.h b/include/linux/clk/clk-conf.h
> new file mode 100644
> index 0000000..2c0a39e
> --- /dev/null
> +++ b/include/linux/clk/clk-conf.h
> @@ -0,0 +1,22 @@
> +/*
> + * Copyright (C) 2014 Samsung Electronics Co., Ltd.
> + * Sylwester Nawrocki <s.nawrocki@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/types.h>
> +
> +struct device_node;
> +
> +#if defined(CONFIG_OFTREE) && defined(CONFIG_COMMON_CLK)
> +int of_clk_set_defaults(struct device_node *node, bool clk_supplier);
> +#else
> +static inline int of_clk_set_defaults(struct device_node *node,
> +				      bool clk_supplier)
> +{
> +	return 0;
> +}
> +#endif

We shouldn't need this static inline variant. The caller already exists for OF
enabled builds only.

Sascha

> -- 
> 2.5.5
> 
> 
> _______________________________________________
> 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

* Re: [PATCH 04/20] i.MX: Add support for VF610 Tower board
From: Sascha Hauer @ 2016-10-04  6:32 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-5-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:41AM -0700, Andrey Smirnov wrote:
> Add support for VF610 Tower board.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  arch/arm/boards/Makefile                           |   3 +-
>  arch/arm/boards/freescale-vf610-twr/Makefile       |   4 +
>  arch/arm/boards/freescale-vf610-twr/board.c        |  61 +++++
>  .../flash-header-vf610-twr.imxcfg                  | 277 +++++++++++++++++++++
>  arch/arm/boards/freescale-vf610-twr/lowlevel.c     |  45 ++++
>  arch/arm/dts/Makefile                              |   1 +
>  arch/arm/dts/vf610-twr.dts                         |  14 ++
>  arch/arm/mach-imx/Kconfig                          |   4 +
>  arch/arm/mach-imx/include/mach/clock-vf610.h       | 215 ++++++++++++++++
>  arch/arm/mach-imx/include/mach/iomux-vf610.h       | 258 +++++++++++++++++++
>  images/Makefile.imx                                |   5 +
>  11 files changed, 886 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
>  create mode 100644 arch/arm/boards/freescale-vf610-twr/board.c
>  create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
>  create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
>  create mode 100644 arch/arm/dts/vf610-twr.dts
>  create mode 100644 arch/arm/mach-imx/include/mach/clock-vf610.h
>  create mode 100644 arch/arm/mach-imx/include/mach/iomux-vf610.h
> 
> diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
> index 23a8dbd..c8bc565 100644
> --- a/arch/arm/boards/Makefile
> +++ b/arch/arm/boards/Makefile
> @@ -10,7 +10,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK)		+= at91sam9260ek/
>  obj-$(CONFIG_MACH_AT91SAM9M10G45EK)		+= at91sam9m10g45ek/
>  obj-$(CONFIG_MACH_AT91SAM9M10IHD)		+= at91sam9m10ihd/
>  obj-$(CONFIG_MACH_AT91SAM9N12EK)		+= at91sam9n12ek/
> -obj-$(CONFIG_MACH_AT91SAM9X5EK)			+= at91sam9x5ek/
> +nobj-$(CONFIG_MACH_AT91SAM9X5EK)			+= at91sam9x5ek/
>  obj-$(CONFIG_MACH_BEAGLE)			+= beagle/
>  obj-$(CONFIG_MACH_BEAGLEBONE)			+= beaglebone/
>  obj-$(CONFIG_MACH_CANON_A1100)			+= canon-a1100/
> @@ -138,3 +138,4 @@ obj-$(CONFIG_MACH_ZEDBOARD)			+= avnet-zedboard/
>  obj-$(CONFIG_MACH_ZYLONITE)			+= zylonite/
>  obj-$(CONFIG_MACH_VARISCITE_MX6)		+= variscite-mx6/
>  obj-$(CONFIG_MACH_QEMU_VIRT64)			+= qemu-virt64/
> +obj-$(CONFIG_MACH_VF610_TWR)			+= freescale-vf610-twr/
> diff --git a/arch/arm/boards/freescale-vf610-twr/Makefile b/arch/arm/boards/freescale-vf610-twr/Makefile
> new file mode 100644
> index 0000000..32a7da5
> --- /dev/null
> +++ b/arch/arm/boards/freescale-vf610-twr/Makefile
> @@ -0,0 +1,4 @@
> +obj-y += board.o
> +obj-y += flash-header-vf610-twr.dcd.o
> +extra-y += flash-header-vf610-twr.dcd.S flash-header-vf610-twr.dcd
> +lwl-y += lowlevel.o
> diff --git a/arch/arm/boards/freescale-vf610-twr/board.c b/arch/arm/boards/freescale-vf610-twr/board.c
> new file mode 100644
> index 0000000..0879f74
> --- /dev/null
> +++ b/arch/arm/boards/freescale-vf610-twr/board.c
> @@ -0,0 +1,61 @@
> +/*
> + * Copyright (c) 2016 Zodiac Inflight Innovation
> + * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
> + *
> + * 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 version 2
> + * as published by the Free Software Foundation.
> + *
> + * 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 <config.h>
> +#include <common.h>
> +#include <dma.h>
> +#include <driver.h>
> +#include <init.h>
> +#include <of.h>
> +#include <malloc.h>
> +#include <mci.h>
> +#include <clock.h>
> +#include <io.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +
> +/*
> + * Make sure that esdhc1's clock divider is 1
> + */
> +static int vf610_twr_sdhc1_clock_init(void)
> +{
> +	int err;
> +	struct clk *esdhc1_div, *esdhc1_div_parent;
> +
> +	if (!of_machine_is_compatible("fsl,vf610-twr"))
> +		return 0;
> +
> +	esdhc1_div = clk_lookup("esdhc1_div");
> +
> +	if (IS_ERR(esdhc1_div))
> +		return PTR_ERR(esdhc1_div);
> +
> +	esdhc1_div_parent = clk_get_parent(esdhc1_div);
> +	if (IS_ERR(esdhc1_div_parent))
> +		return PTR_ERR(esdhc1_div_parent);
> +
> +	err = clk_set_rate(esdhc1_div,
> +			   clk_get_rate(esdhc1_div_parent));
> +	if (err)
> +		return err;
> +
> +	clk_put(esdhc1_div);
> +
> +	return 0;
> +}
> +coredevice_initcall(vf610_twr_sdhc1_clock_init);

What's the background for this? Should it be made SoC specific?

> diff --git a/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
> new file mode 100644
> index 0000000..18138d2
> --- /dev/null
> +++ b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
> @@ -0,0 +1,277 @@
> +soc vf610
> +loadaddr 0x80000000
> +dcdofs 0x400
> +
> +#define VF610_DDR_PAD_CTRL	0x00000180 /* 25 Ohm drive strength */
> +#define VF610_DDR_PAD_CTRL_1	0x00010180 /* 25 Ohm drive strength + differential input */
> +
> +#define DDRMC_PHY_DQ_TIMING	0x00002613
> +#define DDRMC_PHY_DQS_TIMING	0x00002615
> +#define DDRMC_PHY_CTRL		0x00210000
> +#define DDRMC_PHY_MASTER_CTRL	0x0001012a
> +#define DDRMC_PHY_SLAVE_CTRL	0x00002000
> +#define DDRMC_PHY_OFF		0x00000000
> +#define DDRMC_PHY_PROC_PAD_ODT	0x00010101
> +
> +#ifdef DEBUG
> +#define CHECKPOINT(n) wm 32 0x3f000000 n
> +#else
> +#define CHECKPOINT(n)
> +#endif
> +
> +CHECKPOINT(1)
> +
> +/* ======================= Clock initialization =======================*/
> +
> +/*
> + * Ungate all IP block clocks
> + */
> +wm 32 0x4006b040 0xffffffff
> +wm 32 0x4006b044 0xffffffff
> +wm 32 0x4006b048 0xffffffff
> +wm 32 0x4006b04c 0xffffffff
> +wm 32 0x4006b050 0xffffffff
> +wm 32 0x4006b058 0xffffffff
> +wm 32 0x4006b05c 0xffffffff
> +wm 32 0x4006b060 0xffffffff
> +wm 32 0x4006b064 0xffffffff
> +wm 32 0x4006b068 0xffffffff
> +wm 32 0x4006b06c 0xffffffff
> +
> +
> +/*
> + * We have to options to clock DDR controller:
> + *
> + *  - Use Core-A5 clock
> + *  - Use PLL2 PFD2 clock
> + *
> +
> + * Using first option without changing PLL settings doesn't seem to be
> + * possible given that DDRMC requires minimum of 300Mhz and MaskROM
> + * configures it to be clocked at 264Mhz. Changing PLL1 settings
> + * proved to be challenging becuase MaskROM code executing this DCD
> + * will also be fetching the rest of the bootloader via some
> + * peripheral interface whose clock is derived from Cortex-A5 clock.
> + *
> + * As a result this DCD configuration code uses the second option of
> + * clocking DDR wiht PLL2 PFD2 clock output
> + *
> + * Turn PLL2 on
> + */
> +wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */
> +
> +CHECKPOINT(2)
> +
> +/*
> + * Wait for PLLs to lock
> + */
> +check 32 while_any_bit_clear 0x40050030 0x80000000
> +
> +
> +CHECKPOINT(3)
> +
> +/*
> + * Switch DDRMC to be clocked with PLL2 PFD2 and enable PFD2 output
> + */
> +clear_bits 32 0x4006b008 0x00000040
> +set_bits   32 0x4006b008 0x00002000
> +
> +
> +
> +/* ======================= DDR IOMUX ======================= */
> +
> +CHECKPOINT(4)
> +
> +wm 32 0x40048220 VF610_DDR_PAD_CTRL
> +wm 32 0x40048224 VF610_DDR_PAD_CTRL
> +wm 32 0x40048228 VF610_DDR_PAD_CTRL
> +wm 32 0x4004822c VF610_DDR_PAD_CTRL
> +wm 32 0x40048230 VF610_DDR_PAD_CTRL
> +wm 32 0x40048234 VF610_DDR_PAD_CTRL
> +wm 32 0x40048238 VF610_DDR_PAD_CTRL
> +wm 32 0x4004823c VF610_DDR_PAD_CTRL
> +wm 32 0x40048240 VF610_DDR_PAD_CTRL
> +wm 32 0x40048244 VF610_DDR_PAD_CTRL
> +wm 32 0x40048248 VF610_DDR_PAD_CTRL
> +wm 32 0x4004824c VF610_DDR_PAD_CTRL
> +wm 32 0x40048250 VF610_DDR_PAD_CTRL
> +wm 32 0x40048254 VF610_DDR_PAD_CTRL
> +wm 32 0x40048258 VF610_DDR_PAD_CTRL
> +wm 32 0x4004825c VF610_DDR_PAD_CTRL
> +wm 32 0x40048260 VF610_DDR_PAD_CTRL
> +wm 32 0x40048264 VF610_DDR_PAD_CTRL
> +wm 32 0x40048268 VF610_DDR_PAD_CTRL
> +wm 32 0x4004826c VF610_DDR_PAD_CTRL
> +wm 32 0x40048270 VF610_DDR_PAD_CTRL
> +wm 32 0x40048274 VF610_DDR_PAD_CTRL
> +wm 32 0x40048278 VF610_DDR_PAD_CTRL
> +wm 32 0x4004827c VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048280 VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048284 VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048288 VF610_DDR_PAD_CTRL_1
> +wm 32 0x4004828c VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048290 VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048294 VF610_DDR_PAD_CTRL_1
> +wm 32 0x40048298 VF610_DDR_PAD_CTRL_1
> +wm 32 0x4004829c VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482a0 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482a4 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482a8 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482ac VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482b0 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482b4 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482b8 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482bc VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482c0 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482c4 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482c8 VF610_DDR_PAD_CTRL_1
> +wm 32 0x400482cc VF610_DDR_PAD_CTRL
> +wm 32 0x400482d0 VF610_DDR_PAD_CTRL
> +wm 32 0x400482d4 VF610_DDR_PAD_CTRL
> +wm 32 0x400482d8 VF610_DDR_PAD_CTRL
> +wm 32 0x4004821c VF610_DDR_PAD_CTRL
> +
> +/* ======================= DDR Controller =======================*/
> +
> +CHECKPOINT(5)
> +
> +wm 32 0x400ae000 0x00000600
> +wm 32 0x400ae008 0x00000020
> +wm 32 0x400ae028 0x00013880
> +wm 32 0x400ae02c 0x00030d40
> +wm 32 0x400ae030 0x0000050c
> +wm 32 0x400ae034 0x15040400
> +wm 32 0x400ae038 0x1406040f
> +wm 32 0x400ae040 0x04040000
> +wm 32 0x400ae044 0x006db00c
> +wm 32 0x400ae048 0x00000403
> +wm 32 0x400ae050 0x01000000
> +wm 32 0x400ae054 0x00060001
> +wm 32 0x400ae058 0x000c0000
> +wm 32 0x400ae05c 0x03000200
> +wm 32 0x400ae060 0x00000006
> +wm 32 0x400ae064 0x00010000
> +wm 32 0x400ae068 0x0c30002c
> +wm 32 0x400ae070 0x00000000
> +wm 32 0x400ae074 0x00000003
> +wm 32 0x400ae078 0x0000000a
> +wm 32 0x400ae07c 0x003001d4
> +wm 32 0x400ae084 0x00010000
> +wm 32 0x400ae088 0x00050500
> +wm 32 0x400ae098 0x00000000
> +wm 32 0x400ae09c 0x04001002
> +wm 32 0x400ae0a4 0x00000001
> +wm 32 0x400ae0c0 0x00460420
> +wm 32 0x400ae108 0x01000200
> +wm 32 0x400ae10c 0x00000040
> +wm 32 0x400ae114 0x00000200
> +wm 32 0x400ae118 0x00000040
> +wm 32 0x400ae120 0x00000000
> +wm 32 0x400ae124 0x0a010300
> +wm 32 0x400ae128 0x01014040
> +wm 32 0x400ae12c 0x01010101
> +wm 32 0x400ae130 0x03030100
> +wm 32 0x400ae134 0x01000101
> +wm 32 0x400ae138 0x0700000c
> +wm 32 0x400ae13c 0x00000000
> +wm 32 0x400ae148 0x10000000
> +wm 32 0x400ae15c 0x01000000
> +wm 32 0x400ae160 0x00040000
> +wm 32 0x400ae164 0x00000002
> +wm 32 0x400ae16c 0x00020000
> +wm 32 0x400ae180 0x00002819
> +wm 32 0x400ae184 0x01000000
> +wm 32 0x400ae188 0x00000000
> +wm 32 0x400ae18c 0x00000000
> +wm 32 0x400ae198 0x00010100
> +wm 32 0x400ae1a4 0x00000000
> +wm 32 0x400ae1a8 0x00000004
> +wm 32 0x400ae1b8 0x00040000
> +wm 32 0x400ae1c8 0x00000000
> +wm 32 0x400ae1cc 0x00000000
> +wm 32 0x400ae1d4 0x00000000
> +wm 32 0x400ae1d8 0x01010000
> +wm 32 0x400ae1e0 0x02020000
> +wm 32 0x400ae1e4 0x00000202
> +wm 32 0x400ae1e8 0x01010064
> +wm 32 0x400ae1ec 0x00010101
> +wm 32 0x400ae1f0 0x00000064
> +wm 32 0x400ae1f8 0x00000800
> +wm 32 0x400ae210 0x00000506
> +wm 32 0x400ae224 0x00020000
> +wm 32 0x400ae228 0x01000000
> +wm 32 0x400ae22c 0x04070303
> +wm 32 0x400ae230 0x00000040
> +wm 32 0x400ae23c 0x06000080
> +wm 32 0x400ae240 0x04070303
> +wm 32 0x400ae244 0x00000040
> +wm 32 0x400ae248 0x00000040
> +wm 32 0x400ae24c 0x000f0000
> +wm 32 0x400ae250 0x000f0000
> +wm 32 0x400ae25c 0x00000101
> +wm 32 0x400ae268 0x682c4000
> +wm 32 0x400ae26c 0x00000012
> +wm 32 0x400ae278 0x00000006
> +wm 32 0x400ae284 0x00010202
> +
> +/* ======================= DDR PHY =======================*/
> +
> +CHECKPOINT(6)
> +
> +wm 32 0x400ae400 DDRMC_PHY_DQ_TIMING
> +wm 32 0x400ae440 DDRMC_PHY_DQ_TIMING
> +wm 32 0x400ae480 DDRMC_PHY_DQ_TIMING
> +wm 32 0x400ae404 DDRMC_PHY_DQS_TIMING
> +wm 32 0x400ae444 DDRMC_PHY_DQS_TIMING
> +wm 32 0x400ae408 DDRMC_PHY_CTRL
> +wm 32 0x400ae448 DDRMC_PHY_CTRL
> +wm 32 0x400ae488 DDRMC_PHY_CTRL
> +wm 32 0x400ae40c DDRMC_PHY_CTRL
> +wm 32 0x400ae44c DDRMC_PHY_CTRL
> +wm 32 0x400ae48c DDRMC_PHY_CTRL
> +wm 32 0x400ae410 DDRMC_PHY_SLAVE_CTRL
> +wm 32 0x400ae450 DDRMC_PHY_SLAVE_CTRL
> +wm 32 0x400ae490 DDRMC_PHY_SLAVE_CTRL
> +wm 32 0x400ae4c4 DDRMC_PHY_OFF
> +wm 32 0x400ae4c8 0x00001100
> +wm 32 0x400ae4d0 DDRMC_PHY_PROC_PAD_ODT
> +wm 32 0x400ae000 0x00000601
> +
> +CHECKPOINT(7)
> +
> +check 32 while_any_bit_clear 0x400ae140 0x100
> +
> +CHECKPOINT(8)
> +
> +/*
> + * Cargo cult DDR controller initialization here we come!
> + *
> + * Experemintation with VF610 Tower Board shows that without the

s/Experemintation/Experimentation/

> + * following code the board would not boot off of SD card when
> + * power-cycled. It will however happily boot when reset via SW3/Reset
> + * button. For whatever reason the following actions appear to be
> + * necessary:
> + *
> + *          - Initialize DDRMC as usual
> + *	    - Issue a read to location in DDR address space
> + *	    - Disable DDRMC
> + *	    - Enable DDRMC and wait for it to finish initializing
> + *
> + * I am sure this is all going to be extrememly embarrassing to read
> + * if/when the real problem and real solution is found.
> + */
> +
> +/*
> + * Because there's no standalone read command what we do here instead
> + * is write a pattern to memory and then checking that memory address
> + * against that pattern
> + */
> +wm 32 0x80000000 0xa5a5a5a5
> +check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5
> +
> +wm 32 0x400ae000 0x00000600
> +wm 32 0x400ae000 0x00000601
> +
> +check 32 while_any_bit_clear 0x400ae140 0x100
> +
> +CHECKPOINT(9)
> \ No newline at end of file
> diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
> new file mode 100644
> index 0000000..6504273
> --- /dev/null
> +++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
> @@ -0,0 +1,45 @@
> +#include <common.h>
> +#include <linux/sizes.h>
> +#include <mach/generic.h>
> +#include <asm/barebox-arm-head.h>
> +#include <asm/barebox-arm.h>
> +#include <mach/vf610-regs.h>
> +#include <mach/clock-vf610.h>
> +#include <mach/iomux-vf610.h>
> +#include <debug_ll.h>
> +
> +static inline void setup_uart(void)
> +{
> +	void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
> +
> +	vf610_ungate_all_peripherals();
> +
> +	/*
> +	 * VF610_PAD_PTB4__UART1_TX
> +	 */
> +	writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
> +	writel(0, iomuxbase + 0x0380);
> +
> +	vf610_uart_setup_ll();
> +}
> +
> +extern char __dtb_vf610_twr_start[];
> +
> +ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
> +{
> +	int i;
> +	void *fdt;
> +	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
> +
> +	vf610_cpu_lowlevel_init();
> +
> +	for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++)
> +		writew(VF610_MSCM_IRSPRC_CP0_EN,
> +		       mscm + VF610_MSCM_IRSPRC(i));
> +
> +	if (IS_ENABLED(CONFIG_DEBUG_LL))
> +		setup_uart();
> +
> +	fdt = __dtb_vf610_twr_start - get_runtime_offset();
> +	barebox_arm_entry(0x80000000, SZ_128M, fdt);
> +}
> diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
> index d1a3fe8..f93152c 100644
> --- a/arch/arm/dts/Makefile
> +++ b/arch/arm/dts/Makefile
> @@ -76,5 +76,6 @@ pbl-dtb-$(CONFIG_MACH_TX6X) += imx6q-tx6q.dtb.o
>  pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
>  pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
>  pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
> +pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o
>  
>  clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo
> diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
> new file mode 100644
> index 0000000..54b4435
> --- /dev/null
> +++ b/arch/arm/dts/vf610-twr.dts
> @@ -0,0 +1,14 @@
> +/*
> + * Copyright 2013 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.
> + */
> +
> +#include <arm/vf610-twr.dts>
> +
> +&usbdev0 {
> +	status = "disabled";
> +};
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index 71862ef..0284a8f 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -332,6 +332,10 @@ config MACH_CM_FX6
>  	bool "CM FX6"
>  	select ARCH_IMX6
>  
> +config MACH_VF610_TWR
> +	bool "Freescale VF610 Tower Board"
> +	select ARCH_VF610
> +
>  endif
>  
>  # ----------------------------------------------------------
> diff --git a/arch/arm/mach-imx/include/mach/clock-vf610.h b/arch/arm/mach-imx/include/mach/clock-vf610.h

Should be added in a SoC specific patch.

> +#define CCM_CCR_FIRC_EN				(1 << 16)
> +#define CCM_CCR_OSCNT_MASK			0xff
> +#define CCM_CCR_OSCNT(v)			((v) & 0xff)
> +

[...]

> +#define ENET_EXTERNAL_CLK	50000000
> +#define AUDIO_EXTERNAL_CLK	24576000

VF610_ prefix?

> diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h

Should also be added in a SoC specific patch.

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

* Re: [PATCH 02/20] i.MX: Add DEBUG_LL hooks for VF610
From: Sascha Hauer @ 2016-10-04  6:24 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475505657-898-3-git-send-email-andrew.smirnov@gmail.com>

On Mon, Oct 03, 2016 at 07:40:39AM -0700, Andrey Smirnov wrote:
> Add code to support DEBUG_LL functionality on VF610/Vybrid platform.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
>  arch/arm/mach-imx/include/mach/debug_ll.h   |  27 ++-
>  arch/arm/mach-imx/include/mach/vf610-regs.h | 126 +++++++++++++
>  common/Kconfig                              |  10 +-
>  include/serial/lpuart.h                     | 265 ++++++++++++++++++++++++++++
>  4 files changed, 426 insertions(+), 2 deletions(-)
>  create mode 100644 arch/arm/mach-imx/include/mach/vf610-regs.h
>  create mode 100644 include/serial/lpuart.h
> 
> diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h
> index 5c2db6c..a132f3c 100644
> --- a/arch/arm/mach-imx/include/mach/debug_ll.h
> +++ b/arch/arm/mach-imx/include/mach/debug_ll.h
> @@ -14,8 +14,10 @@
>  #include <mach/imx51-regs.h>
>  #include <mach/imx53-regs.h>
>  #include <mach/imx6-regs.h>
> +#include <mach/vf610-regs.h>
>  
>  #include <serial/imx-uart.h>
> +#include <serial/lpuart.h>
>  
>  #ifdef CONFIG_DEBUG_LL
>  
> @@ -42,6 +44,8 @@
>  #define IMX_DEBUG_SOC MX53
>  #elif defined CONFIG_DEBUG_IMX6Q_UART
>  #define IMX_DEBUG_SOC MX6
> +#elif defined CONFIG_DEBUG_VF610_UART
> +#define IMX_DEBUG_SOC VF610
>  #else
>  #error "unknown i.MX debug uart soc type"
>  #endif
> @@ -74,6 +78,13 @@ static inline void imx6_uart_setup_ll(void)
>  	imx6_uart_setup(base);
>  }
>  
> +static inline void vf610_uart_setup_ll(void)
> +{
> +	void *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC, CONFIG_DEBUG_IMX_UART_PORT));
> +
> +	lpuart_setup(base, 66000000);
> +}
> +
>  static inline void PUTC_LL(int c)
>  {
>  	void __iomem *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
> @@ -82,14 +93,19 @@ static inline void PUTC_LL(int c)
>  	if (!base)
>  		return;
>  
> -	imx_uart_putc(base, c);
> +	if (IS_ENABLED(CONFIG_DEBUG_VF610_UART))
> +		lpuart_putc(base, c);
> +	else
> +		imx_uart_putc(base, c);
>  }
> +
>  #else
>  
>  static inline void imx50_uart_setup_ll(void) {}
>  static inline void imx51_uart_setup_ll(void) {}
>  static inline void imx53_uart_setup_ll(void) {}
>  static inline void imx6_uart_setup_ll(void)  {}
> +static inline void vf610_uart_setup_ll(void) {}
>  
>  #endif /* CONFIG_DEBUG_LL */
>  
> @@ -115,4 +131,13 @@ static inline void imx53_ungate_all_peripherals(void)
>  	imx_ungate_all_peripherals(IOMEM(MX53_CCM_BASE_ADDR));
>  }
>  
> +static inline void vf610_ungate_all_peripherals(void)
> +{
> +	void __iomem *ccmbase = IOMEM(VF610_CCM_BASE_ADDR);
> +	int i;
> +
> +	for (i = 0x40; i <= 0x6c; i += 4)
> +		writel(0xffffffff, ccmbase + i);
> +}
> +
>  #endif /* __MACH_DEBUG_LL_H__ */
> diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h

This is probably not the right patch to add this file.

> new file mode 100644
> index 0000000..a1c1a09
> --- /dev/null
> +++ b/arch/arm/mach-imx/include/mach/vf610-regs.h
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright 2013-2014 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __ASM_ARCH_IMX_REGS_H__
> +#define __ASM_ARCH_IMX_REGS_H__

MACH_VF610_REGS_H ?

> +/* System Reset Controller (SRC) */
> +#define SRC_SRSR_SW_RST					(0x1 << 18)
> +#define SRC_SRSR_RESETB					(0x1 << 7)
> +#define SRC_SRSR_JTAG_RST				(0x1 << 5)
> +#define SRC_SRSR_WDOG_M4				(0x1 << 4)
> +#define SRC_SRSR_WDOG_A5				(0x1 << 3)
> +#define SRC_SRSR_POR_RST				(0x1 << 0)
> +#define SRC_SBMR2_BMOD_MASK             (0x3 << 24)
> +#define SRC_SBMR2_BMOD_SHIFT            24
> +#define SRC_SBMR2_BMOD_FUSES            0x0
> +#define SRC_SBMR2_BMOD_SERIAL           0x1
> +#define SRC_SBMR2_BMOD_RCON             0x2

Please add a VF610_ prefix.

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

* Re: [PATCH] sandbox: Makefile: drop unused SUBARCH stuff
From: Sascha Hauer @ 2016-10-04  6:16 UTC (permalink / raw)
  To: Antony Pavlov; +Cc: barebox
In-Reply-To: <20161003115657.17953-1-antonynpavlov@gmail.com>

On Mon, Oct 03, 2016 at 02:56:57PM +0300, Antony Pavlov wrote:
> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
> ---
>  arch/sandbox/Makefile | 5 -----
>  1 file changed, 5 deletions(-)

Applied, thanks

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

* Re: [PATCH] net/phy: marvell: fix error handling
From: Sascha Hauer @ 2016-10-04  6:15 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: barebox
In-Reply-To: <20160930201008.4136-1-u.kleine-koenig@pengutronix.de>

On Fri, Sep 30, 2016 at 10:10:08PM +0200, Uwe Kleine-König wrote:
> Without first assigning to ret it doesn't make sense to check it.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/net/phy/marvell.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Applied, thanks

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

* Re: [PATCH 01/10] serial: arm_dcc: depend on !CPU_V8
From: Sascha Hauer @ 2016-10-04  6:13 UTC (permalink / raw)
  To: Lucas Stach; +Cc: barebox
In-Reply-To: <20160930103607.15791-1-l.stach@pengutronix.de>

On Fri, Sep 30, 2016 at 12:35:58PM +0200, Lucas Stach wrote:
> The DCC console uses coprocessor registers registers accesses, the
> implementation of those for ARMv8 is currently missing.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
> ---
>  drivers/serial/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied, thanks

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

* Re: [PATCH 1/2] i.MX: Introduce imx6_cpu_revision()
From: Sascha Hauer @ 2016-10-04  6:10 UTC (permalink / raw)
  To: Andrey Smirnov; +Cc: barebox
In-Reply-To: <1475187703-5748-1-git-send-email-andrew.smirnov@gmail.com>

On Thu, Sep 29, 2016 at 03:21:42PM -0700, Andrey Smirnov wrote:
> Factor out CPU revision identification code from imx6_init() into a
> standalone inline function (similar to imx6_cpu_type()), so that it
> would be possible to use that functionality in PBL code.
> 
> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
> ---
> 
> Sascha:
> 
> I have an almost ready to send, board support patch that uses this in
> PBL. Unfortunately at the last minute a regression in functionality
> was discovered in that code, so I can't post it until that is
> resolved, meanwhile I am hoping I can get this code in while I am
> debugging.
> 
> Let me know if you'd rathe I send everything together.

Looks good as is. Just send your board support when the remaining issues
are resolved. Thanks, applied.

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

* Re: [PATCH] pinctrl: mvebu: add newline to error message
From: Sascha Hauer @ 2016-10-04  6:05 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: barebox
In-Reply-To: <1475092260-12749-1-git-send-email-uwe@kleine-koenig.org>

On Wed, Sep 28, 2016 at 09:51:00PM +0200, Uwe Kleine-König wrote:
> Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org>
> ---
>  drivers/pinctrl/mvebu/common.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/pinctrl/mvebu/common.c b/drivers/pinctrl/mvebu/common.c
> index 532705286795..ae16b39268d7 100644
> --- a/drivers/pinctrl/mvebu/common.c
> +++ b/drivers/pinctrl/mvebu/common.c
> @@ -78,7 +78,8 @@ static int mvebu_pinctrl_set_state(struct pinctrl_device *pdev,
>  
>  		set = mvebu_pinctrl_find_setting_by_name(pctl, mode, function);
>  		if (!set) {
> -			dev_err(pdev->dev, "unsupported function %s on pin %s",
> +			dev_err(pdev->dev,
> +				"unsupported function %s on pin %s\n",
>  				function, group);
>  			continue;
>  		}
> -- 
> 2.8.1
> 
> 
> _______________________________________________
> 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

* Re: [PATCH 0/7] scripts: kwboot: various improvements
From: Sascha Hauer @ 2016-10-04  6:05 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: barebox
In-Reply-To: <20160928185017.25002-1-u.kleine-koenig@pengutronix.de>

On Wed, Sep 28, 2016 at 08:50:10PM +0200, Uwe Kleine-König wrote:
> Hello,
> 
> this series is the result of my efforts to make UART booting on an
> Netgear ReadyNAS 2120 work.
> 
> Best regards
> Uwe

Applied, thanks

Sascha

> 
> Uwe Kleine-König (7):
>   scripts: kwboot: try to resync on packet boundary after receiving a
>     NAK
>   scripts: kwboot: flush input and output only once
>   scripts: kwboot: improve diagnostic output
>   scripts: kwboot: shorten delay between two boot messages
>   scripts: kwboot: simplify kwboot_mmap_image
>   scripts: kwboot: set boot source to UART before sending
>   images: mvebu: don't generate uart images
> 
>  images/Makefile.mvebu |  29 ---------------
>  scripts/kwboot.c      | 101 +++++++++++++++++++++++++++++++++++++++-----------
>  2 files changed, 80 insertions(+), 50 deletions(-)
> 
> -- 
> 2.9.3
> 
> 
> _______________________________________________
> 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

* Problems with item delivery, n.00809120
From: FedEx Standard Overnight @ 2016-10-03 23:06 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: Type: text/plain, Size: 185 bytes --]

Dear Customer,

Courier was unable to deliver the parcel to you.
Please, download Delivery Label attached to this email.

Thanks and best regards,
Ivan Skinner,
FedEx Station Manager.


[-- Attachment #2: FedEx_00809120.zip --]
[-- Type: application/zip, Size: 7408 bytes --]

[-- Attachment #3: Type: text/plain, Size: 149 bytes --]

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

^ permalink raw reply

* [PATCH 11/20] i.MX: Add VF610 clock tree initialization code
From: Andrey Smirnov @ 2016-10-03 14:40 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1475505657-898-1-git-send-email-andrew.smirnov@gmail.com>

Based on analogous code from Linux kernel

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/clk/imx/Makefile    |    1 +
 drivers/clk/imx/clk-vf610.c | 1224 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1225 insertions(+)
 create mode 100644 drivers/clk/imx/clk-vf610.c

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index 0303c0b..2665f49 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -1 +1,2 @@
 obj-y += clk.o
+obj-$(CONFIG_ARCH_VF610) += clk-vf610.o
diff --git a/drivers/clk/imx/clk-vf610.c b/drivers/clk/imx/clk-vf610.c
new file mode 100644
index 0000000..2fbdbb3
--- /dev/null
+++ b/drivers/clk/imx/clk-vf610.c
@@ -0,0 +1,1224 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovations
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on analogous code from Linux kernel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <of_address.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <mfd/syscon.h>
+#include <dt-bindings/clock/vf610-clock.h>
+
+#include "../../../arch/arm/mach-imx/clk.h"
+
+enum {
+	CCM_CCR		= 0x00,
+	CCM_CSR		= 0x04,
+	CCM_CCSR	= 0x08,
+	CCM_CACRR	= 0x0c,
+	CCM_CSCMR1	= 0x10,
+	CCM_CSCDR1	= 0x14,
+	CCM_CSCDR2	= 0x18,
+	CCM_CSCDR3	= 0x1c,
+	CCM_CSCMR2	= 0x20,
+	CCM_CSCDR4	= 0x24,
+	CCM_CLPCR	= 0x2c,
+	CCM_CISR	= 0x30,
+	CCM_CIMR	= 0x34,
+	CCM_CGPR	= 0x3c,
+	CCM_CCGR0	= 0x40,
+	CCM_CCGR1	= 0x44,
+	CCM_CCGR2	= 0x48,
+	CCM_CCGR3	= 0x4c,
+	CCM_CCGR4	= 0x50,
+	CCM_CCGR5	= 0x54,
+	CCM_CCGR6	= 0x58,
+	CCM_CCGR7	= 0x5c,
+	CCM_CCGR8	= 0x60,
+	CCM_CCGR9	= 0x64,
+	CCM_CCGR10	= 0x68,
+	CCM_CCGR11	= 0x6c,
+
+	CCM_CMEOR0	= 0x70,
+	CCM_CMEOR1	= 0x74,
+	CCM_CMEOR2	= 0x78,
+	CCM_CMEOR3	= 0x7c,
+	CCM_CMEOR4	= 0x80,
+	CCM_CMEOR5	= 0x84,
+	CCM_CPPDSR	= 0x88,
+	CCM_CCOWR	= 0x8c,
+	CCM_CCPGR0	= 0x90,
+	CCM_CCPGR1	= 0x94,
+	CCM_CCPGR2	= 0x98,
+	CCM_CCPGR3	= 0x9c,
+};
+
+/* CCM_CCGRx(x)		(CCM_CCGR0 + (x) * 4) */
+
+static int vf610_ccm_ccgrx_cgn(int n) {
+	return n * 2;
+}
+
+
+enum {
+	PFD_PLL1_BASE	= 0x2b0,
+	PFD_PLL2_BASE	= 0x100,
+	PFD_PLL3_BASE	= 0x0f0,
+	ANA_MISC1	= 0x160,
+};
+
+static const unsigned int PLL_CTRL[7] = {
+	0x270,
+	0x030,
+	0x010,
+	0x070,
+	0x0e0,
+	0x0a0,
+	0x020,
+};
+
+
+static struct clk *clk[VF610_CLK_END];
+struct clk_onecell_data clk_data;
+
+static struct clk * __init vf610_get_fixed_clock(struct device_node *np,
+						 const char *name)
+{
+	struct clk *clk = of_clk_get_by_name(np, name);
+
+	/* Backward compatibility if device tree is missing clks assignments */
+	if (IS_ERR(clk))
+		clk = imx_obtain_fixed_clock(name, 0);
+
+	return clk;
+};
+
+static void vf610_ccm_setup_fixed(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	clk[VF610_CLK_DUMMY]	 = clk_fixed("dummy", 0);
+	clk[VF610_CLK_SIRC_128K] = clk_fixed("sirc_128k", 128000);
+	clk[VF610_CLK_SIRC_32K]  = clk_fixed("sirc_32k", 32000);
+	clk[VF610_CLK_FIRC]	 = clk_fixed("firc", 24000000);
+}
+
+static void vf610_ccm_setup_from_dt(struct device_node *np,
+				    void __iomem *anatop,
+				    void __iomem *ccm)
+{
+	clk[VF610_CLK_SXOSC]     = vf610_get_fixed_clock(np, "sxosc");
+	clk[VF610_CLK_FXOSC]     = vf610_get_fixed_clock(np, "fxosc");
+	clk[VF610_CLK_AUDIO_EXT] = vf610_get_fixed_clock(np, "audio_ext");
+	clk[VF610_CLK_ENET_EXT]  = vf610_get_fixed_clock(np, "enet_ext");
+
+	/* Clock source from external clock via LVDs PAD */
+	clk[VF610_CLK_ANACLK1] = vf610_get_fixed_clock(np, "anaclk1");
+
+	clk[VF610_CLK_FXOSC_HALF] = imx_clk_fixed_factor("fxosc_half",
+							 "fxosc", 1, 2);
+}
+
+static void vf610_ccm_setup_slow_clk(struct device_node *np,
+				     void __iomem *anatop,
+				     void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"sirc_32k",
+		"sxosc",
+	};
+
+	clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel",
+						  ccm + CCM_CCSR,
+						  4, 1,
+						  sources,
+						  ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_fast_clk(struct device_node *np,
+				     void __iomem *anatop,
+				     void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"firc",
+		"fxosc",
+	};
+
+	clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel",
+						  ccm + CCM_CCSR,
+						  5, 1,
+						  sources,
+						  ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_pll_bypass_srcs(struct device_node *np,
+					    void __iomem *anatop,
+					    void __iomem *ccm)
+{
+	size_t i;
+
+	static const char *parents[] = {
+		"fast_clk_sel",
+		"lvds1_in",
+	};
+
+#define VF610_CLK_PLL_BYPASS_SRC(n)			\
+	{ VF610_CLK_PLL##n##_BYPASS_SRC, "pll" #n "_bypass_src" }
+
+	static const struct {
+		int id;
+		const char *name;
+	} clocks[] = {
+		VF610_CLK_PLL_BYPASS_SRC(1),
+		VF610_CLK_PLL_BYPASS_SRC(2),
+		VF610_CLK_PLL_BYPASS_SRC(3),
+		VF610_CLK_PLL_BYPASS_SRC(4),
+		VF610_CLK_PLL_BYPASS_SRC(5),
+		VF610_CLK_PLL_BYPASS_SRC(6),
+		VF610_CLK_PLL_BYPASS_SRC(7),
+	};
+
+#undef VF610_CLK_PLL_BYPASS_SRC
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		const char *name = clocks[i].name;
+		const int id = clocks[i].id;
+
+		clk[id] = imx_clk_mux(name, anatop + PLL_CTRL[i],
+				      14, 1,
+				      parents, ARRAY_SIZE(parents));
+	}
+}
+
+static void vf610_ccm_setup_plls(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	size_t i;
+
+#define VF610_CLK_PLL(n, type, mask)				   \
+	{ VF610_CLK_PLL##n, type, "pll" #n, "pll" #n "_bypass_src", mask }
+
+	static const struct {
+		int id;
+		int type;
+		const char *name;
+		const char *parent;
+		u32 mask;
+	} clocks[] = {
+		VF610_CLK_PLL(1, IMX_PLLV3_GENERIC,   0x01),
+		VF610_CLK_PLL(2, IMX_PLLV3_GENERIC,   0x01),
+		VF610_CLK_PLL(3, IMX_PLLV3_USB_VF610, 0x02),
+		VF610_CLK_PLL(4, IMX_PLLV3_AV,        0x7f),
+		VF610_CLK_PLL(5, IMX_PLLV3_ENET,      0x03),
+		VF610_CLK_PLL(6, IMX_PLLV3_AV,        0x7f),
+		VF610_CLK_PLL(7, IMX_PLLV3_USB_VF610, 0x02),
+	};
+
+#undef VF610_CLK_PLL
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		const char *name = clocks[i].name;
+		const int id = clocks[i].id;
+
+		clk[id] = imx_clk_pllv3(clocks[i].type,
+					name,
+					clocks[i].parent,
+					anatop + PLL_CTRL[i],
+					clocks[i].mask);
+	}
+}
+
+static void vf610_ccm_setup_pll_bypass(struct device_node *np,
+				       void __iomem *anatop,
+				       void __iomem *ccm)
+{
+	size_t i;
+	static const char *pll_bypass_parents[][2] = {
+		{ "pll1", "pll1_bypass_src" },
+		{ "pll2", "pll2_bypass_src" },
+		{ "pll3", "pll3_bypass_src" },
+		{ "pll4", "pll4_bypass_src" },
+		{ "pll5", "pll5_bypass_src" },
+		{ "pll6", "pll6_bypass_src" },
+		{ "pll7", "pll7_bypass_src" },
+	};
+
+#define VF610_PLL_BYPASS(n)				\
+	{ VF610_PLL##n##_BYPASS, "pll" #n "_bypass" }
+
+	static const struct {
+		int id;
+		const char *name;
+	} clocks[] = {
+		VF610_PLL_BYPASS(1),
+		VF610_PLL_BYPASS(2),
+		VF610_PLL_BYPASS(3),
+		VF610_PLL_BYPASS(4),
+		VF610_PLL_BYPASS(5),
+		VF610_PLL_BYPASS(6),
+		VF610_PLL_BYPASS(7),
+	};
+
+#undef VF610_PLL_BYPASS
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		const char *name = clocks[i].name;
+		const int id = clocks[i].id;
+
+		clk[id] = imx_clk_mux_p(name,
+					anatop + PLL_CTRL[i],
+					16, 1,
+					pll_bypass_parents[i],
+					ARRAY_SIZE(pll_bypass_parents[i]));
+	}
+}
+
+static void vf610_ccm_setup_group1(struct device_node *np,
+				   void __iomem *anatop,
+				   void __iomem *ccm)
+{
+	size_t i;
+
+	static const struct {
+		int id;
+		const char *name;
+		const char *parent;
+		unsigned int reg;
+	} clocks[] = {
+		{ VF610_CLK_PLL1_SYS,      "pll1_sys",      "pll1_bypass" },
+		{ VF610_CLK_PLL2_BUS,      "pll2_bus",      "pll2_bypass" },
+		{ VF610_CLK_PLL3_USB_OTG,  "pll3_usb_otg",  "pll3_bypass" },
+		{ VF610_CLK_PLL4_AUDIO,    "pll4_audio",    "pll4_bypass" },
+		{ VF610_CLK_PLL5_ENET,     "pll5_enet",     "pll5_bypass" },
+		{ VF610_CLK_PLL6_VIDEO,    "pll6_video",    "pll6_bypass" },
+		{ VF610_CLK_PLL7_USB_HOST, "pll7_usb_host", "pll7_bypass" },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		const char *name = clocks[i].name;
+		const int id = clocks[i].id;
+
+		clk[id] = imx_clk_gate(name, clocks[i].parent,
+				       anatop + PLL_CTRL[i], 13);
+	}
+}
+
+static void vf610_ccm_setup_pfds(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	size_t i;
+
+#define VF610_CLK_PLL_PFD(n, m)						\
+	{ VF610_CLK_PLL##n##_PFD##m, "pll" #n "_pfd" #m,		\
+	  "pll" #n "_sys", PFD_PLL##n##_BASE, m - 1 }
+
+	const static struct {
+		int id;
+		const char *name;
+		const char *parent;
+		unsigned int reg;
+		u8 idx;
+	} clocks[] = {
+		VF610_CLK_PLL_PFD(1, 1),
+		VF610_CLK_PLL_PFD(1, 2),
+		VF610_CLK_PLL_PFD(1, 3),
+		VF610_CLK_PLL_PFD(1, 4),
+
+		VF610_CLK_PLL_PFD(2, 1),
+		VF610_CLK_PLL_PFD(2, 2),
+		VF610_CLK_PLL_PFD(2, 3),
+		VF610_CLK_PLL_PFD(2, 4),
+
+		VF610_CLK_PLL_PFD(3, 1),
+		VF610_CLK_PLL_PFD(3, 2),
+		VF610_CLK_PLL_PFD(3, 3),
+		VF610_CLK_PLL_PFD(3, 4),
+	};
+
+#undef VF610_CLK_PLL_PFD
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		const char *name = clocks[i].name;
+		const int id = clocks[i].id;
+
+		clk[id] = imx_clk_pfd(name,
+				      clocks[i].parent,
+				      anatop + clocks[i].reg,
+				      clocks[i].idx);
+	}
+}
+
+static void vf610_ccm_setup_pll1_pfd_out(struct device_node *np,
+					 void __iomem *anatop,
+					 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll1_sys",
+		"pll1_pfd1",
+		"pll1_pfd2",
+		"pll1_pfd3",
+		"pll1_pfd4",
+	};
+
+	clk[VF610_CLK_PLL1_PFD_SEL] = imx_clk_mux("pll1_pfd_sel",
+						  ccm + CCM_CCSR,
+						  16, 3,
+						  sources, ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_pll2_pfd_out(struct device_node *np,
+					 void __iomem *anatop,
+					 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll2_bus",
+		"pll2_pfd1",
+		"pll2_pfd2",
+		"pll2_pfd3",
+		"pll2_pfd4",
+	};
+
+	clk[VF610_CLK_PLL2_PFD_SEL] = imx_clk_mux("pll2_pfd_sel",
+						  ccm + CCM_CCSR,
+						  19, 3,
+						  sources, ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_sys_out(struct device_node *np,
+				   void __iomem *anatop,
+				   void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"fast_clk_sel",
+		"slow_clk_sel",
+		"pll2_pfd_sel",
+		"pll2_bus",
+		"pll1_pfd_sel",
+		"pll3_usb_otg",
+	};
+
+	clk[VF610_CLK_SYS_SEL] = imx_clk_mux("sys_sel",
+					     ccm + CCM_CCSR,
+					     0, 3,
+					     sources, ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_ddr_out(struct device_node *np,
+				    void __iomem *anatop,
+				    void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll2_pfd2",
+		"sys_sel",
+	};
+
+	clk[VF610_CLK_DDR_SEL] = imx_clk_mux("ddr_sel",
+					     ccm + CCM_CCSR,
+					     6, 1,
+					     sources, ARRAY_SIZE(sources));
+}
+
+static void vf610_ccm_setup_dividers(struct device_node *np,
+				     void __iomem *anatop,
+				     void __iomem *ccm)
+{
+	size_t i;
+
+	static const struct {
+		int id;
+		const char *name;
+		const char *parent;
+		u8 shift;
+		u8 width;
+	} clocks[] = {
+		{
+			.id	= VF610_CLK_SYS_BUS,
+			.name	= "sys_bus",
+			.parent = "sys_sel",
+			.shift	= 0,
+			.width	= 3,
+		},
+		{
+			.id	= VF610_CLK_PLATFORM_BUS,
+			.name	= "platform_bus",
+			.parent = "sys_bus",
+			.shift	= 3,
+			.width	= 3,
+		},
+		{
+			.id	= VF610_CLK_IPG_BUS,
+			.name	= "ipg_bus",
+			.parent = "platform_bus",
+			.shift	= 11,
+			.width	= 2,
+		},
+		{
+			.id	= VF610_CLK_PLL3_MAIN_DIV,
+			.name	= "pll3_usb_otg_div",
+			.parent = "pll3_usb_otg",
+			.shift	= 20,
+			.width	= 1,
+		},
+		{
+			.id	= VF610_CLK_PLL6_MAIN_DIV,
+			.name	= "pll6_video_div",
+			.parent = "pll6_video",
+			.shift	= 21,
+			.width	= 1,
+		},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++)
+		clk[clocks[i].id] = imx_clk_divider(clocks[i].name,
+						    clocks[i].parent,
+						    ccm + CCM_CACRR,
+						    clocks[i].shift,
+						    clocks[i].width);
+}
+
+static void vf610_ccm_setup_pll4_main_div(struct device_node *np,
+					  void __iomem *anatop,
+					  void __iomem *ccm)
+{
+	static const struct clk_div_table div_table[] = {
+		{ .val = 0, .div = 1  },
+		{ .val = 1, .div = 2  },
+		{ .val = 2, .div = 6  },
+		{ .val = 3, .div = 8  },
+		{ .val = 4, .div = 10 },
+		{ .val = 5, .div = 12 },
+		{ .val = 6, .div = 14 },
+		{ .val = 7, .div = 16 },
+		{ }
+	};
+
+	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_divider_table("pll4_audio_div",
+							 "pll4_audio",
+							 ccm +  CCM_CACRR, 6, 3,
+							 div_table, 0);
+}
+
+static void vf610_ccm_setup_ddrmc(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc",
+						 "ddr_sel",
+						 ccm + CCM_CCGR6,
+						 vf610_ccm_ccgrx_cgn(14),
+						 0x2);
+}
+
+static void vf610_ccm_setup_wkpu(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu",
+						"ipg_bus",
+						ccm + CCM_CCGR4,
+						vf610_ccm_ccgrx_cgn(10),
+						0x2);
+}
+
+static void vf610_ccm_setup_usbphys(struct device_node *np,
+				    void __iomem *anatop,
+				    void __iomem *ccm)
+{
+	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg",
+					      anatop + PLL_CTRL[2], 6);
+	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host",
+					      anatop + PLL_CTRL[6], 6);
+}
+
+static void vf610_ccm_setup_usbcs(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+
+{
+
+	clk[VF610_CLK_USBC0] = imx_clk_gate2("usbc0", "ipg_bus",
+					     ccm + CCM_CCGR1,
+					     vf610_ccm_ccgrx_cgn(4));
+	clk[VF610_CLK_USBC1] = imx_clk_gate2("usbc1", "ipg_bus",
+					     ccm + CCM_CCGR7,
+					     vf610_ccm_ccgrx_cgn(4));
+
+}
+
+static void vf610_ccm_setup_qspis(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll3_usb_otg",
+		"pll3_pfd4",
+		"pll2_pfd4",
+		"pll1_pfd4",
+	};
+
+	clk[VF610_CLK_QSPI0_SEL] = imx_clk_mux("qspi0_sel",
+					       ccm + CCM_CSCMR1,
+					       22, 2,
+					       sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_QSPI0_EN] = imx_clk_gate("qspi0_en", "qspi0_sel",
+					       ccm + CCM_CSCDR3, 4);
+	clk[VF610_CLK_QSPI0_X4_DIV] = imx_clk_divider("qspi0_x4", "qspi0_en",
+						      ccm + CCM_CSCDR3, 0, 2);
+	clk[VF610_CLK_QSPI0_X2_DIV] = imx_clk_divider("qspi0_x2", "qspi0_x4",
+						      ccm + CCM_CSCDR3, 2, 1);
+	clk[VF610_CLK_QSPI0_X1_DIV] = imx_clk_divider("qspi0_x1", "qspi0_x2",
+						      ccm + CCM_CSCDR3, 3, 1);
+	clk[VF610_CLK_QSPI0] = imx_clk_gate2("qspi0", "qspi0_x1",
+					     ccm + CCM_CCGR2,
+					     vf610_ccm_ccgrx_cgn(4));
+
+	clk[VF610_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel",
+					       ccm + CCM_CSCMR1,
+					       24, 2,
+					       sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_QSPI1_EN] = imx_clk_gate("qspi1_en", "qspi1_sel",
+					       ccm + CCM_CSCDR3, 12);
+	clk[VF610_CLK_QSPI1_X4_DIV] = imx_clk_divider("qspi1_x4", "qspi1_en",
+						      ccm + CCM_CSCDR3, 8, 2);
+	clk[VF610_CLK_QSPI1_X2_DIV] = imx_clk_divider("qspi1_x2", "qspi1_x4",
+						      ccm + CCM_CSCDR3, 10, 1);
+	clk[VF610_CLK_QSPI1_X1_DIV] = imx_clk_divider("qspi1_x1", "qspi1_x2",
+						      ccm + CCM_CSCDR3, 11, 1);
+	clk[VF610_CLK_QSPI1] = imx_clk_gate2("qspi1", "qspi1_x1",
+					     ccm + CCM_CCGR8,
+					     vf610_ccm_ccgrx_cgn(4));
+}
+
+static void vf610_ccm_setup_enets(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	static const char *enet_sels[] = {
+		"enet_ext",
+		"audio_ext",
+		"enet_50m",
+		"enet_25m",
+	};
+
+	static const char *enet_ts_sels[] = {
+		"enet_ext",
+		"fxosc",
+		"audio_ext",
+		"usb",
+		"enet_ts",
+		"enet_25m",
+		"enet_50m",
+	};
+
+	clk[VF610_CLK_ENET_50M] = imx_clk_fixed_factor("enet_50m",
+						       "pll5_enet", 1, 10);
+	clk[VF610_CLK_ENET_25M] = imx_clk_fixed_factor("enet_25m",
+						       "pll5_enet", 1, 20);
+	clk[VF610_CLK_ENET_SEL] = imx_clk_mux("enet_sel",
+					      ccm + CCM_CSCMR2, 4, 2,
+					      enet_sels,
+					      ARRAY_SIZE(enet_sels));
+	clk[VF610_CLK_ENET_TS_SEL] = imx_clk_mux("enet_ts_sel",
+						 ccm + CCM_CSCMR2, 0, 3,
+						 enet_ts_sels,
+						 ARRAY_SIZE(enet_ts_sels));
+	clk[VF610_CLK_ENET] = imx_clk_gate("enet", "enet_sel",
+					   ccm + CCM_CSCDR1, 24);
+	clk[VF610_CLK_ENET_TS] = imx_clk_gate("enet_ts", "enet_ts_sel",
+					      ccm + CCM_CSCDR1, 23);
+	clk[VF610_CLK_ENET0] = imx_clk_gate2("enet0", "ipg_bus",
+					     ccm + CCM_CCGR9,
+					     vf610_ccm_ccgrx_cgn(0));
+	clk[VF610_CLK_ENET1] = imx_clk_gate2("enet1", "ipg_bus",
+					     ccm + CCM_CCGR9,
+					     vf610_ccm_ccgrx_cgn(1));
+}
+
+static void vf610_ccm_setup_pit(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	clk[VF610_CLK_PIT] = imx_clk_gate2("pit", "ipg_bus",
+					   ccm + CCM_CCGR1,
+					   vf610_ccm_ccgrx_cgn(7));
+}
+
+static void vf610_ccm_setup_uarts(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	clk[VF610_CLK_UART0] = imx_clk_gate2("uart0", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(7));
+	clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(8));
+	clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(9));
+	clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(10));
+	clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus",
+					     ccm + CCM_CCGR6,
+					     vf610_ccm_ccgrx_cgn(9));
+	clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus",
+					     ccm + CCM_CCGR6,
+					     vf610_ccm_ccgrx_cgn(10));
+}
+
+static void vf610_ccm_setup_i2cs(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+
+{
+	clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus",
+					    ccm + CCM_CCGR4,
+					    vf610_ccm_ccgrx_cgn(6));
+	clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus",
+					    ccm + CCM_CCGR4,
+					    vf610_ccm_ccgrx_cgn(7));
+	clk[VF610_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_bus",
+					    ccm + CCM_CCGR10,
+					    vf610_ccm_ccgrx_cgn(6));
+	clk[VF610_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_bus",
+					    ccm + CCM_CCGR10,
+					    vf610_ccm_ccgrx_cgn(7));
+}
+
+static void vf610_ccm_setup_dspis(struct device_node *np,
+				  void __iomem *anatop,
+				  void __iomem *ccm)
+{
+	clk[VF610_CLK_DSPI0] = imx_clk_gate2("dspi0", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(12));
+	clk[VF610_CLK_DSPI1] = imx_clk_gate2("dspi1", "ipg_bus",
+					     ccm + CCM_CCGR0,
+					     vf610_ccm_ccgrx_cgn(13));
+	clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus",
+					     ccm + CCM_CCGR6,
+					     vf610_ccm_ccgrx_cgn(12));
+	clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus",
+					     ccm + CCM_CCGR6,
+					     vf610_ccm_ccgrx_cgn(13));
+}
+
+static void vf610_ccm_setup_wdt(struct device_node *np,
+				void __iomem *anatop,
+				void __iomem *ccm)
+{
+	clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus",
+					   ccm + CCM_CCGR1,
+					   vf610_ccm_ccgrx_cgn(14));
+}
+
+static void vf610_ccm_setup_esdhcs(struct device_node *np,
+				   void __iomem *anatop,
+				   void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll3_usb_otg",
+		"pll3_pfd3",
+		"pll1_pfd3",
+		"platform_bus",
+	};
+
+	clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel",
+						ccm + CCM_CSCMR1, 16, 2,
+						sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_ESDHC0_EN] = imx_clk_gate("esdhc0_en", "esdhc0_sel",
+						ccm + CCM_CSCDR2, 28);
+	clk[VF610_CLK_ESDHC0_DIV] = imx_clk_divider("esdhc0_div", "esdhc0_en",
+						    ccm +CCM_CSCDR2, 16, 4);
+	clk[VF610_CLK_ESDHC0] = imx_clk_gate2("eshc0", "esdhc0_div",
+					      ccm + CCM_CCGR7,
+					      vf610_ccm_ccgrx_cgn(1));
+
+	clk[VF610_CLK_ESDHC1_SEL] = imx_clk_mux("esdhc1_sel",
+						ccm + CCM_CSCMR1, 18, 2,
+						sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_ESDHC1_EN] = imx_clk_gate("esdhc1_en", "esdhc1_sel",
+						ccm + CCM_CSCDR2, 29);
+	clk[VF610_CLK_ESDHC1_DIV] = imx_clk_divider("esdhc1_div", "esdhc1_en",
+						    ccm + CCM_CSCDR2, 20, 4);
+	clk[VF610_CLK_ESDHC1] = imx_clk_gate2("eshc1", "esdhc1_div",
+					      ccm + CCM_CCGR7,
+					      vf610_ccm_ccgrx_cgn(2));
+}
+
+static void vf610_ccm_setup_ftms(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	/* FTM counter clock source, not module clock */
+	static const char *ftm_ext_sels[] = {
+		"sirc_128k",
+		"sxosc",
+		"fxosc_half",
+		"audio_ext",
+	};
+
+	static const char *ftm_fix_sels[] = {
+		"sxosc",
+		"ipg_bus",
+	};
+
+	/*
+	 * ftm_ext_clk and ftm_fix_clk are FTM timer counter's
+	 * selectable clock sources, both use a common enable bit
+	 * in CCM_CSCDR1, selecting "dummy" clock as parent of
+	 * "ftm0_ext_fix" make it serve only for enable/disable.
+	 */
+	clk[VF610_CLK_FTM0_EXT_SEL] = imx_clk_mux("ftm0_ext_sel",
+						  ccm + CCM_CSCMR2, 6, 2,
+						  ftm_ext_sels,
+						  ARRAY_SIZE(ftm_ext_sels));
+	clk[VF610_CLK_FTM0_FIX_SEL] = imx_clk_mux("ftm0_fix_sel",
+						  ccm + CCM_CSCMR2, 14, 1,
+						  ftm_fix_sels,
+						  ARRAY_SIZE(ftm_fix_sels));
+	clk[VF610_CLK_FTM0_EXT_FIX_EN] = imx_clk_gate("ftm0_ext_fix_en",
+						      "dummy",
+						      ccm + CCM_CSCDR1, 25);
+	clk[VF610_CLK_FTM1_EXT_SEL] = imx_clk_mux("ftm1_ext_sel",
+						  ccm + CCM_CSCMR2, 8, 2,
+						  ftm_ext_sels,
+						  ARRAY_SIZE(ftm_ext_sels));
+	clk[VF610_CLK_FTM1_FIX_SEL] = imx_clk_mux("ftm1_fix_sel",
+						  ccm + CCM_CSCMR2, 15, 1,
+						  ftm_fix_sels,
+						  ARRAY_SIZE(ftm_fix_sels));
+	clk[VF610_CLK_FTM1_EXT_FIX_EN] = imx_clk_gate("ftm1_ext_fix_en",
+						      "dummy",
+						      ccm + CCM_CSCDR1, 26);
+	clk[VF610_CLK_FTM2_EXT_SEL] = imx_clk_mux("ftm2_ext_sel",
+						  ccm + CCM_CSCMR2, 10, 2,
+						  ftm_ext_sels,
+						  ARRAY_SIZE(ftm_ext_sels));
+	clk[VF610_CLK_FTM2_FIX_SEL] = imx_clk_mux("ftm2_fix_sel",
+						  ccm + CCM_CSCMR2, 16, 1,
+						  ftm_fix_sels,
+						  ARRAY_SIZE(ftm_fix_sels));
+	clk[VF610_CLK_FTM2_EXT_FIX_EN] = imx_clk_gate("ftm2_ext_fix_en",
+						      "dummy",
+						      ccm + CCM_CSCDR1, 27);
+	clk[VF610_CLK_FTM3_EXT_SEL] = imx_clk_mux("ftm3_ext_sel",
+						  ccm + CCM_CSCMR2, 12, 2,
+						  ftm_ext_sels,
+						  ARRAY_SIZE(ftm_ext_sels));
+	clk[VF610_CLK_FTM3_FIX_SEL] = imx_clk_mux("ftm3_fix_sel",
+						  ccm + CCM_CSCMR2, 17, 1,
+						  ftm_fix_sels,
+						  ARRAY_SIZE(ftm_fix_sels));
+	clk[VF610_CLK_FTM3_EXT_FIX_EN] = imx_clk_gate("ftm3_ext_fix_en",
+						      "dummy",
+						      ccm + CCM_CSCDR1, 28);
+
+	/* ftm(n)_clk are FTM module operation clock */
+	clk[VF610_CLK_FTM0] = imx_clk_gate2("ftm0", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(8));
+	clk[VF610_CLK_FTM1] = imx_clk_gate2("ftm1", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(9));
+	clk[VF610_CLK_FTM2] = imx_clk_gate2("ftm2", "ipg_bus",
+					    ccm + CCM_CCGR7,
+					    vf610_ccm_ccgrx_cgn(8));
+	clk[VF610_CLK_FTM3] = imx_clk_gate2("ftm3", "ipg_bus",
+					    ccm + CCM_CCGR7,
+					    vf610_ccm_ccgrx_cgn(9));
+}
+
+static void vf610_ccm_setup_dcus(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll1_pfd2",
+		"pll3_usb_otg",
+	};
+
+	clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel",
+					      ccm + CCM_CSCMR1, 28, 1,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel",
+					      ccm + CCM_CSCDR3, 19);
+	clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en",
+						  ccm + CCM_CSCDR3, 16, 3);
+	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus",
+					    ccm + CCM_CCGR3,
+					    vf610_ccm_ccgrx_cgn(8));
+	clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel",
+					      ccm + CCM_CSCMR1, 29, 1,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel",
+					      ccm + CCM_CSCDR3, 23);
+	clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en",
+						  ccm + CCM_CSCDR3, 20, 3);
+	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus",
+					    ccm + CCM_CCGR9,
+					    vf610_ccm_ccgrx_cgn(8));
+}
+
+static void vf610_ccm_setup_tcons(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus",
+					     ccm + CCM_CCGR1,
+					     vf610_ccm_ccgrx_cgn(13));
+	clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus",
+					     ccm + CCM_CCGR7,
+					     vf610_ccm_ccgrx_cgn(13));
+}
+
+
+static void vf610_ccm_setup_esai(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"audio_ext",
+		"mlb",
+		"spdif_rx",
+		"pll4_audio_div",
+	};
+
+	clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel",
+					      ccm + CCM_CSCMR1, 20, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel",
+					      ccm + CCM_CSCDR2, 30);
+	clk[VF610_CLK_ESAI_DIV] = imx_clk_divider("esai_div", "esai_en",
+						  ccm + CCM_CSCDR2, 24, 4);
+	clk[VF610_CLK_ESAI] = imx_clk_gate2("esai", "esai_div",
+					    ccm + CCM_CCGR4,
+					    vf610_ccm_ccgrx_cgn(2));
+}
+
+static void vf610_ccm_setup_sais(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"audio_ext",
+		"mlb",
+		"spdif_rx",
+		"pll4_audio_div",
+	};
+
+	clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel",
+					      ccm + CCM_CSCMR1, 0, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel",
+					      ccm + CCM_CSCDR1, 16);
+	clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en",
+						  ccm + CCM_CSCDR1, 0, 4);
+	clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "ipg_bus",
+					    ccm + CCM_CCGR0,
+					    vf610_ccm_ccgrx_cgn(15));
+
+	clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel",
+					      ccm + CCM_CSCMR1, 2, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel",
+					      ccm + CCM_CSCDR1, 17);
+	clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en",
+						  ccm + CCM_CSCDR1, 4, 4);
+	clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(0));
+
+	clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel",
+					      ccm + CCM_CSCMR1, 4, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel",
+					      ccm + CCM_CSCDR1, 18);
+	clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en",
+						  ccm + CCM_CSCDR1, 8, 4);
+	clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(1));
+
+	clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel",
+					      ccm + CCM_CSCMR1, 6, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel",
+					      ccm + CCM_CSCDR1, 19);
+	clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en",
+						  ccm + CCM_CSCDR1, 12, 4);
+	clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(2));
+}
+
+static void vf610_ccm_setup_nfc(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"platform_bus",
+		"pll1_pfd1",
+		"pll3_pfd1",
+		"pll3_pfd3",
+	};
+
+	clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel",
+					     ccm + CCM_CSCMR1, 12, 2,
+					     sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel",
+					     ccm + CCM_CSCDR2, 9);
+	clk[VF610_CLK_NFC_PRE_DIV] = imx_clk_divider("nfc_pre_div", "nfc_en",
+						     ccm + CCM_CSCDR3, 13, 3);
+	clk[VF610_CLK_NFC_FRAC_DIV] = imx_clk_divider("nfc_frac_div",
+						      "nfc_pre_div",
+						      ccm + CCM_CSCDR2, 4, 4);
+	clk[VF610_CLK_NFC] = imx_clk_gate2("nfc", "nfc_frac_div",
+					   ccm + CCM_CCGR10,
+					   vf610_ccm_ccgrx_cgn(0));
+}
+
+static void vf610_ccm_setup_gpu(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll2_pfd2",
+		"pll3_pfd2",
+	};
+
+	clk[VF610_CLK_GPU_SEL] = imx_clk_mux("gpu_sel",
+					     ccm + CCM_CSCMR1, 14, 1,
+					     sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_GPU_EN] = imx_clk_gate("gpu_en", "gpu_sel",
+					     ccm + CCM_CSCDR2, 10);
+	clk[VF610_CLK_GPU2D] = imx_clk_gate2("gpu", "gpu_en",
+					     ccm + CCM_CCGR8,
+					     vf610_ccm_ccgrx_cgn(15));
+}
+
+static void vf610_ccm_setup_vadc(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	static const char *sources[] = {
+		"pll6_video_div",
+		"pll3_usb_otg_div",
+		"pll3_usb_otg",
+	};
+
+	clk[VF610_CLK_VADC_SEL] = imx_clk_mux("vadc_sel",
+					      ccm + CCM_CSCMR1, 8, 2,
+					      sources, ARRAY_SIZE(sources));
+	clk[VF610_CLK_VADC_EN] = imx_clk_gate("vadc_en", "vadc_sel",
+					      ccm + CCM_CSCDR1, 22);
+	clk[VF610_CLK_VADC_DIV] = imx_clk_divider("vadc_div", "vadc_en",
+						  ccm + CCM_CSCDR1, 20, 2);
+	clk[VF610_CLK_VADC_DIV_HALF] = imx_clk_fixed_factor("vadc_div_half",
+							    "vadc_div",
+							    1, 2);
+	clk[VF610_CLK_VADC] = imx_clk_gate2("vadc", "vadc_div",
+					    ccm + CCM_CCGR8,
+					    vf610_ccm_ccgrx_cgn(7));
+}
+
+
+static void vf610_ccm_setup_adcs(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	clk[VF610_CLK_ADC0] = imx_clk_gate2("adc0", "ipg_bus",
+					    ccm + CCM_CCGR1,
+					    vf610_ccm_ccgrx_cgn(11));
+	clk[VF610_CLK_ADC1] = imx_clk_gate2("adc1", "ipg_bus",
+					    ccm + CCM_CCGR7,
+					    vf610_ccm_ccgrx_cgn(11));
+	clk[VF610_CLK_DAC0] = imx_clk_gate2("dac0", "ipg_bus",
+					    ccm + CCM_CCGR8,
+					    vf610_ccm_ccgrx_cgn(12));
+	clk[VF610_CLK_DAC1] = imx_clk_gate2("dac1", "ipg_bus",
+					    ccm + CCM_CCGR8,
+					    vf610_ccm_ccgrx_cgn(13));
+}
+
+static void vf610_ccm_setup_flexcans(struct device_node *np,
+				     void __iomem *anatop,
+				     void __iomem *ccm)
+{
+	clk[VF610_CLK_FLEXCAN0_EN] = imx_clk_gate("flexcan0_en", "ipg_bus",
+						  ccm + CCM_CSCDR2, 11);
+	clk[VF610_CLK_FLEXCAN0] = imx_clk_gate2("flexcan0", "flexcan0_en",
+						ccm + CCM_CCGR0,
+						vf610_ccm_ccgrx_cgn(0));
+	clk[VF610_CLK_FLEXCAN1_EN] = imx_clk_gate("flexcan1_en", "ipg_bus",
+						  ccm + CCM_CSCDR2, 12);
+	clk[VF610_CLK_FLEXCAN1] = imx_clk_gate2("flexcan1", "flexcan1_en",
+						ccm + CCM_CCGR9,
+						vf610_ccm_ccgrx_cgn(4));
+}
+
+static void vf610_ccm_setup_dmas(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	clk[VF610_CLK_DMAMUX0] = imx_clk_gate2("dmamux0", "platform_bus",
+					       ccm + CCM_CCGR0,
+					       vf610_ccm_ccgrx_cgn(4));
+	clk[VF610_CLK_DMAMUX1] = imx_clk_gate2("dmamux1", "platform_bus",
+					       ccm + CCM_CCGR0,
+					       vf610_ccm_ccgrx_cgn(5));
+	clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus",
+					       ccm + CCM_CCGR6,
+					       vf610_ccm_ccgrx_cgn(1));
+	clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus",
+					       ccm + CCM_CCGR6,
+					       vf610_ccm_ccgrx_cgn(2));
+}
+
+static void vf610_ccm_setup_misc(struct device_node *np,
+				 void __iomem *anatop,
+				 void __iomem *ccm)
+{
+	clk[VF610_CLK_ASRC] = imx_clk_gate2("asrc", "ipg_bus",
+					    ccm + CCM_CCGR4,
+					    vf610_ccm_ccgrx_cgn(1));
+	clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus",
+					    ccm + CCM_CCGR6,
+					    vf610_ccm_ccgrx_cgn(7));
+	clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus",
+					  ccm + CCM_CCSR, 24);
+	clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus",
+					    ccm + CCM_CCGR6,
+					    vf610_ccm_ccgrx_cgn(5));
+
+	clk[VF610_CLK_LVDS1_IN] = imx_clk_gate_exclusive("lvds1_in",
+							 "anaclk1",
+							 anatop + ANA_MISC1,
+							 12, BIT(10));
+}
+
+typedef void (*vf610_ccm_group_setup_func) (struct device_node *np,
+					    void __iomem *anatop,
+					    void __iomem *ccm);
+
+static void __init vf610_clocks_init(struct device_node *np)
+{
+	size_t i;
+	struct device_node *node;
+	void __iomem *anatop;
+	void __iomem *ccm;
+
+	static const vf610_ccm_group_setup_func group_setup_funcs[] = {
+		vf610_ccm_setup_fixed,
+		vf610_ccm_setup_from_dt,
+		vf610_ccm_setup_slow_clk,
+		vf610_ccm_setup_fast_clk,
+		vf610_ccm_setup_pll_bypass_srcs,
+		vf610_ccm_setup_plls,
+		vf610_ccm_setup_pll_bypass,
+		vf610_ccm_setup_group1,
+		vf610_ccm_setup_pfds,
+		vf610_ccm_setup_pll1_pfd_out,
+		vf610_ccm_setup_pll2_pfd_out,
+		vf610_ccm_setup_sys_out,
+		vf610_ccm_setup_ddr_out,
+		vf610_ccm_setup_dividers,
+		vf610_ccm_setup_pll4_main_div,
+		vf610_ccm_setup_ddrmc,
+		vf610_ccm_setup_wkpu,
+		vf610_ccm_setup_usbphys,
+		vf610_ccm_setup_usbcs,
+		vf610_ccm_setup_qspis,
+		vf610_ccm_setup_enets,
+		vf610_ccm_setup_pit,
+		vf610_ccm_setup_uarts,
+		vf610_ccm_setup_i2cs,
+		vf610_ccm_setup_dspis,
+		vf610_ccm_setup_wdt,
+		vf610_ccm_setup_esdhcs,
+		vf610_ccm_setup_ftms,
+		vf610_ccm_setup_dcus,
+		vf610_ccm_setup_tcons,
+		vf610_ccm_setup_esai,
+		vf610_ccm_setup_sais,
+		vf610_ccm_setup_nfc,
+		vf610_ccm_setup_gpu,
+		vf610_ccm_setup_vadc,
+		vf610_ccm_setup_adcs,
+		vf610_ccm_setup_flexcans,
+		vf610_ccm_setup_dmas,
+		vf610_ccm_setup_misc,
+	};
+
+	ccm = of_iomap(np, 0);
+	BUG_ON(!ccm);
+
+	node = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop");
+	anatop = of_iomap(node, 0);
+	/* anatop = syscon_base_lookup_by_phandle(np, "fsl,anatop"); */
+	BUG_ON(IS_ERR(anatop));
+
+	for (i = 0; i < ARRAY_SIZE(group_setup_funcs); i++)
+		group_setup_funcs[i](np, anatop, ccm);
+
+	imx_check_clocks(clk, VF610_CLK_END);
+
+	/* Do not bypass PLLs initially */
+
+	clk_set_parent(clk[VF610_PLL1_BYPASS], clk[VF610_CLK_PLL1]);
+	clk_set_parent(clk[VF610_PLL2_BYPASS], clk[VF610_CLK_PLL2]);
+	clk_set_parent(clk[VF610_PLL3_BYPASS], clk[VF610_CLK_PLL3]);
+	clk_set_parent(clk[VF610_PLL4_BYPASS], clk[VF610_CLK_PLL4]);
+	clk_set_parent(clk[VF610_PLL5_BYPASS], clk[VF610_CLK_PLL5]);
+	clk_set_parent(clk[VF610_PLL6_BYPASS], clk[VF610_CLK_PLL6]);
+	clk_set_parent(clk[VF610_PLL7_BYPASS], clk[VF610_CLK_PLL7]);
+
+	clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X4_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI0_SEL]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X2_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI0_X4_DIV]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI0_X1_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI0_X2_DIV]) / 2);
+
+	clk_set_parent(clk[VF610_CLK_QSPI1_SEL], clk[VF610_CLK_PLL1_PFD4]);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X4_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI1_SEL]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X2_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI1_X4_DIV]) / 2);
+	clk_set_rate(clk[VF610_CLK_QSPI1_X1_DIV],
+		     clk_get_rate(clk[VF610_CLK_QSPI1_X2_DIV]) / 2);
+
+	clk_set_parent(clk[VF610_CLK_SAI0_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI1_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI2_SEL], clk[VF610_CLK_AUDIO_EXT]);
+	clk_set_parent(clk[VF610_CLK_SAI3_SEL], clk[VF610_CLK_AUDIO_EXT]);
+
+	clk_enable(clk[VF610_CLK_SYS_BUS]);
+	clk_enable(clk[VF610_CLK_DDR_SEL]);
+	clk_enable(clk[VF610_CLK_DAP]);
+	clk_enable(clk[VF610_CLK_DDRMC]);
+	clk_enable(clk[VF610_CLK_WKPU]);
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+}
+CLK_OF_DECLARE(vf610, "fsl,vf610-ccm", vf610_clocks_init);
-- 
2.5.5


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

^ permalink raw reply related

* [PATCH 14/20] i.MX: i2c-imx: Add Vybrid support
From: Andrey Smirnov @ 2016-10-03 14:40 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1475505657-898-1-git-send-email-andrew.smirnov@gmail.com>

Vybrid flavour of the I2C controller requires some additional quirks on
part of the driver. This commit ports those quirks code from analogous
Linux kernel driver.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 drivers/i2c/busses/i2c-imx.c | 215 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 160 insertions(+), 55 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index e407896..dbc76c2 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -43,6 +43,7 @@
 #include <linux/err.h>
 #include <pinctrl.h>
 #include <of_gpio.h>
+#include <of_device.h>
 
 #include <io.h>
 #include <i2c/i2c.h>
@@ -54,14 +55,25 @@
 /* Default value */
 #define FSL_I2C_BIT_RATE	100000	/* 100kHz */
 
-/* FSL I2C registers */
+/* IMX I2C registers:
+ * the I2C register offset is different between SoCs,
+ * to provid support for all these chips, split the
+ * register offset into a fixed base address and a
+ * variable shift value, then the full register offset
+ * will be calculated by
+ * reg_off = ( reg_base_addr << reg_shift)
+ */
 #define FSL_I2C_IADR	0x00	/* i2c slave address */
-#define FSL_I2C_IFDR	0x04	/* i2c frequency divider */
-#define FSL_I2C_I2CR	0x08	/* i2c control */
-#define FSL_I2C_I2SR	0x0C	/* i2c status */
-#define FSL_I2C_I2DR	0x10	/* i2c transfer data */
+#define FSL_I2C_IFDR	0x01	/* i2c frequency divider */
+#define FSL_I2C_I2CR	0x02	/* i2c control */
+#define FSL_I2C_I2SR	0x03	/* i2c status */
+#define FSL_I2C_I2DR	0x04	/* i2c transfer data */
 #define FSL_I2C_DFSRR	0x14	/* i2c digital filter sampling rate */
 
+#define IMX_I2C_REGSHIFT	2
+#define VF610_I2C_REGSHIFT	0
+
+
 /* Bits of FSL I2C registers */
 #define I2SR_RXAK	0x01
 #define I2SR_IIF	0x02
@@ -77,6 +89,22 @@
 #define I2CR_IIEN	0x40
 #define I2CR_IEN	0x80
 
+/* register bits different operating codes definition:
+ * 1) I2SR: Interrupt flags clear operation differ between SoCs:
+ * - write zero to clear(w0c) INT flag on i.MX,
+ * - but write one to clear(w1c) INT flag on Vybrid.
+ * 2) I2CR: I2C module enable operation also differ between SoCs:
+ * - set I2CR_IEN bit enable the module on i.MX,
+ * - but clear I2CR_IEN bit enable the module on Vybrid.
+ */
+#define I2SR_CLR_OPCODE_W0C	0x0
+#define I2SR_CLR_OPCODE_W1C	(I2SR_IAL | I2SR_IIF)
+#define I2CR_IEN_OPCODE_0	0x0
+#define I2CR_IEN_OPCODE_1	I2CR_IEN
+
+#define I2C_PM_TIMEOUT		10 /* ms */
+
+
 /*
  * sorted list of clock divider, register value pairs
  * taken from table 26-5, p.26-9, Freescale i.MX
@@ -85,8 +113,14 @@
  *
  * Duplicated divider values removed from list
  */
+struct fsl_i2c_clk_pair {
+	u16	div;
+	u16	val;
+};
+
 #ifndef CONFIG_PPC
-static u16 i2c_clk_div[50][2] = {
+
+static struct fsl_i2c_clk_pair imx_i2c_clk_div[] = {
 	{ 22,	0x20 }, { 24,	0x21 }, { 26,	0x22 }, { 28,	0x23 },
 	{ 30,	0x00 },	{ 32,	0x24 }, { 36,	0x25 }, { 40,	0x26 },
 	{ 42,	0x03 }, { 44,	0x27 },	{ 48,	0x28 }, { 52,	0x05 },
@@ -101,8 +135,36 @@ static u16 i2c_clk_div[50][2] = {
 	{ 1920,	0x1B },	{ 2048,	0x3F }, { 2304,	0x1C }, { 2560,	0x1D },
 	{ 3072,	0x1E }, { 3840,	0x1F }
 };
+
+/* Vybrid VF610 clock divider, register value pairs */
+static struct fsl_i2c_clk_pair vf610_i2c_clk_div[] = {
+	{ 20,   0x00 }, { 22,   0x01 }, { 24,   0x02 }, { 26,   0x03 },
+	{ 28,   0x04 }, { 30,   0x05 }, { 32,   0x09 }, { 34,   0x06 },
+	{ 36,   0x0A }, { 40,   0x07 }, { 44,   0x0C }, { 48,   0x0D },
+	{ 52,   0x43 }, { 56,   0x0E }, { 60,   0x45 }, { 64,   0x12 },
+	{ 68,   0x0F }, { 72,   0x13 }, { 80,   0x14 }, { 88,   0x15 },
+	{ 96,   0x19 }, { 104,  0x16 }, { 112,  0x1A }, { 128,  0x17 },
+	{ 136,  0x4F }, { 144,  0x1C }, { 160,  0x1D }, { 176,  0x55 },
+	{ 192,  0x1E }, { 208,  0x56 }, { 224,  0x22 }, { 228,  0x24 },
+	{ 240,  0x1F }, { 256,  0x23 }, { 288,  0x5C }, { 320,  0x25 },
+	{ 384,  0x26 }, { 448,  0x2A }, { 480,  0x27 }, { 512,  0x2B },
+	{ 576,  0x2C }, { 640,  0x2D }, { 768,  0x31 }, { 896,  0x32 },
+	{ 960,  0x2F }, { 1024, 0x33 }, { 1152, 0x34 }, { 1280, 0x35 },
+	{ 1536, 0x36 }, { 1792, 0x3A }, { 1920, 0x37 }, { 2048, 0x3B },
+	{ 2304, 0x3C }, { 2560, 0x3D }, { 3072, 0x3E }, { 3584, 0x7A },
+	{ 3840, 0x3F }, { 4096, 0x7B }, { 5120, 0x7D }, { 6144, 0x7E },
+};
+
 #endif
 
+struct fsl_i2c_hwdata {
+	unsigned		regshift;
+	struct fsl_i2c_clk_pair	*clk_div;
+	unsigned		ndivs;
+	unsigned		i2sr_clr_opcode;
+	unsigned		i2cr_ien_opcode;
+};
+
 struct fsl_i2c_struct {
 	void __iomem		*base;
 	struct clk		*clk;
@@ -112,6 +174,7 @@ struct fsl_i2c_struct {
 	unsigned int		ifdr;	/* FSL_I2C_IFDR */
 	unsigned int		dfsrr;  /* FSL_I2C_DFSRR */
 	struct i2c_bus_recovery_info rinfo;
+	const struct fsl_i2c_hwdata *hwdata;
 };
 #define to_fsl_i2c_struct(a)	container_of(a, struct fsl_i2c_struct, adapter)
 
@@ -144,16 +207,28 @@ static inline void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 }
 #endif
 
+static inline void fsl_i2c_write_reg(unsigned int val,
+				     struct fsl_i2c_struct *i2c_fsl,
+				     unsigned int reg)
+{
+	writeb(val, i2c_fsl->base + (reg << i2c_fsl->hwdata->regshift));
+}
+
+static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c_struct *i2c_fsl,
+					     unsigned int reg)
+{
+	return readb(i2c_fsl->base + (reg << i2c_fsl->hwdata->regshift));
+}
+
 static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 	unsigned int temp;
 
 	start = get_time_ns();
 	while (1) {
-		temp = readb(base + FSL_I2C_I2SR);
+		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (for_busy && (temp & I2SR_IBB))
 			break;
 		if (!for_busy && !(temp & I2SR_IBB))
@@ -172,12 +247,11 @@ static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
 static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 
 	start = get_time_ns();
 	while (1) {
-		unsigned int reg = readb(base + FSL_I2C_I2SR);
+		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (reg & I2SR_IIF)
 			break;
 
@@ -186,7 +260,9 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 			return -EIO;
 		}
 	}
-	writeb(0, base + FSL_I2C_I2SR);
+
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
 
 	return 0;
 }
@@ -194,12 +270,11 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 static int i2c_fsl_acked(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	uint64_t start;
 
 	start = get_time_ns();
 	while (1) {
-		unsigned int reg = readb(base + FSL_I2C_I2SR);
+		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
 		if (!(reg & I2SR_RXAK))
 			break;
 
@@ -215,25 +290,28 @@ static int i2c_fsl_acked(struct i2c_adapter *adapter)
 static int i2c_fsl_start(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	unsigned int temp = 0;
 	int result;
 
-	writeb(i2c_fsl->ifdr, base + FSL_I2C_IFDR);
+	fsl_i2c_write_reg(i2c_fsl->ifdr, i2c_fsl, FSL_I2C_IFDR);
+#ifdef CONFIG_PPC
 	if (i2c_fsl->dfsrr != -1)
 		writeb(i2c_fsl->dfsrr, base + FSL_I2C_DFSRR);
+#endif
 
 	/* Enable I2C controller */
-	writeb(0, base + FSL_I2C_I2SR);
-	writeb(I2CR_IEN, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode,
+			  i2c_fsl, FSL_I2C_I2CR);
 
 	/* Wait controller to be stable */
 	udelay(100);
 
 	/* Start I2C transaction */
-	temp = readb(base + FSL_I2C_I2CR);
+	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 	temp |= I2CR_MSTA;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 	result = i2c_fsl_bus_busy(adapter, 1);
 	if (result) {
@@ -246,7 +324,7 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	i2c_fsl->stopped = 0;
 
 	temp |= I2CR_MTX | I2CR_TXAK;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 	return result;
 }
@@ -254,14 +332,13 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 static void i2c_fsl_stop(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	unsigned int temp = 0;
 
 	if (!i2c_fsl->stopped) {
 		/* Stop I2C transaction */
-		temp = readb(base + FSL_I2C_I2CR);
+		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
-		writeb(temp, base + FSL_I2C_I2CR);
+		fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 		/* wait for the stop condition to be send, otherwise the i2c
 		 * controller is disabled before the STOP is sent completely */
 		i2c_fsl->stopped = i2c_fsl_bus_busy(adapter, 0) ? 0 : 1;
@@ -273,7 +350,8 @@ static void i2c_fsl_stop(struct i2c_adapter *adapter)
 	}
 
 	/* Disable I2C controller, and force our state to stopped */
-	writeb(0, base + FSL_I2C_I2CR);
+	temp = i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 }
 
 #ifdef CONFIG_PPC
@@ -349,6 +427,7 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 			    unsigned int rate)
 {
+	struct fsl_i2c_clk_pair *i2c_clk_div = i2c_fsl->hwdata->clk_div;
 	unsigned int i2c_clk_rate;
 	unsigned int div;
 	int i;
@@ -356,16 +435,16 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 	/* Divider value calculation */
 	i2c_clk_rate = clk_get_rate(i2c_fsl->clk);
 	div = (i2c_clk_rate + rate - 1) / rate;
-	if (div < i2c_clk_div[0][0])
+	if (div < i2c_clk_div[0].div)
 		i = 0;
-	else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0])
-		i = ARRAY_SIZE(i2c_clk_div) - 1;
+	else if (div > i2c_clk_div[i2c_fsl->hwdata->ndivs - 1].div)
+		i = i2c_clk_div[i2c_fsl->hwdata->ndivs - 1].div - 1;
 	else
-		for (i = 0; i2c_clk_div[i][0] < div; i++)
+		for (i = 0; i2c_clk_div[i].div < div; i++)
 			;
 
 	/* Store divider value */
-	i2c_fsl->ifdr = i2c_clk_div[i][1];
+	i2c_fsl->ifdr = i2c_clk_div[i].val;
 
 	/*
 	 * There dummy delay is calculated.
@@ -374,20 +453,19 @@ static void i2c_fsl_set_clk(struct fsl_i2c_struct *i2c_fsl,
 	 * to fix chip hardware bug.
 	 */
 	i2c_fsl->disable_delay =
-		(500000U * i2c_clk_div[i][0] + (i2c_clk_rate / 2) - 1) /
+		(500000U * i2c_clk_div[i].div + (i2c_clk_rate / 2) - 1) /
 		(i2c_clk_rate / 2);
 
 	dev_dbg(&i2c_fsl->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
 		__func__, i2c_clk_rate, div);
 	dev_dbg(&i2c_fsl->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
-		__func__, i2c_clk_div[i][1], i2c_clk_div[i][0]);
+		__func__, i2c_clk_div[i].val, i2c_clk_div[i].div);
 }
 #endif
 
 static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	int i, result;
 
 	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
@@ -396,7 +474,8 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, msgs->addr << 1);
 
 		/* write slave address */
-		writeb(msgs->addr << 1, base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->addr << 1, i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -411,7 +490,8 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 		dev_dbg(&adapter->dev,
 			"<%s> write byte: B%d=0x%02X\n",
 			__func__, i, msgs->buf[i]);
-		writeb(msgs->buf[i], base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg(msgs->buf[i], i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -426,12 +506,12 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
 	int i, result;
 	unsigned int temp;
 
 	/* clear IIF */
-	writeb(0x0, base + FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
+			  i2c_fsl, FSL_I2C_I2SR);
 
 	if ( !(msgs->flags & I2C_M_DATA_ONLY) ) {
 		dev_dbg(&adapter->dev,
@@ -439,7 +519,8 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			__func__, (msgs->addr << 1) | 0x01);
 
 		/* write slave address */
-		writeb((msgs->addr << 1) | 0x01, base + FSL_I2C_I2DR);
+		fsl_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_fsl,
+				  FSL_I2C_I2DR);
 
 		result = i2c_fsl_trx_complete(adapter);
 		if (result)
@@ -450,13 +531,13 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 	}
 
 	/* setup bus to read data */
-	temp = readb(base + FSL_I2C_I2CR);
+	temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 	temp &= ~I2CR_MTX;
 	if (msgs->len - 1)
 		temp &= ~I2CR_TXAK;
-	writeb(temp, base + FSL_I2C_I2CR);
+	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
-	readb(base + FSL_I2C_I2DR);	/* dummy read */
+	fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR); /* dummy read */
 
 	/* read data */
 	for (i = 0; i < msgs->len; i++) {
@@ -469,9 +550,9 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			 * It must generate STOP before read I2DR to prevent
 			 * controller from generating another clock cycle
 			 */
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp &= ~(I2CR_MSTA | I2CR_MTX);
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 			/*
 			 * adding this delay helps on low bitrates
@@ -481,11 +562,11 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
 			i2c_fsl_bus_busy(adapter, 0);
 			i2c_fsl->stopped = 1;
 		} else if (i == (msgs->len - 2)) {
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_TXAK;
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 		}
-		msgs->buf[i] = readb(base + FSL_I2C_I2DR);
+		msgs->buf[i] = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2DR);
 
 		dev_dbg(&adapter->dev, "<%s> read byte: B%d=0x%02X\n",
 			__func__, i, msgs->buf[i]);
@@ -497,7 +578,7 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 			struct i2c_msg *msgs, int num)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	void __iomem *base = i2c_fsl->base;
+
 	unsigned int i, temp;
 	int result;
 
@@ -514,9 +595,9 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 	/* read/write data */
 	for (i = 0; i < num; i++) {
 		if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) {
-			temp = readb(base + FSL_I2C_I2CR);
+			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
 			temp |= I2CR_RSTA;
-			writeb(temp, base + FSL_I2C_I2CR);
+			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
 			result = i2c_fsl_bus_busy(adapter, 1);
 			if (result)
@@ -600,6 +681,13 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 		goto fail;
 	}
 #endif
+
+	i2c_fsl->hwdata = of_device_get_match_data(pdev);
+	if (!i2c_fsl->hwdata) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
 	/* Setup i2c_fsl driver structure */
 	i2c_fsl->adapter.master_xfer = i2c_fsl_xfer;
 	i2c_fsl->adapter.nr = pdev->id;
@@ -623,8 +711,9 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 		i2c_fsl_set_clk(i2c_fsl, FSL_I2C_BIT_RATE);
 
 	/* Set up chip registers to defaults */
-	writeb(0, i2c_fsl->base + FSL_I2C_I2CR);
-	writeb(0, i2c_fsl->base + FSL_I2C_I2SR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
+			  i2c_fsl, FSL_I2C_I2CR);
+	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode, i2c_fsl, FSL_I2C_I2SR);
 
 	/* Add I2C adapter */
 	ret = i2c_add_numbered_adapter(&i2c_fsl->adapter);
@@ -640,12 +729,28 @@ fail:
 	return ret;
 }
 
+static const struct fsl_i2c_hwdata imx21_i2c_hwdata = {
+	.regshift		= IMX_I2C_REGSHIFT,
+	.clk_div		= imx_i2c_clk_div,
+	.ndivs			= ARRAY_SIZE(imx_i2c_clk_div),
+	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W0C,
+	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_1,
+
+};
+
+static const struct fsl_i2c_hwdata vf610_i2c_hwdata = {
+	.regshift		= VF610_I2C_REGSHIFT,
+	.clk_div		= vf610_i2c_clk_div,
+	.ndivs			= ARRAY_SIZE(vf610_i2c_clk_div),
+	.i2sr_clr_opcode	= I2SR_CLR_OPCODE_W1C,
+	.i2cr_ien_opcode	= I2CR_IEN_OPCODE_0,
+
+};
+
 static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = {
-	{
-		.compatible = "fsl,imx21-i2c",
-	}, {
-		/* sentinel */
-	}
+	{ .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
+	{ .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
+	{ /* sentinel */ }
 };
 
 static struct driver_d i2c_fsl_driver = {
-- 
2.5.5


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

^ permalink raw reply related

* [PATCH 04/20] i.MX: Add support for VF610 Tower board
From: Andrey Smirnov @ 2016-10-03 14:40 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1475505657-898-1-git-send-email-andrew.smirnov@gmail.com>

Add support for VF610 Tower board.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/boards/Makefile                           |   3 +-
 arch/arm/boards/freescale-vf610-twr/Makefile       |   4 +
 arch/arm/boards/freescale-vf610-twr/board.c        |  61 +++++
 .../flash-header-vf610-twr.imxcfg                  | 277 +++++++++++++++++++++
 arch/arm/boards/freescale-vf610-twr/lowlevel.c     |  45 ++++
 arch/arm/dts/Makefile                              |   1 +
 arch/arm/dts/vf610-twr.dts                         |  14 ++
 arch/arm/mach-imx/Kconfig                          |   4 +
 arch/arm/mach-imx/include/mach/clock-vf610.h       | 215 ++++++++++++++++
 arch/arm/mach-imx/include/mach/iomux-vf610.h       | 258 +++++++++++++++++++
 images/Makefile.imx                                |   5 +
 11 files changed, 886 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
 create mode 100644 arch/arm/boards/freescale-vf610-twr/board.c
 create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
 create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
 create mode 100644 arch/arm/dts/vf610-twr.dts
 create mode 100644 arch/arm/mach-imx/include/mach/clock-vf610.h
 create mode 100644 arch/arm/mach-imx/include/mach/iomux-vf610.h

diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 23a8dbd..c8bc565 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK)		+= at91sam9260ek/
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK)		+= at91sam9m10g45ek/
 obj-$(CONFIG_MACH_AT91SAM9M10IHD)		+= at91sam9m10ihd/
 obj-$(CONFIG_MACH_AT91SAM9N12EK)		+= at91sam9n12ek/
-obj-$(CONFIG_MACH_AT91SAM9X5EK)			+= at91sam9x5ek/
+nobj-$(CONFIG_MACH_AT91SAM9X5EK)			+= at91sam9x5ek/
 obj-$(CONFIG_MACH_BEAGLE)			+= beagle/
 obj-$(CONFIG_MACH_BEAGLEBONE)			+= beaglebone/
 obj-$(CONFIG_MACH_CANON_A1100)			+= canon-a1100/
@@ -138,3 +138,4 @@ obj-$(CONFIG_MACH_ZEDBOARD)			+= avnet-zedboard/
 obj-$(CONFIG_MACH_ZYLONITE)			+= zylonite/
 obj-$(CONFIG_MACH_VARISCITE_MX6)		+= variscite-mx6/
 obj-$(CONFIG_MACH_QEMU_VIRT64)			+= qemu-virt64/
+obj-$(CONFIG_MACH_VF610_TWR)			+= freescale-vf610-twr/
diff --git a/arch/arm/boards/freescale-vf610-twr/Makefile b/arch/arm/boards/freescale-vf610-twr/Makefile
new file mode 100644
index 0000000..32a7da5
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/Makefile
@@ -0,0 +1,4 @@
+obj-y += board.o
+obj-y += flash-header-vf610-twr.dcd.o
+extra-y += flash-header-vf610-twr.dcd.S flash-header-vf610-twr.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/freescale-vf610-twr/board.c b/arch/arm/boards/freescale-vf610-twr/board.c
new file mode 100644
index 0000000..0879f74
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/board.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <config.h>
+#include <common.h>
+#include <dma.h>
+#include <driver.h>
+#include <init.h>
+#include <of.h>
+#include <malloc.h>
+#include <mci.h>
+#include <clock.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+/*
+ * Make sure that esdhc1's clock divider is 1
+ */
+static int vf610_twr_sdhc1_clock_init(void)
+{
+	int err;
+	struct clk *esdhc1_div, *esdhc1_div_parent;
+
+	if (!of_machine_is_compatible("fsl,vf610-twr"))
+		return 0;
+
+	esdhc1_div = clk_lookup("esdhc1_div");
+
+	if (IS_ERR(esdhc1_div))
+		return PTR_ERR(esdhc1_div);
+
+	esdhc1_div_parent = clk_get_parent(esdhc1_div);
+	if (IS_ERR(esdhc1_div_parent))
+		return PTR_ERR(esdhc1_div_parent);
+
+	err = clk_set_rate(esdhc1_div,
+			   clk_get_rate(esdhc1_div_parent));
+	if (err)
+		return err;
+
+	clk_put(esdhc1_div);
+
+	return 0;
+}
+coredevice_initcall(vf610_twr_sdhc1_clock_init);
diff --git a/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
new file mode 100644
index 0000000..18138d2
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
@@ -0,0 +1,277 @@
+soc vf610
+loadaddr 0x80000000
+dcdofs 0x400
+
+#define VF610_DDR_PAD_CTRL	0x00000180 /* 25 Ohm drive strength */
+#define VF610_DDR_PAD_CTRL_1	0x00010180 /* 25 Ohm drive strength + differential input */
+
+#define DDRMC_PHY_DQ_TIMING	0x00002613
+#define DDRMC_PHY_DQS_TIMING	0x00002615
+#define DDRMC_PHY_CTRL		0x00210000
+#define DDRMC_PHY_MASTER_CTRL	0x0001012a
+#define DDRMC_PHY_SLAVE_CTRL	0x00002000
+#define DDRMC_PHY_OFF		0x00000000
+#define DDRMC_PHY_PROC_PAD_ODT	0x00010101
+
+#ifdef DEBUG
+#define CHECKPOINT(n) wm 32 0x3f000000 n
+#else
+#define CHECKPOINT(n)
+#endif
+
+CHECKPOINT(1)
+
+/* ======================= Clock initialization =======================*/
+
+/*
+ * Ungate all IP block clocks
+ */
+wm 32 0x4006b040 0xffffffff
+wm 32 0x4006b044 0xffffffff
+wm 32 0x4006b048 0xffffffff
+wm 32 0x4006b04c 0xffffffff
+wm 32 0x4006b050 0xffffffff
+wm 32 0x4006b058 0xffffffff
+wm 32 0x4006b05c 0xffffffff
+wm 32 0x4006b060 0xffffffff
+wm 32 0x4006b064 0xffffffff
+wm 32 0x4006b068 0xffffffff
+wm 32 0x4006b06c 0xffffffff
+
+
+/*
+ * We have to options to clock DDR controller:
+ *
+ *  - Use Core-A5 clock
+ *  - Use PLL2 PFD2 clock
+ *
+
+ * Using first option without changing PLL settings doesn't seem to be
+ * possible given that DDRMC requires minimum of 300Mhz and MaskROM
+ * configures it to be clocked at 264Mhz. Changing PLL1 settings
+ * proved to be challenging becuase MaskROM code executing this DCD
+ * will also be fetching the rest of the bootloader via some
+ * peripheral interface whose clock is derived from Cortex-A5 clock.
+ *
+ * As a result this DCD configuration code uses the second option of
+ * clocking DDR wiht PLL2 PFD2 clock output
+ *
+ * Turn PLL2 on
+ */
+wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */
+
+CHECKPOINT(2)
+
+/*
+ * Wait for PLLs to lock
+ */
+check 32 while_any_bit_clear 0x40050030 0x80000000
+
+
+CHECKPOINT(3)
+
+/*
+ * Switch DDRMC to be clocked with PLL2 PFD2 and enable PFD2 output
+ */
+clear_bits 32 0x4006b008 0x00000040
+set_bits   32 0x4006b008 0x00002000
+
+
+
+/* ======================= DDR IOMUX ======================= */
+
+CHECKPOINT(4)
+
+wm 32 0x40048220 VF610_DDR_PAD_CTRL
+wm 32 0x40048224 VF610_DDR_PAD_CTRL
+wm 32 0x40048228 VF610_DDR_PAD_CTRL
+wm 32 0x4004822c VF610_DDR_PAD_CTRL
+wm 32 0x40048230 VF610_DDR_PAD_CTRL
+wm 32 0x40048234 VF610_DDR_PAD_CTRL
+wm 32 0x40048238 VF610_DDR_PAD_CTRL
+wm 32 0x4004823c VF610_DDR_PAD_CTRL
+wm 32 0x40048240 VF610_DDR_PAD_CTRL
+wm 32 0x40048244 VF610_DDR_PAD_CTRL
+wm 32 0x40048248 VF610_DDR_PAD_CTRL
+wm 32 0x4004824c VF610_DDR_PAD_CTRL
+wm 32 0x40048250 VF610_DDR_PAD_CTRL
+wm 32 0x40048254 VF610_DDR_PAD_CTRL
+wm 32 0x40048258 VF610_DDR_PAD_CTRL
+wm 32 0x4004825c VF610_DDR_PAD_CTRL
+wm 32 0x40048260 VF610_DDR_PAD_CTRL
+wm 32 0x40048264 VF610_DDR_PAD_CTRL
+wm 32 0x40048268 VF610_DDR_PAD_CTRL
+wm 32 0x4004826c VF610_DDR_PAD_CTRL
+wm 32 0x40048270 VF610_DDR_PAD_CTRL
+wm 32 0x40048274 VF610_DDR_PAD_CTRL
+wm 32 0x40048278 VF610_DDR_PAD_CTRL
+wm 32 0x4004827c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048280 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048284 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048288 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004828c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048290 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048294 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048298 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004829c VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482ac VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482bc VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482cc VF610_DDR_PAD_CTRL
+wm 32 0x400482d0 VF610_DDR_PAD_CTRL
+wm 32 0x400482d4 VF610_DDR_PAD_CTRL
+wm 32 0x400482d8 VF610_DDR_PAD_CTRL
+wm 32 0x4004821c VF610_DDR_PAD_CTRL
+
+/* ======================= DDR Controller =======================*/
+
+CHECKPOINT(5)
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae008 0x00000020
+wm 32 0x400ae028 0x00013880
+wm 32 0x400ae02c 0x00030d40
+wm 32 0x400ae030 0x0000050c
+wm 32 0x400ae034 0x15040400
+wm 32 0x400ae038 0x1406040f
+wm 32 0x400ae040 0x04040000
+wm 32 0x400ae044 0x006db00c
+wm 32 0x400ae048 0x00000403
+wm 32 0x400ae050 0x01000000
+wm 32 0x400ae054 0x00060001
+wm 32 0x400ae058 0x000c0000
+wm 32 0x400ae05c 0x03000200
+wm 32 0x400ae060 0x00000006
+wm 32 0x400ae064 0x00010000
+wm 32 0x400ae068 0x0c30002c
+wm 32 0x400ae070 0x00000000
+wm 32 0x400ae074 0x00000003
+wm 32 0x400ae078 0x0000000a
+wm 32 0x400ae07c 0x003001d4
+wm 32 0x400ae084 0x00010000
+wm 32 0x400ae088 0x00050500
+wm 32 0x400ae098 0x00000000
+wm 32 0x400ae09c 0x04001002
+wm 32 0x400ae0a4 0x00000001
+wm 32 0x400ae0c0 0x00460420
+wm 32 0x400ae108 0x01000200
+wm 32 0x400ae10c 0x00000040
+wm 32 0x400ae114 0x00000200
+wm 32 0x400ae118 0x00000040
+wm 32 0x400ae120 0x00000000
+wm 32 0x400ae124 0x0a010300
+wm 32 0x400ae128 0x01014040
+wm 32 0x400ae12c 0x01010101
+wm 32 0x400ae130 0x03030100
+wm 32 0x400ae134 0x01000101
+wm 32 0x400ae138 0x0700000c
+wm 32 0x400ae13c 0x00000000
+wm 32 0x400ae148 0x10000000
+wm 32 0x400ae15c 0x01000000
+wm 32 0x400ae160 0x00040000
+wm 32 0x400ae164 0x00000002
+wm 32 0x400ae16c 0x00020000
+wm 32 0x400ae180 0x00002819
+wm 32 0x400ae184 0x01000000
+wm 32 0x400ae188 0x00000000
+wm 32 0x400ae18c 0x00000000
+wm 32 0x400ae198 0x00010100
+wm 32 0x400ae1a4 0x00000000
+wm 32 0x400ae1a8 0x00000004
+wm 32 0x400ae1b8 0x00040000
+wm 32 0x400ae1c8 0x00000000
+wm 32 0x400ae1cc 0x00000000
+wm 32 0x400ae1d4 0x00000000
+wm 32 0x400ae1d8 0x01010000
+wm 32 0x400ae1e0 0x02020000
+wm 32 0x400ae1e4 0x00000202
+wm 32 0x400ae1e8 0x01010064
+wm 32 0x400ae1ec 0x00010101
+wm 32 0x400ae1f0 0x00000064
+wm 32 0x400ae1f8 0x00000800
+wm 32 0x400ae210 0x00000506
+wm 32 0x400ae224 0x00020000
+wm 32 0x400ae228 0x01000000
+wm 32 0x400ae22c 0x04070303
+wm 32 0x400ae230 0x00000040
+wm 32 0x400ae23c 0x06000080
+wm 32 0x400ae240 0x04070303
+wm 32 0x400ae244 0x00000040
+wm 32 0x400ae248 0x00000040
+wm 32 0x400ae24c 0x000f0000
+wm 32 0x400ae250 0x000f0000
+wm 32 0x400ae25c 0x00000101
+wm 32 0x400ae268 0x682c4000
+wm 32 0x400ae26c 0x00000012
+wm 32 0x400ae278 0x00000006
+wm 32 0x400ae284 0x00010202
+
+/* ======================= DDR PHY =======================*/
+
+CHECKPOINT(6)
+
+wm 32 0x400ae400 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae440 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae480 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae404 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae444 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae408 DDRMC_PHY_CTRL
+wm 32 0x400ae448 DDRMC_PHY_CTRL
+wm 32 0x400ae488 DDRMC_PHY_CTRL
+wm 32 0x400ae40c DDRMC_PHY_CTRL
+wm 32 0x400ae44c DDRMC_PHY_CTRL
+wm 32 0x400ae48c DDRMC_PHY_CTRL
+wm 32 0x400ae410 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae450 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae490 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae4c4 DDRMC_PHY_OFF
+wm 32 0x400ae4c8 0x00001100
+wm 32 0x400ae4d0 DDRMC_PHY_PROC_PAD_ODT
+wm 32 0x400ae000 0x00000601
+
+CHECKPOINT(7)
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(8)
+
+/*
+ * Cargo cult DDR controller initialization here we come!
+ *
+ * Experemintation with VF610 Tower Board shows that without the
+ * following code the board would not boot off of SD card when
+ * power-cycled. It will however happily boot when reset via SW3/Reset
+ * button. For whatever reason the following actions appear to be
+ * necessary:
+ *
+ *          - Initialize DDRMC as usual
+ *	    - Issue a read to location in DDR address space
+ *	    - Disable DDRMC
+ *	    - Enable DDRMC and wait for it to finish initializing
+ *
+ * I am sure this is all going to be extrememly embarrassing to read
+ * if/when the real problem and real solution is found.
+ */
+
+/*
+ * Because there's no standalone read command what we do here instead
+ * is write a pattern to memory and then checking that memory address
+ * against that pattern
+ */
+wm 32 0x80000000 0xa5a5a5a5
+check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae000 0x00000601
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(9)
\ No newline at end of file
diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
new file mode 100644
index 0000000..6504273
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -0,0 +1,45 @@
+#include <common.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/vf610-regs.h>
+#include <mach/clock-vf610.h>
+#include <mach/iomux-vf610.h>
+#include <debug_ll.h>
+
+static inline void setup_uart(void)
+{
+	void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
+
+	vf610_ungate_all_peripherals();
+
+	/*
+	 * VF610_PAD_PTB4__UART1_TX
+	 */
+	writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
+	writel(0, iomuxbase + 0x0380);
+
+	vf610_uart_setup_ll();
+}
+
+extern char __dtb_vf610_twr_start[];
+
+ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
+{
+	int i;
+	void *fdt;
+	void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+
+	vf610_cpu_lowlevel_init();
+
+	for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++)
+		writew(VF610_MSCM_IRSPRC_CP0_EN,
+		       mscm + VF610_MSCM_IRSPRC(i));
+
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart();
+
+	fdt = __dtb_vf610_twr_start - get_runtime_offset();
+	barebox_arm_entry(0x80000000, SZ_128M, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index d1a3fe8..f93152c 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -76,5 +76,6 @@ pbl-dtb-$(CONFIG_MACH_TX6X) += imx6q-tx6q.dtb.o
 pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
 pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
 pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
+pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo
diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
new file mode 100644
index 0000000..54b4435
--- /dev/null
+++ b/arch/arm/dts/vf610-twr.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2013 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.
+ */
+
+#include <arm/vf610-twr.dts>
+
+&usbdev0 {
+	status = "disabled";
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 71862ef..0284a8f 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -332,6 +332,10 @@ config MACH_CM_FX6
 	bool "CM FX6"
 	select ARCH_IMX6
 
+config MACH_VF610_TWR
+	bool "Freescale VF610 Tower Board"
+	select ARCH_VF610
+
 endif
 
 # ----------------------------------------------------------
diff --git a/arch/arm/mach-imx/include/mach/clock-vf610.h b/arch/arm/mach-imx/include/mach/clock-vf610.h
new file mode 100644
index 0000000..b75309a
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/clock-vf610.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ARCH_ARM_MACH_VF610_CCM_REGS_H__
+#define __ARCH_ARM_MACH_VF610_CCM_REGS_H__
+
+
+#define VF610_CCM_CCR			(VF610_CCM_BASE_ADDR + 0x00)
+#define VF610_CCM_CSR			(VF610_CCM_BASE_ADDR + 0x04)
+#define VF610_CCM_CCSR			(VF610_CCM_BASE_ADDR + 0x08)
+#define VF610_CCM_CACRR			(VF610_CCM_BASE_ADDR + 0x0c)
+#define VF610_CCM_CSCMR1		(VF610_CCM_BASE_ADDR + 0x10)
+#define VF610_CCM_CSCDR1		(VF610_CCM_BASE_ADDR + 0x14)
+#define VF610_CCM_CSCDR2		(VF610_CCM_BASE_ADDR + 0x18)
+#define VF610_CCM_CSCDR3		(VF610_CCM_BASE_ADDR + 0x1c)
+#define VF610_CCM_CSCMR2		(VF610_CCM_BASE_ADDR + 0x20)
+#define VF610_CCM_CTOR		(VF610_CCM_BASE_ADDR + 0x28)
+#define VF610_CCM_CLPCR		(VF610_CCM_BASE_ADDR + 0x2c)
+#define VF610_CCM_CISR		(VF610_CCM_BASE_ADDR + 0x30)
+#define VF610_CCM_CIMR		(VF610_CCM_BASE_ADDR + 0x34)
+#define VF610_CCM_CCOSR		(VF610_CCM_BASE_ADDR + 0x38)
+#define VF610_CCM_CGPR		(VF610_CCM_BASE_ADDR + 0x3c)
+#define VF610_CCM_CCGR0		(VF610_CCM_BASE_ADDR + 0x40)
+#define VF610_CCM_CCGR1		(VF610_CCM_BASE_ADDR + 0x44)
+#define VF610_CCM_CCGR2		(VF610_CCM_BASE_ADDR + 0x48)
+#define VF610_CCM_CCGR3		(VF610_CCM_BASE_ADDR + 0x4c)
+#define VF610_CCM_CCGR4		(VF610_CCM_BASE_ADDR + 0x50)
+#define VF610_CCM_CCGR5		(VF610_CCM_BASE_ADDR + 0x54)
+#define VF610_CCM_CCGR6		(VF610_CCM_BASE_ADDR + 0x58)
+#define VF610_CCM_CCGR7		(VF610_CCM_BASE_ADDR + 0x5c)
+#define VF610_CCM_CCGR8		(VF610_CCM_BASE_ADDR + 0x60)
+#define VF610_CCM_CCGR9		(VF610_CCM_BASE_ADDR + 0x64)
+#define VF610_CCM_CCGR10		(VF610_CCM_BASE_ADDR + 0x68)
+#define VF610_CCM_CCGR11		(VF610_CCM_BASE_ADDR + 0x6c)
+#define VF610_CCM_CMEOR0		(VF610_CCM_BASE_ADDR + 0x70)
+#define VF610_CCM_CMEOR1		(VF610_CCM_BASE_ADDR + 0x74)
+#define VF610_CCM_CMEOR2		(VF610_CCM_BASE_ADDR + 0x78)
+#define VF610_CCM_CMEOR3		(VF610_CCM_BASE_ADDR + 0x7c)
+#define VF610_CCM_CMEOR4		(VF610_CCM_BASE_ADDR + 0x80)
+#define VF610_CCM_CMEOR5		(VF610_CCM_BASE_ADDR + 0x84)
+#define VF610_CCM_CPPDSR		(VF610_CCM_BASE_ADDR + 0x88)
+#define VF610_CCM_CCOWR			(VF610_CCM_BASE_ADDR + 0x8c)
+#define VF610_CCM_CCPGR0		(VF610_CCM_BASE_ADDR + 0x90)
+#define VF610_CCM_CCPGR1		(VF610_CCM_BASE_ADDR + 0x94)
+#define VF610_CCM_CCPGR2		(VF610_CCM_BASE_ADDR + 0x98)
+#define VF610_CCM_CCPGR3		(VF610_CCM_BASE_ADDR + 0x9c)
+
+#define VF610_CCM_CCGRx_CGn(n)	((n) * 2)
+
+/* #define VF610_ANADIG_PFD_PLL1_BASE	(VF610_ANADIG_BASE_ADDR + 0x2b0) */
+/* #define VF610_ANADIG_PFD_PLL2_BASE	(VF610_ANADIG_BASE_ADDR + 0x100) */
+/* #define VF610_ANADIG_PFD_PLL3_BASE	(VF610_ANADIG_BASE_ADDR + 0xf0) */
+#define VF610_ANADIG_PLL1_CTRL		(VF610_ANADIG_BASE_ADDR + 0x270)
+#define VF610_ANADIG_PLL1_NUM		(VF610_ANADIG_BASE_ADDR + 0x290)
+#define VF610_ANADIG_PLL1_DENOM		(VF610_ANADIG_BASE_ADDR + 0x2A0)
+#define VF610_ANADIG_PLL2_CTRL		(VF610_ANADIG_BASE_ADDR + 0x30)
+#define VF610_ANADIG_PLL2_NUM		(VF610_ANADIG_BASE_ADDR + 0x50)
+#define VF610_ANADIG_PLL3_CTRL		(VF610_ANADIG_BASE_ADDR + 0x10)
+#define VF610_ANADIG_PLL4_CTRL		(VF610_ANADIG_BASE_ADDR + 0x70)
+#define VF610_ANADIG_PLL5_CTRL		(VF610_ANADIG_BASE_ADDR + 0xe0)
+#define VF610_ANADIG_PLL6_CTRL		(VF610_ANADIG_BASE_ADDR + 0xa0)
+#define VF610_ANADIG_PLL7_CTRL		(VF610_ANADIG_BASE_ADDR + 0x20)
+#define VF610_ANADIG_ANA_MISC1		(VF610_ANADIG_BASE_ADDR + 0x160)
+#define VF610_ANADIG_LOCK		(VF610_ANADIG_BASE_ADDR + 0x2C0)
+
+#define CCM_CCR_FIRC_EN				(1 << 16)
+#define CCM_CCR_OSCNT_MASK			0xff
+#define CCM_CCR_OSCNT(v)			((v) & 0xff)
+
+#define CCM_CCSR_PLL2_PFD_CLK_SEL_OFFSET	19
+#define CCM_CCSR_PLL2_PFD_CLK_SEL_MASK		(0x7 << 19)
+#define CCM_CCSR_PLL2_PFD_CLK_SEL(v)		(((v) & 0x7) << 19)
+
+#define CCM_CCSR_PLL1_PFD_CLK_SEL_OFFSET	16
+#define CCM_CCSR_PLL1_PFD_CLK_SEL_MASK		(0x7 << 16)
+#define CCM_CCSR_PLL1_PFD_CLK_SEL(v)		(((v) & 0x7) << 16)
+
+#define CCM_CCSR_PLL2_PFD4_EN			(1 << 15)
+#define CCM_CCSR_PLL2_PFD3_EN			(1 << 14)
+#define CCM_CCSR_PLL2_PFD2_EN			(1 << 13)
+#define CCM_CCSR_PLL2_PFD1_EN			(1 << 12)
+#define CCM_CCSR_PLL1_PFD4_EN			(1 << 11)
+#define CCM_CCSR_PLL1_PFD3_EN			(1 << 10)
+#define CCM_CCSR_PLL1_PFD2_EN			(1 << 9)
+#define CCM_CCSR_PLL1_PFD1_EN			(1 << 8)
+
+#define CCM_CCSR_DDRC_CLK_SEL(v)		((v) << 6)
+#define CCM_CCSR_FAST_CLK_SEL(v)		((v) << 5)
+
+#define CCM_CCSR_SYS_CLK_SEL_OFFSET		0
+#define CCM_CCSR_SYS_CLK_SEL_MASK		0x7
+#define CCM_CCSR_SYS_CLK_SEL(v)			((v) & 0x7)
+
+#define CCM_CACRR_IPG_CLK_DIV_OFFSET		11
+#define CCM_CACRR_IPG_CLK_DIV_MASK		(0x3 << 11)
+#define CCM_CACRR_IPG_CLK_DIV(v)		(((v) & 0x3) << 11)
+#define CCM_CACRR_BUS_CLK_DIV_OFFSET		3
+#define CCM_CACRR_BUS_CLK_DIV_MASK		(0x7 << 3)
+#define CCM_CACRR_BUS_CLK_DIV(v)		(((v) & 0x7) << 3)
+#define CCM_CACRR_ARM_CLK_DIV_OFFSET		0
+#define CCM_CACRR_ARM_CLK_DIV_MASK		0x7
+#define CCM_CACRR_ARM_CLK_DIV(v)		((v) & 0x7)
+
+#define CCM_CSCMR1_QSPI0_CLK_SEL_OFFSET		22
+#define CCM_CSCMR1_QSPI0_CLK_SEL_MASK		(0x3 << 22)
+#define CCM_CSCMR1_QSPI0_CLK_SEL(v)		(((v) & 0x3) << 22)
+#define CCM_CSCMR1_ESDHC1_CLK_SEL_OFFSET	18
+#define CCM_CSCMR1_ESDHC1_CLK_SEL_MASK		(0x3 << 18)
+#define CCM_CSCMR1_ESDHC1_CLK_SEL(v)		(((v) & 0x3) << 18)
+#define CCM_CSCMR1_NFC_CLK_SEL_OFFSET		12
+#define CCM_CSCMR1_NFC_CLK_SEL_MASK		(0x3 << 12)
+#define CCM_CSCMR1_NFC_CLK_SEL(v)		(((v) & 0x3) << 12)
+
+#define CCM_CSCDR1_RMII_CLK_EN			(1 << 24)
+
+#define CCM_CSCDR2_NFC_EN			(1 << 9)
+#define CCM_CSCDR2_NFC_FRAC_DIV_EN		(1 << 13)
+#define CCM_CSCDR2_NFC_CLK_INV			(1 << 14)
+#define CCM_CSCDR2_NFC_FRAC_DIV_OFFSET		4
+#define CCM_CSCDR2_NFC_FRAC_DIV_MASK		(0xf << 4)
+#define CCM_CSCDR2_NFC_FRAC_DIV(v)		(((v) & 0xf) << 4)
+
+#define CCM_CSCDR2_ESDHC1_EN			(1 << 29)
+#define CCM_CSCDR2_ESDHC1_CLK_DIV_OFFSET	20
+#define CCM_CSCDR2_ESDHC1_CLK_DIV_MASK		(0xf << 20)
+#define CCM_CSCDR2_ESDHC1_CLK_DIV(v)		(((v) & 0xf) << 20)
+
+#define CCM_CSCDR3_NFC_PRE_DIV_OFFSET		13
+#define CCM_CSCDR3_NFC_PRE_DIV_MASK		(0x7 << 13)
+#define CCM_CSCDR3_NFC_PRE_DIV(v)		(((v) & 0x7) << 13)
+#define CCM_CSCDR3_QSPI0_EN			(1 << 4)
+#define CCM_CSCDR3_QSPI0_DIV(v)			((v) << 3)
+#define CCM_CSCDR3_QSPI0_X2_DIV(v)		((v) << 2)
+#define CCM_CSCDR3_QSPI0_X4_DIV(v)		((v) & 0x3)
+
+#define CCM_CSCMR2_RMII_CLK_SEL_OFFSET		4
+#define CCM_CSCMR2_RMII_CLK_SEL_MASK		(0x3 << 4)
+#define CCM_CSCMR2_RMII_CLK_SEL(v)		(((v) & 0x3) << 4)
+
+#define CCM_REG_CTRL_MASK			0xffffffff
+#define CCM_CCGR0_UART0_CTRL_MASK               (0x3 << 14)
+#define CCM_CCGR0_UART1_CTRL_MASK		(0x3 << 16)
+#define CCM_CCGR0_DSPI0_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR0_DSPI1_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR1_USBC0_CTRL_MASK       (0x3 << 8)
+#define CCM_CCGR1_PIT_CTRL_MASK			(0x3 << 14)
+#define CCM_CCGR1_WDOGA5_CTRL_MASK		(0x3 << 28)
+#define CCM_CCGR2_QSPI0_CTRL_MASK		(0x3 << 8)
+#define CCM_CCGR2_IOMUXC_CTRL_MASK		(0x3 << 16)
+#define CCM_CCGR2_PORTA_CTRL_MASK		(0x3 << 18)
+#define CCM_CCGR2_PORTB_CTRL_MASK		(0x3 << 20)
+#define CCM_CCGR2_PORTC_CTRL_MASK		(0x3 << 22)
+#define CCM_CCGR2_PORTD_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR2_PORTE_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR3_ANADIG_CTRL_MASK		0x3
+#define CCM_CCGR3_SCSC_CTRL_MASK        (0x3 << 4)
+#define CCM_CCGR4_WKUP_CTRL_MASK		(0x3 << 20)
+#define CCM_CCGR4_CCM_CTRL_MASK			(0x3 << 22)
+#define CCM_CCGR4_GPC_CTRL_MASK			(0x3 << 24)
+#define CCM_CCGR4_I2C0_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR4_I2C1_CTRL_MASK		(0x3 << 14)
+#define CCM_CCGR6_OCOTP_CTRL_MASK		(0x3 << 10)
+#define CCM_CCGR6_DSPI2_CTRL_MASK		(0x3 << 24)
+#define CCM_CCGR6_DSPI3_CTRL_MASK		(0x3 << 26)
+#define CCM_CCGR6_DDRMC_CTRL_MASK		(0x3 << 28)
+#define CCM_CCGR7_SDHC1_CTRL_MASK		(0x3 << 4)
+#define CCM_CCGR7_USBC1_CTRL_MASK       (0x3 << 8)
+#define CCM_CCGR9_FEC0_CTRL_MASK		0x3
+#define CCM_CCGR9_FEC1_CTRL_MASK		(0x3 << 2)
+#define CCM_CCGR10_NFC_CTRL_MASK		0x3
+#define CCM_CCGR10_I2C2_CTRL_MASK		(0x3 << 12)
+#define CCM_CCGR10_I2C3_CTRL_MASK		(0x3 << 14)
+
+#define ANADIG_PLL7_CTRL_BYPASS         (1 << 16)
+#define ANADIG_PLL7_CTRL_ENABLE         (1 << 13)
+#define ANADIG_PLL7_CTRL_POWERDOWN      (1 << 12)
+#define ANADIG_PLL7_CTRL_DIV_SELECT     (1 << 1)
+#define ANADIG_PLL5_CTRL_BYPASS                 (1 << 16)
+#define ANADIG_PLL5_CTRL_ENABLE                 (1 << 13)
+#define ANADIG_PLL5_CTRL_POWERDOWN              (1 << 12)
+#define ANADIG_PLL5_CTRL_DIV_SELECT		1
+#define ANADIG_PLL3_CTRL_BYPASS         (1 << 16)
+#define ANADIG_PLL3_CTRL_ENABLE         (1 << 13)
+#define ANADIG_PLL3_CTRL_POWERDOWN      (1 << 12)
+#define ANADIG_PLL3_CTRL_DIV_SELECT     (1 << 1)
+#define ANADIG_PLL2_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL2_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL2_CTRL_DIV_SELECT		1
+#define ANADIG_PLL1_CTRL_ENABLE			(1 << 13)
+#define ANADIG_PLL1_CTRL_POWERDOWN		(1 << 12)
+#define ANADIG_PLL1_CTRL_DIV_SELECT		1
+
+#define FASE_CLK_FREQ		24000000
+#define SLOW_CLK_FREQ		32000
+#define PLL1_PFD1_FREQ		500000000
+#define PLL1_PFD2_FREQ		452000000
+#define PLL1_PFD3_FREQ		396000000
+#define PLL1_PFD4_FREQ		528000000
+#define PLL1_MAIN_FREQ		528000000
+#define PLL2_PFD1_FREQ		500000000
+#define PLL2_PFD2_FREQ		396000000
+#define PLL2_PFD3_FREQ		339000000
+#define PLL2_PFD4_FREQ		413000000
+#define PLL2_MAIN_FREQ		528000000
+#define PLL3_MAIN_FREQ		480000000
+#define PLL3_PFD3_FREQ		298000000
+#define PLL5_MAIN_FREQ		500000000
+
+#define ENET_EXTERNAL_CLK	50000000
+#define AUDIO_EXTERNAL_CLK	24576000
+
+#endif /*__ARCH_ARM_MACH_VF610_CCM_REGS_H__ */
diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h
new file mode 100644
index 0000000..db0e59f
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __IOMUX_VF610_H__
+#define __IOMUX_VF610_H__
+
+#include <mach/iomux-v3.h>
+
+#undef PAD_CTL_ODE
+#undef PAD_CTL_PKE
+#undef PAD_CTL_PUE
+
+#define PAD_MUX_MODE_SHIFT	20
+
+#define PAD_CTL_INPUT_DIFFERENTIAL (1 << 16)
+
+#define PAD_CTL_SPEED_MED	(1 << 12)
+#define PAD_CTL_SPEED_HIGH	(3 << 12)
+
+#define PAD_CTL_SRE		(1 << 11)
+
+
+#define PAD_CTL_ODE		(1 << 10)
+
+#define PAD_CTL_DSE_150ohm	(1 << 6)
+#define PAD_CTL_DSE_50ohm	(3 << 6)
+#define PAD_CTL_DSE_25ohm	(6 << 6)
+#define PAD_CTL_DSE_20ohm	(7 << 6)
+
+#define PAD_CTL_PUS_47K_UP	(1 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_100K_UP	(2 << 4 | PAD_CTL_PUE)
+#define PAD_CTL_PUS_22K_UP	(3 << 4 | PAD_CTL_PUE)
+
+#define PAD_CTL_PKE		(1 << 3)
+#define PAD_CTL_PUE		(1 << 2 | PAD_CTL_PKE)
+
+#define PAD_CTL_OBE_IBE_ENABLE	(3 << 0)
+#define PAD_CTL_OBE_ENABLE	(1 << 1)
+#define PAD_CTL_IBE_ENABLE	(1 << 0)
+
+
+/* These 2 defines are for pins that may not have a mux register, but could
+ * have a pad setting register, and vice-versa. */
+#define __NA_	0x00
+
+
+
+/* Pad control groupings */
+#define VF610_UART_PAD_CTRL	(PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_25ohm | \
+				PAD_CTL_OBE_IBE_ENABLE)
+#define VF610_SDHC_PAD_CTRL	(PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_20ohm | \
+				PAD_CTL_OBE_IBE_ENABLE)
+#define VF610_ENET_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | \
+				PAD_CTL_OBE_IBE_ENABLE)
+#define VF610_DDR_PAD_CTRL	PAD_CTL_DSE_25ohm
+#define VF610_DDR_PAD_CTRL_1	(PAD_CTL_DSE_25ohm | \
+				PAD_CTL_INPUT_DIFFERENTIAL)
+#define VF610_I2C_PAD_CTRL	(PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_50ohm | \
+				PAD_CTL_SPEED_HIGH | PAD_CTL_ODE | \
+				PAD_CTL_OBE_IBE_ENABLE)
+#define VF610_NFC_IO_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
+				PAD_CTL_DSE_50ohm | PAD_CTL_PUS_47K_UP | \
+				PAD_CTL_OBE_IBE_ENABLE)
+#define VF610_NFC_CN_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
+				PAD_CTL_DSE_25ohm | PAD_CTL_OBE_ENABLE)
+#define VF610_NFC_RB_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_SRE | \
+				PAD_CTL_PUS_22K_UP | PAD_CTL_IBE_ENABLE)
+
+#define VF610_QSPI_PAD_CTRL	(PAD_CTL_SPEED_HIGH | PAD_CTL_DSE_150ohm | \
+				PAD_CTL_PUS_22K_UP | PAD_CTL_OBE_IBE_ENABLE)
+
+#define VF610_GPIO_PAD_CTRL	(PAD_CTL_SPEED_MED | PAD_CTL_DSE_50ohm | \
+				PAD_CTL_IBE_ENABLE)
+
+#define VF610_DSPI_PAD_CTRL	(PAD_CTL_OBE_ENABLE | PAD_CTL_DSE_20ohm | \
+				PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH)
+#define VF610_DSPI_SIN_PAD_CTRL	(PAD_CTL_IBE_ENABLE | PAD_CTL_DSE_20ohm | \
+				PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH)
+
+enum {
+	VF610_PAD_PTA6__RMII0_CLKIN		= IOMUX_PAD(0x0000, 0x0000, 2, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTA6__RMII0_CLKOUT		= IOMUX_PAD(0x0000, 0x0000, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTA7__GPIO_134		= IOMUX_PAD(0x0218, 0x0218, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA17__GPIO_7			= IOMUX_PAD(0x001c, 0x001c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA20__GPIO_10		= IOMUX_PAD(0x0028, 0x0028, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA21__GPIO_11		= IOMUX_PAD(0x002c, 0x002c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA30__GPIO_20		= IOMUX_PAD(0x0050, 0x0050, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA31__GPIO_21		= IOMUX_PAD(0x0054, 0x0054, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB0__GPIO_22			= IOMUX_PAD(0x0058, 0x0058, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB1__GPIO_23			= IOMUX_PAD(0x005C, 0x005C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB4__UART1_TX		= IOMUX_PAD(0x0068, 0x0068, 2, 0x0380, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB5__UART1_RX		= IOMUX_PAD(0x006c, 0x006c, 2, 0x037c, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB6__GPIO_28			= IOMUX_PAD(0x0070, 0x0070, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB7__GPIO_29			= IOMUX_PAD(0x0074, 0x0074, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB8__GPIO_30			= IOMUX_PAD(0x0078, 0x0078, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB9__GPIO_31			= IOMUX_PAD(0x007C, 0x007C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB10__UART0_TX		= IOMUX_PAD(0x0080, 0x0080, 1, __NA_, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB11__UART0_RX		= IOMUX_PAD(0x0084, 0x0084, 1, __NA_, 0, VF610_UART_PAD_CTRL),
+	VF610_PAD_PTB12__GPIO_34		= IOMUX_PAD(0x0088, 0x0088, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB13__GPIO_35		= IOMUX_PAD(0x008c, 0x008c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB16__GPIO_38		= IOMUX_PAD(0x0098, 0x0098, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB17__GPIO_39		= IOMUX_PAD(0x009c, 0x009c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB18__GPIO_40		= IOMUX_PAD(0x00a0, 0x00a0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB21__GPIO_43		= IOMUX_PAD(0x00ac, 0x00ac, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB22__GPIO_44		= IOMUX_PAD(0x00b0, 0x00b0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB23__GPIO_93		= IOMUX_PAD(0x0174, 0x0174, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB26__GPIO_96		= IOMUX_PAD(0x0180, 0x0180, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTB28__GPIO_98		= IOMUX_PAD(0x0188, 0x0188, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC1__GPIO_46			= IOMUX_PAD(0x00b8, 0x00b8, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC1__RMII0_MDIO		= IOMUX_PAD(0x00b8, 0x00b8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC0__GPIO_45			= IOMUX_PAD(0x00b4, 0x00b4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC0__RMII0_MDC		= IOMUX_PAD(0x00b4, 0x00b4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC2__RMII0_CRS_DV		= IOMUX_PAD(0x00bc, 0x00bc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC2__GPIO_47			= IOMUX_PAD(0x00bc, 0x00bc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC3__RMII0_RD1		= IOMUX_PAD(0x00c0, 0x00c0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC3__GPIO_48			= IOMUX_PAD(0x00c0, 0x00c0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC4__RMII0_RD0		= IOMUX_PAD(0x00c4, 0x00c4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC4__GPIO_49			= IOMUX_PAD(0x00c4, 0x00c4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC5__RMII0_RXER		= IOMUX_PAD(0x00c8, 0x00c8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC5__GPIO_50			= IOMUX_PAD(0x00c8, 0x00c8, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC6__RMII0_TD1		= IOMUX_PAD(0x00cc, 0x00cc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC6__GPIO_51			= IOMUX_PAD(0x00cc, 0x00cc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC7__RMII0_TD0		= IOMUX_PAD(0x00D0, 0x00D0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC7__GPIO_52			= IOMUX_PAD(0x00D0, 0x00D0, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC8__RMII0_TXEN		= IOMUX_PAD(0x00D4, 0x00D4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC8__GPIO_53			= IOMUX_PAD(0x00D4, 0x00D4, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC10__RMII1_MDIO		= IOMUX_PAD(0x00dc, 0x00dc, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC9__RMII1_MDC		= IOMUX_PAD(0x00d8, 0x00d8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC11__RMII1_CRS_DV		= IOMUX_PAD(0x00e0, 0x00e0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC12__RMII1_RD1		= IOMUX_PAD(0x00e4, 0x00e4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC13__RMII1_RD0		= IOMUX_PAD(0x00e8, 0x00e8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC14__RMII1_RXER		= IOMUX_PAD(0x00ec, 0x00ec, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC15__RMII1_TD1		= IOMUX_PAD(0x00f0, 0x00f0, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC16__RMII1_TD0		= IOMUX_PAD(0x00f4, 0x00f4, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTC17__RMII1_TXEN		= IOMUX_PAD(0x00f8, 0x00f8, 1, __NA_, 0, VF610_ENET_PAD_CTRL),
+	VF610_PAD_PTD5__DSPI1_CS0		= IOMUX_PAD(0x0150, 0x0150, 3, 0x300, 1, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTD6__DSPI1_SIN		= IOMUX_PAD(0x0154, 0x0154, 3, 0x2fc, 1, VF610_DSPI_SIN_PAD_CTRL),
+	VF610_PAD_PTD7__DSPI1_SOUT		= IOMUX_PAD(0x0158, 0x0158, 3, __NA_, 0, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTD8__DSPI1_SCK		= IOMUX_PAD(0x015c, 0x015c, 3, 0x2f8, 1, VF610_DSPI_PAD_CTRL),
+	VF610_PAD_PTC29__GPIO_102		= IOMUX_PAD(0x0198, 0x0198, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTC30__GPIO_103		= IOMUX_PAD(0x019c, 0x019c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTA24__ESDHC1_CLK		= IOMUX_PAD(0x0038, 0x0038, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA25__ESDHC1_CMD		= IOMUX_PAD(0x003c, 0x003c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA26__ESDHC1_DAT0		= IOMUX_PAD(0x0040, 0x0040, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA27__ESDHC1_DAT1		= IOMUX_PAD(0x0044, 0x0044, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA28__ESDHC1_DAT2		= IOMUX_PAD(0x0048, 0x0048, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTA29__ESDHC1_DAT3		= IOMUX_PAD(0x004c, 0x004c, 5, __NA_, 0, VF610_SDHC_PAD_CTRL),
+	VF610_PAD_PTB14__I2C0_SCL		= IOMUX_PAD(0x0090, 0x0090, 2, 0x033c, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTB15__I2C0_SDA		= IOMUX_PAD(0x0094, 0x0094, 2, 0x0340, 1, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA22__I2C2_SCL		= IOMUX_PAD(0x0030, 0x0030, 6, 0x034c, 0, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTA23__I2C2_SDA		= IOMUX_PAD(0x0034, 0x0034, 6, 0x0350, 0, VF610_I2C_PAD_CTRL),
+	VF610_PAD_PTD31__NF_IO15		= IOMUX_PAD(0x00fc, 0x00fc, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD31__GPIO_63		= IOMUX_PAD(0x00fc, 0x00fc, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD30__NF_IO14		= IOMUX_PAD(0x0100, 0x0100, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD30__GPIO_64		= IOMUX_PAD(0x0100, 0x0100, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD29__NF_IO13		= IOMUX_PAD(0x0104, 0x0104, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD29__GPIO_65		= IOMUX_PAD(0x0104, 0x0104, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD28__NF_IO12		= IOMUX_PAD(0x0108, 0x0108, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD28__GPIO_66		= IOMUX_PAD(0x0108, 0x0108, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD27__NF_IO11		= IOMUX_PAD(0x010c, 0x010c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD27__GPIO_67		= IOMUX_PAD(0x010c, 0x010c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD26__NF_IO10		= IOMUX_PAD(0x0110, 0x0110, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD26__GPIO_68		= IOMUX_PAD(0x0110, 0x0110, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD25__NF_IO9			= IOMUX_PAD(0x0114, 0x0114, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD25__GPIO_69		= IOMUX_PAD(0x0114, 0x0114, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD24__NF_IO8			= IOMUX_PAD(0x0118, 0x0118, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD24__GPIO_70		= IOMUX_PAD(0x0118, 0x0118, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD23__NF_IO7			= IOMUX_PAD(0x011c, 0x011c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD0__QSPI0_A_QSCK		= IOMUX_PAD(0x013c, 0x013c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD1__QSPI0_A_CS0		= IOMUX_PAD(0x0140, 0x0140, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD2__QSPI0_A_DATA3		= IOMUX_PAD(0x0144, 0x0144, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD3__QSPI0_A_DATA2		= IOMUX_PAD(0x0148, 0x0148, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD4__GPIO_83         = IOMUX_PAD(0x014C, 0x014C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD4__QSPI0_A_DATA1		= IOMUX_PAD(0x014c, 0x014c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD5__QSPI0_A_DATA0		= IOMUX_PAD(0x0150, 0x0150, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD7__QSPI0_B_QSCK		= IOMUX_PAD(0x0158, 0x0158, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD8__QSPI0_B_CS0		= IOMUX_PAD(0x015c, 0x015c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD9__QSPI0_B_DATA3		= IOMUX_PAD(0x0160, 0x0160, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD9__GPIO_88			= IOMUX_PAD(0x0160, 0x0160, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD10__QSPI0_B_DATA2		= IOMUX_PAD(0x0164, 0x0164, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD10__GPIO_89		= IOMUX_PAD(0x0164, 0x0164, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD11__QSPI0_B_DATA1		= IOMUX_PAD(0x0168, 0x0168, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD11__GPIO_90		= IOMUX_PAD(0x0168, 0x0168, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD12__QSPI0_B_DATA0		= IOMUX_PAD(0x016c, 0x016c, 1, __NA_, 0, VF610_QSPI_PAD_CTRL),
+	VF610_PAD_PTD12__GPIO_91		= IOMUX_PAD(0x016c, 0x016c, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD13__GPIO_92		= IOMUX_PAD(0x0170, 0x0170, 0, __NA_, 0, VF610_GPIO_PAD_CTRL),
+	VF610_PAD_PTD22__NF_IO6			= IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD21__NF_IO5			= IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD20__NF_IO4			= IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD19__NF_IO3			= IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD18__NF_IO2			= IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD17__NF_IO1			= IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTD16__NF_IO0			= IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL),
+	VF610_PAD_PTB24__NF_WE_B		= IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+	VF610_PAD_PTB25__NF_CE0_B		= IOMUX_PAD(0x017c, 0x017c, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+
+	VF610_PAD_PTB27__NF_RE_B 		= IOMUX_PAD(0x0184, 0x0184, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+
+	VF610_PAD_PTC26__NF_RB_B 		= IOMUX_PAD(0x018C, 0x018C, 5, __NA_, 0, VF610_NFC_RB_PAD_CTRL),
+
+	VF610_PAD_PTC27__NF_ALE  		= IOMUX_PAD(0x0190, 0x0190, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+
+	VF610_PAD_PTC28__NF_CLE  		= IOMUX_PAD(0x0194, 0x0194, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL),
+
+	VF610_PAD_DDR_RESETB			= IOMUX_PAD(0x021c, 0x021c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A15__DDR_A_15		= IOMUX_PAD(0x0220, 0x0220, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A14__DDR_A_14		= IOMUX_PAD(0x0224, 0x0224, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A13__DDR_A_13		= IOMUX_PAD(0x0228, 0x0228, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A12__DDR_A_12		= IOMUX_PAD(0x022c, 0x022c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A11__DDR_A_11		= IOMUX_PAD(0x0230, 0x0230, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A10__DDR_A_10		= IOMUX_PAD(0x0234, 0x0234, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A9__DDR_A_9		= IOMUX_PAD(0x0238, 0x0238, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A8__DDR_A_8		= IOMUX_PAD(0x023c, 0x023c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A7__DDR_A_7		= IOMUX_PAD(0x0240, 0x0240, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A6__DDR_A_6		= IOMUX_PAD(0x0244, 0x0244, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A5__DDR_A_5		= IOMUX_PAD(0x0248, 0x0248, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A4__DDR_A_4		= IOMUX_PAD(0x024c, 0x024c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A3__DDR_A_3		= IOMUX_PAD(0x0250, 0x0250, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A2__DDR_A_2		= IOMUX_PAD(0x0254, 0x0254, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A1__DDR_A_1		= IOMUX_PAD(0x0258, 0x0258, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_A0__DDR_A_0		= IOMUX_PAD(0x025c, 0x025c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA2__DDR_BA_2		= IOMUX_PAD(0x0260, 0x0260, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA1__DDR_BA_1		= IOMUX_PAD(0x0264, 0x0264, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_BA0__DDR_BA_0		= IOMUX_PAD(0x0268, 0x0268, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CAS__DDR_CAS_B		= IOMUX_PAD(0x026c, 0x026c, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CKE__DDR_CKE_0		= IOMUX_PAD(0x0270, 0x0270, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CLK__DDR_CLK_0		= IOMUX_PAD(0x0274, 0x0274, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_CS__DDR_CS_B_0		= IOMUX_PAD(0x0278, 0x0278, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_D15__DDR_D_15		= IOMUX_PAD(0x027c, 0x027c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D14__DDR_D_14		= IOMUX_PAD(0x0280, 0x0280, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D13__DDR_D_13		= IOMUX_PAD(0x0284, 0x0284, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D12__DDR_D_12		= IOMUX_PAD(0x0288, 0x0288, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D11__DDR_D_11		= IOMUX_PAD(0x028c, 0x028c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D10__DDR_D_10		= IOMUX_PAD(0x0290, 0x0290, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D9__DDR_D_9		= IOMUX_PAD(0x0294, 0x0294, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D8__DDR_D_8		= IOMUX_PAD(0x0298, 0x0298, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D7__DDR_D_7		= IOMUX_PAD(0x029c, 0x029c, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D6__DDR_D_6		= IOMUX_PAD(0x02a0, 0x02a0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D5__DDR_D_5		= IOMUX_PAD(0x02a4, 0x02a4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D4__DDR_D_4		= IOMUX_PAD(0x02a8, 0x02a8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D3__DDR_D_3		= IOMUX_PAD(0x02ac, 0x02ac, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D2__DDR_D_2		= IOMUX_PAD(0x02b0, 0x02b0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D1__DDR_D_1		= IOMUX_PAD(0x02b4, 0x02b4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_D0__DDR_D_0		= IOMUX_PAD(0x02b8, 0x02b8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQM1__DDR_DQM_1		= IOMUX_PAD(0x02bc, 0x02bc, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQM0__DDR_DQM_0		= IOMUX_PAD(0x02c0, 0x02c0, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQS1__DDR_DQS_1		= IOMUX_PAD(0x02c4, 0x02c4, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_DQS0__DDR_DQS_0		= IOMUX_PAD(0x02c8, 0x02c8, 0, __NA_, 0, VF610_DDR_PAD_CTRL_1),
+	VF610_PAD_DDR_RAS__DDR_RAS_B		= IOMUX_PAD(0x02cc, 0x02cc, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_WE__DDR_WE_B		= IOMUX_PAD(0x02d0, 0x02d0, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_ODT1__DDR_ODT_0		= IOMUX_PAD(0x02d4, 0x02d4, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+	VF610_PAD_DDR_ODT0__DDR_ODT_1		= IOMUX_PAD(0x02d8, 0x02d8, 0, __NA_, 0, VF610_DDR_PAD_CTRL),
+};
+
+#endif	/* __IOMUX_VF610_H__ */
diff --git a/images/Makefile.imx b/images/Makefile.imx
index b02fdff..14241b6 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -392,3 +392,8 @@ pblx-$(CONFIG_MACH_ELTEC_HIPERCAM) += start_imx6dl_eltec_hipercam
 CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-header-eltec-hipercam.imxcfg
 FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
 image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
+
+pblx-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr
+CFG_start_vf610_twr.pblx.imximg = $(board)/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
+FILE_barebox-vf610-twr.img = start_vf610_twr.pblx.imximg
+image-$(CONFIG_MACH_VF610_TWR) += barebox-vf610-twr.img
-- 
2.5.5


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

^ permalink raw reply related

* [PATCH 18/20] i.MX: ocotp: Account for shadow memory gaps
From: Andrey Smirnov @ 2016-10-03 14:40 UTC (permalink / raw)
  To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1475505657-898-1-git-send-email-andrew.smirnov@gmail.com>

Shadow memory does not have a true 1:1 mapping to fuse address
space. All i.MX6 devices, with exception of i.MX6SL have a 0x100 byte
gap between banks 5 and 6 (or addresses 0x2f and 0x30), so we need to
account for that when reading data from shadow memory.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
 arch/arm/mach-imx/ocotp.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 44ee0b7..b978508 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -73,6 +73,7 @@
 
 struct imx_ocotp_data {
 	int num_regs;
+	u32 (*addr_to_offset)(u32 addr);
 };
 
 struct ocotp_priv {
@@ -84,6 +85,7 @@ struct ocotp_priv {
 	int sense_enable;
 	char ethaddr[6];
 	struct regmap_config map_config;
+	const struct imx_ocotp_data *data;
 };
 
 static int imx6_ocotp_set_timing(struct ocotp_priv *priv)
@@ -192,7 +194,8 @@ static int imx_ocotp_reg_read(void *ctx, unsigned int reg, unsigned int *val)
 		if (ret)
 			return ret;
 	} else {
-		*(u32 *)val = readl(priv->base + 0x400 + index * 0x10);
+		*(u32 *)val = readl(priv->base +
+				    priv->data->addr_to_offset(index));
 	}
 
 	return 0;
@@ -272,7 +275,8 @@ static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
 		if (ret < 0)
 			return ret;
 	} else {
-		writel(val, priv->base + 0x400 + index * 0x10);
+		writel(val, priv->base +
+		       priv->data->addr_to_offset(index));
 	}
 
 	if (priv->permanent_write_enable)
@@ -374,7 +378,7 @@ static int imx_ocotp_probe(struct device_d *dev)
 	void __iomem *base;
 	struct ocotp_priv *priv;
 	int ret = 0;
-	struct imx_ocotp_data *data;
+	const struct imx_ocotp_data *data;
 
 	ret = dev_get_drvdata(dev, (const void **)&data);
 	if (ret)
@@ -389,6 +393,7 @@ static int imx_ocotp_probe(struct device_d *dev)
 
 	priv = xzalloc(sizeof(*priv));
 
+	priv->data      = data;
 	priv->base	= base;
 	priv->clk	= clk_get(dev, NULL);
 	if (IS_ERR(priv->clk))
@@ -425,12 +430,35 @@ static int imx_ocotp_probe(struct device_d *dev)
 	return 0;
 }
 
+static u32 imx6sl_addr_to_offset(u32 addr)
+{
+	return 0x400 + addr * 0x10;
+}
+
+static u32 imx6q_addr_to_offset(u32 addr)
+{
+	u32 addendum = 0;
+
+	if (addr > 0x2F) {
+		/*
+		 * If we are reading past Bank 5, take into account a
+		 * 0x100 bytes wide gap between Bank 5 and Bank 6
+		 */
+		addendum += 0x100;
+	}
+
+
+	return imx6sl_addr_to_offset(addr) + addendum;
+}
+
 static struct imx_ocotp_data imx6q_ocotp_data = {
 	.num_regs = 512,
+	.addr_to_offset = imx6q_addr_to_offset,
 };
 
 static struct imx_ocotp_data imx6sl_ocotp_data = {
 	.num_regs = 256,
+	.addr_to_offset = imx6sl_addr_to_offset,
 };
 
 static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
-- 
2.5.5


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

^ permalink raw reply related


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