From viresh.kumar at st.com  Fri Oct  1 00:16:55 2010
From: viresh.kumar at st.com (viresh kumar)
Date: Fri, 1 Oct 2010 09:46:55 +0530
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
Message-ID: <4CA560B7.5080505@st.com>

On 09/13/2010 04:05 AM, Linus WALLEIJ wrote:
> This is the same driver submitted by ST Micros SPEAr team but
> generalized and tested on the ST-Ericsson U300. It probably
> easily works on the NHK8815 too.
> 
<snip...>
> ---
>  drivers/mtd/nand/Kconfig     |    7 +
>  drivers/mtd/nand/Makefile    |    1 +
>  drivers/mtd/nand/fsmc_nand.c |  862 ++++++++++++++++++++++++++++++++++++++++++
>  include/mtd/fsmc.h           |  181 +++++++++

Linus,

Just one query, what should be the location of fsmc.h
include/mtd/ or include/linux/mtd ??

viresh.


From dwmw2 at infradead.org  Fri Oct  1 01:21:29 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Fri, 01 Oct 2010 14:21:29 +0900
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <4CA560B7.5080505@st.com>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
	<4CA560B7.5080505@st.com>
Message-ID: <1285910489.31224.14.camel@macbook.infradead.org>

On Fri, 2010-10-01 at 09:46 +0530, viresh kumar wrote:
> 
> 
> Just one query, what should be the location of fsmc.h
> include/mtd/ or include/linux/mtd ?? 

We use include/mtd/ for headers which are exported to userspace. Looks
like this should be include/linux/mtd/

-- 
dwmw2



From vapier at gentoo.org  Fri Oct  1 01:37:14 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:37:14 -0400
Subject: [PATCH] mtd-utils: enable garbage collection of unused function/data
	sections
Message-ID: <1285911434-9186-1-git-send-email-vapier@gentoo.org>

On my default build, this cumulatively shaves off ~100KiB of unused
code and data from the mtd-utils programs.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 common.mk |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/common.mk b/common.mk
index 0444ad9..a55c548 100644
--- a/common.mk
+++ b/common.mk
@@ -3,6 +3,7 @@ AR := $(CROSS)ar
 RANLIB := $(CROSS)ranlib
 
 # Stolen from Linux build system
+comma = ,
 try-run = $(shell set -e; ($(1)) >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
 cc-option = $(call try-run, $(CC) $(1) -c -xc /dev/null -o /dev/null,$(1),$(2))
 
@@ -12,6 +13,8 @@ WFLAGS := -Wall \
 	$(call cc-option,-Wwrite-strings) \
 	$(call cc-option,-Wno-sign-compare)
 CFLAGS += $(WFLAGS)
+SECTION_CFLAGS := $(call cc-option,-ffunction-sections -fdata-sections -Wl$(comma)--gc-sections)
+CFLAGS += $(SECTION_CFLAGS)
 
 ifneq ($(WITHOUT_LARGEFILE), 1)
   CPPFLAGS += -D_FILE_OFFSET_BITS=64
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:38:48 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:38:48 -0400
Subject: [PATCH] mtd-utils: introduce xzalloc() helper
Message-ID: <1285911528-9268-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/xalloc.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/xalloc.h b/include/xalloc.h
index d49a1ae..35a94af 100644
--- a/include/xalloc.h
+++ b/include/xalloc.h
@@ -56,6 +56,12 @@ static void *xcalloc(size_t nmemb, size_t size)
 }
 
 __attribute__((unused))
+static void *xzalloc(size_t size)
+{
+	return xcalloc(1, size);
+}
+
+__attribute__((unused))
 static void *xrealloc(void *ptr, size_t size)
 {
 	ptr = realloc(ptr, size);
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:39:49 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:39:49 -0400
Subject: [PATCH] mtd-utils: sys_errmsg: optimize indentation
Message-ID: <1285911589-9323-1-git-send-email-vapier@gentoo.org>

Rather than do a for loop and output 1 space at a time, let the printf
code take care of indenting the string based on the constant length.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/common.h |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/include/common.h b/include/common.h
index 9f49f55..6684a73 100644
--- a/include/common.h
+++ b/include/common.h
@@ -65,11 +65,9 @@ extern "C" {
 /* System error messages */
 #define sys_errmsg(fmt, ...)  ({                                            \
 	int _err = errno;                                                   \
-	size_t _i;                                                          \
 	errmsg(fmt, ##__VA_ARGS__);                                         \
-	for (_i = 0; _i < sizeof(PROGRAM_NAME) + 1; _i++)                   \
-		fprintf(stderr, " ");                                       \
-	fprintf(stderr, "error %d (%s)\n", _err, strerror(_err));           \
+	fprintf(stderr, "%*serror %d (%s)\n", (int)sizeof(PROGRAM_NAME) + 1,\
+		"", _err, strerror(_err));                                  \
 	-1;                                                                 \
 })
 #define sys_errmsg_die(fmt, ...) do {                                       \
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:40:33 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:40:33 -0400
Subject: [PATCH] libmtd: fix "fount" typo
Message-ID: <1285911633-9386-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 lib/libmtd_legacy.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/libmtd_legacy.c b/lib/libmtd_legacy.c
index 27fb3f8..3d129c1 100644
--- a/lib/libmtd_legacy.c
+++ b/lib/libmtd_legacy.c
@@ -125,18 +125,18 @@ static int proc_parse_next(struct proc_parse_info *pi)
 
 	p = memchr(pi->next, '\"', pi->data_size - pos);
 	if (!p)
-		return errmsg("opening \" not fount");
+		return errmsg("opening \" not found");
 	p += 1;
 	pos = p - pi->buf;
 	if (pos >= pi->data_size)
-		return errmsg("opening \" not fount");
+		return errmsg("opening \" not found");
 
 	p1 = memchr(p, '\"', pi->data_size - pos);
 	if (!p1)
-		return errmsg("closing \" not fount");
+		return errmsg("closing \" not found");
 	pos = p1 - pi->buf;
 	if (pos >= pi->data_size)
-		return errmsg("closing \" not fount");
+		return errmsg("closing \" not found");
 
 	len = p1 - p;
 	if (len > MTD_NAME_MAX)
@@ -146,7 +146,7 @@ static int proc_parse_next(struct proc_parse_info *pi)
 	pi->name[len] = '\0';
 
 	if (p1[1] != '\n')
-		return errmsg("opening \"\n\" not fount");
+		return errmsg("opening \"\n\" not found");
 	pi->next = p1 + 2;
 	return 1;
 }
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:43:30 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:43:30 -0400
Subject: [PATCH] mkfs.jffs2: convert to common.h helpers
Message-ID: <1285911810-9555-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 mkfs.jffs2.c |  146 +++++++++++++++++----------------------------------------
 1 files changed, 44 insertions(+), 102 deletions(-)

diff --git a/mkfs.jffs2.c b/mkfs.jffs2.c
index 528a7fe..85a8564 100644
--- a/mkfs.jffs2.c
+++ b/mkfs.jffs2.c
@@ -80,7 +80,7 @@
 #undef basename
 
 //#define DMALLOC
-//#define mkfs_debug_msg    error_msg
+//#define mkfs_debug_msg    errmsg
 #define mkfs_debug_msg(a...)	{ }
 
 #define PAD(x) (((x)+3)&~3)
@@ -138,64 +138,6 @@ uint32_t find_hardlink(struct filesystem_entry *e)
 	return 0;
 }
 
-static void verror_msg(const char *s, va_list p)
-{
-	fflush(stdout);
-	fprintf(stderr, "%s: ", PROGRAM_NAME);
-	vfprintf(stderr, s, p);
-}
-static void error_msg(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	verror_msg(s, p);
-	va_end(p);
-	putc('\n', stderr);
-}
-
-static void error_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	verror_msg(s, p);
-	va_end(p);
-	putc('\n', stderr);
-	exit(EXIT_FAILURE);
-}
-
-static void vperror_msg(const char *s, va_list p)
-{
-	int err = errno;
-
-	if (s == 0)
-		s = "";
-	verror_msg(s, p);
-	if (*s)
-		s = ": ";
-	fprintf(stderr, "%s%s\n", s, strerror(err));
-}
-
-static void perror_msg(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	vperror_msg(s, p);
-	va_end(p);
-}
-
-static void perror_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	vperror_msg(s, p);
-	va_end(p);
-	exit(EXIT_FAILURE);
-}
-
 extern char *xreadlink(const char *path)
 {
 	static const int GROWBY = 80; /* how large we will grow strings by */
@@ -207,7 +149,7 @@ extern char *xreadlink(const char *path)
 		buf = xrealloc(buf, bufsize += GROWBY);
 		readsize = readlink(path, buf, bufsize); /* 1st try */
 		if (readsize == -1) {
-			perror_msg("%s:%s", PROGRAM_NAME, path);
+			sys_errmsg("%s:%s", PROGRAM_NAME, path);
 			return NULL;
 		}
 	}
@@ -221,7 +163,7 @@ static FILE *xfopen(const char *path, const char *mode)
 {
 	FILE *fp;
 	if ((fp = fopen(path, mode)) == NULL)
-		perror_msg_and_die("%s", path);
+		sys_errmsg_die("%s", path);
 	return fp;
 }
 
@@ -285,13 +227,13 @@ static struct filesystem_entry *add_host_filesystem_entry(const char *name,
 		 * device nodes), but if they _do_ exist the specified mode had
 		 * better match the actual file or strange things will happen.... */
 		if ((mode & S_IFMT) != (sb.st_mode & S_IFMT)) {
-			error_msg_and_die ("%s: file type does not match specified type!", path);
+			errmsg_die ("%s: file type does not match specified type!", path);
 		}
 		timestamp = sb.st_mtime;
 	} else {
 		/* If this is a regular file, it _must_ exist on disk */
 		if ((mode & S_IFMT) == S_IFREG) {
-			error_msg_and_die("%s: does not exist!", path);
+			errmsg_die("%s: does not exist!", path);
 		}
 	}
 
@@ -370,7 +312,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 
 	if (lstat(hostpath, &sb)) {
-		perror_msg_and_die("%s", hostpath);
+		sys_errmsg_die("%s", hostpath);
 	}
 
 	entry = add_host_filesystem_entry(targetpath, hostpath,
@@ -378,7 +320,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 	n = scandir(hostpath, &namelist, 0, alphasort);
 	if (n < 0) {
-		perror_msg_and_die("opening directory %s", hostpath);
+		sys_errmsg_die("opening directory %s", hostpath);
 	}
 
 	for (i=0; i<n; i++)
@@ -393,7 +335,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 		xasprintf(&hpath, "%s/%s", hostpath, dp->d_name);
 		if (lstat(hpath, &sb)) {
-			perror_msg_and_die("%s", hpath);
+			sys_errmsg_die("%s", hpath);
 		}
 		if (strcmp(targetpath, "/") == 0) {
 			xasprintf(&tpath, "%s%s", targetpath, dp->d_name);
@@ -417,7 +359,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 				break;
 
 			default:
-				error_msg("Unknown file type %o for %s", sb.st_mode, hpath);
+				errmsg("Unknown file type %o for %s", sb.st_mode, hpath);
 				break;
 		}
 		free(dp);
@@ -486,7 +428,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 	}
 
 	if (!strcmp(name, "/")) {
-		error_msg_and_die("Device table entries require absolute paths");
+		errmsg_die("Device table entries require absolute paths");
 	}
 
 	xasprintf(&hostpath, "%s%s", rootdir, name);
@@ -512,7 +454,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 			mode |= S_IFLNK;
 			break;
 		default:
-			error_msg_and_die("Unsupported file type '%c'", type);
+			errmsg_die("Unsupported file type '%c'", type);
 	}
 	entry = find_filesystem_entry(root, name, mode);
 	if (entry) {
@@ -532,7 +474,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 		parent = find_filesystem_entry(root, dir, S_IFDIR);
 		free(tmp);
 		if (parent == NULL) {
-			error_msg ("skipping device_table entry '%s': no parent directory!", name);
+			errmsg ("skipping device_table entry '%s': no parent directory!", name);
 			free(name);
 			free(hostpath);
 			return 1;
@@ -571,7 +513,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 				}
 				break;
 			default:
-				error_msg_and_die("Unsupported file type '%c'", type);
+				errmsg_die("Unsupported file type '%c'", type);
 		}
 	}
 	free(name);
@@ -684,10 +626,10 @@ static void full_write(int fd, const void *buf, int len)
 		ret = write(fd, buf, len);
 
 		if (ret < 0)
-			perror_msg_and_die("write");
+			sys_errmsg_die("write");
 
 		if (ret == 0)
-			perror_msg_and_die("write returned zero");
+			sys_errmsg_die("write returned zero");
 
 		len -= ret;
 		buf += ret;
@@ -787,12 +729,12 @@ static unsigned int write_regular_file(struct filesystem_entry *e)
 
 	statbuf = &(e->sb);
 	if (statbuf->st_size >= JFFS2_MAX_FILE_SIZE) {
-		error_msg("Skipping file \"%s\" too large.", e->path);
+		errmsg("Skipping file \"%s\" too large.", e->path);
 		return -1;
 	}
 	fd = open(e->hostname, O_RDONLY);
 	if (fd == -1) {
-		perror_msg_and_die("%s: open file", e->hostname);
+		sys_errmsg_die("%s: open file", e->hostname);
 	}
 
 	e->ino = ++ino;
@@ -824,7 +766,7 @@ static unsigned int write_regular_file(struct filesystem_entry *e)
 		unsigned char *tbuf = buf;
 
 		if (len < 0) {
-			perror_msg_and_die("read");
+			sys_errmsg_die("read");
 		}
 
 		while (len) {
@@ -915,7 +857,7 @@ static void write_symlink(struct filesystem_entry *e)
 
 	len = strlen(e->link);
 	if (len > JFFS2_MAX_SYMLINK_LEN) {
-		error_msg("symlink too large. Truncated to %d chars.",
+		errmsg("symlink too large. Truncated to %d chars.",
 				JFFS2_MAX_SYMLINK_LEN);
 		len = JFFS2_MAX_SYMLINK_LEN;
 	}
@@ -1356,7 +1298,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
 				}
 				break;
 			default:
-				error_msg("Unknown mode %o for %s", e->sb.st_mode,
+				errmsg("Unknown mode %o for %s", e->sb.st_mode,
 						e->fullname);
 				break;
 		}
@@ -1643,15 +1585,15 @@ int main(int argc, char **argv)
 			case 'D':
 				devtable = xfopen(optarg, "r");
 				if (fstat(fileno(devtable), &sb) < 0)
-					perror_msg_and_die(optarg);
+					sys_errmsg_die("%s", optarg);
 				if (sb.st_size < 10)
-					error_msg_and_die("%s: not a proper device table file", optarg);
+					errmsg_die("%s: not a proper device table file", optarg);
 				break;
 
 			case 'r':
 			case 'd':	/* for compatibility with mkfs.jffs, genext2fs, etc... */
 				if (rootdir != default_rootdir) {
-					error_msg_and_die("root directory specified more than once");
+					errmsg_die("root directory specified more than once");
 				}
 				rootdir = xstrdup(optarg);
 				break;
@@ -1663,11 +1605,11 @@ int main(int argc, char **argv)
 
 			case 'o':
 				if (out_fd != -1) {
-					error_msg_and_die("output filename specified more than once");
+					errmsg_die("output filename specified more than once");
 				}
 				out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644);
 				if (out_fd == -1) {
-					perror_msg_and_die("open output file");
+					sys_errmsg_die("open output file");
 				}
 				break;
 
@@ -1690,21 +1632,21 @@ int main(int argc, char **argv)
 
 			case 'h':
 			case '?':
-				error_msg_and_die(helptext);
+				errmsg_die("%s", helptext);
 
 			case 'v':
 				verbose = 1;
 				break;
 
 			case 'V':
-				error_msg_and_die("revision %s\n", revtext);
+				errmsg_die("revision %s\n", revtext);
 
 			case 'e': {
 						  char *next;
 						  unsigned units = 0;
 						  erase_block_size = strtol(optarg, &next, 0);
 						  if (!erase_block_size)
-							  error_msg_and_die("Unrecognisable erase size\n");
+							  errmsg_die("Unrecognisable erase size\n");
 
 						  if (*next) {
 							  if (!strcmp(next, "KiB")) {
@@ -1712,7 +1654,7 @@ int main(int argc, char **argv)
 							  } else if (!strcmp(next, "MiB")) {
 								  units = 1024 * 1024;
 							  } else {
-								  error_msg_and_die("Unknown units in erasesize\n");
+								  errmsg_die("Unknown units in erasesize\n");
 							  }
 						  } else {
 							  if (erase_block_size < 0x1000)
@@ -1751,29 +1693,29 @@ int main(int argc, char **argv)
 			case 'c':
 					  cleanmarker_size = strtol(optarg, NULL, 0);
 					  if (cleanmarker_size < sizeof(cleanmarker)) {
-						  error_msg_and_die("cleanmarker size must be >= 12");
+						  errmsg_die("cleanmarker size must be >= 12");
 					  }
 					  if (cleanmarker_size >= erase_block_size) {
-						  error_msg_and_die("cleanmarker size must be < eraseblock size");
+						  errmsg_die("cleanmarker size must be < eraseblock size");
 					  }
 					  break;
 			case 'm':
 					  if (jffs2_set_compression_mode_name(optarg)) {
-						  error_msg_and_die("Unknown compression mode %s", optarg);
+						  errmsg_die("Unknown compression mode %s", optarg);
 					  }
 					  break;
 			case 'x':
 					  if (jffs2_disable_compressor_name(optarg)) {
-						  error_msg_and_die("Unknown compressor name %s",optarg);
+						  errmsg_die("Unknown compressor name %s",optarg);
 					  }
 					  break;
 			case 'X':
 					  if (jffs2_enable_compressor_name(optarg)) {
-						  error_msg_and_die("Unknown compressor name %s",optarg);
+						  errmsg_die("Unknown compressor name %s",optarg);
 					  }
 					  break;
 			case 'L':
-					  error_msg_and_die("\n%s",jffs2_list_compressors());
+					  errmsg_die("\n%s",jffs2_list_compressors());
 					  break;
 			case 't':
 					  jffs2_compression_check_set(1);
@@ -1786,17 +1728,17 @@ int main(int argc, char **argv)
 							  exit(EXIT_FAILURE);
 					  }
 					  else {
-						  error_msg_and_die("Cannot parse %s",optarg);
+						  errmsg_die("Cannot parse %s",optarg);
 					  }
 					  free(compr_name);
 					  break;
 			case 'i':
 					  if (in_fd != -1) {
-						  error_msg_and_die("(incremental) filename specified more than once");
+						  errmsg_die("(incremental) filename specified more than once");
 					  }
 					  in_fd = open(optarg, O_RDONLY);
 					  if (in_fd == -1) {
-						  perror_msg_and_die("cannot open (incremental) file");
+						  sys_errmsg_die("cannot open (incremental) file");
 					  }
 					  break;
 #ifndef WITHOUT_XATTR
@@ -1818,23 +1760,23 @@ int main(int argc, char **argv)
 		}
 	}
 	if (warn_page_size) {
-		error_msg("Page size for this system is by default %d", page_size);
-		error_msg("Use the --pagesize=SIZE option if this is not what you want");
+		errmsg("Page size for this system is by default %d", page_size);
+		errmsg("Use the --pagesize=SIZE option if this is not what you want");
 	}
 	if (out_fd == -1) {
 		if (isatty(1)) {
-			error_msg_and_die(helptext);
+			errmsg_die("%s", helptext);
 		}
 		out_fd = 1;
 	}
 	if (lstat(rootdir, &sb)) {
-		perror_msg_and_die("%s", rootdir);
+		sys_errmsg_die("%s", rootdir);
 	}
 	if (chdir(rootdir))
-		perror_msg_and_die("%s", rootdir);
+		sys_errmsg_die("%s", rootdir);
 
 	if (!(cwd = getcwd(0, GETCWD_SIZE)))
-		perror_msg_and_die("getcwd failed");
+		sys_errmsg_die("getcwd failed");
 
 	if(in_fd != -1)
 		parse_image();
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:44:21 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:44:21 -0400
Subject: [PATCH] mtd-utils: dont redefine MIN()
Message-ID: <1285911861-9621-1-git-send-email-vapier@gentoo.org>

Some C library headers will define MIN(), so add an #ifndef check.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/common.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/common.h b/include/common.h
index 6684a73..25abc0c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -33,7 +33,9 @@
 extern "C" {
 #endif
 
+#ifndef MIN	/* some C lib headers define this for us */
 #define MIN(a ,b) ((a) < (b) ? (a) : (b))
+#endif
 #define min(a, b) MIN(a, b) /* glue for linux kernel source */
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:45:06 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:45:06 -0400
Subject: [PATCH] mtd-utils: xalloc: simplify/unify error messages
Message-ID: <1285911906-9672-1-git-send-email-vapier@gentoo.org>

I'm not sure that if we actually are out of memory that declaring the
failing allocation size is useful in the output.  So use the same
simple string in every error message to cut down on size (there will
only be one copy of this at runtime).  Size is a much more common
concern than handling OOM issues which most likely aren't the fault
of mtd-utils in the first place.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/xalloc.h |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/xalloc.h b/include/xalloc.h
index 35a94af..f1cc8d4 100644
--- a/include/xalloc.h
+++ b/include/xalloc.h
@@ -41,7 +41,7 @@ static void *xmalloc(size_t size)
 	void *ptr = malloc(size);
 
 	if (ptr == NULL && size != 0)
-		sys_errmsg_die("malloc(%zu) failed", size);
+		sys_errmsg_die("out of memory");
 	return ptr;
 }
 
@@ -51,7 +51,7 @@ static void *xcalloc(size_t nmemb, size_t size)
 	void *ptr = calloc(nmemb, size);
 
 	if (ptr == NULL && nmemb != 0 && size != 0)
-		sys_errmsg_die("calloc(%zu, %zu) failed", nmemb, size);
+		sys_errmsg_die("out of memory");
 	return ptr;
 }
 
@@ -66,7 +66,7 @@ static void *xrealloc(void *ptr, size_t size)
 {
 	ptr = realloc(ptr, size);
 	if (ptr == NULL && size != 0)
-		sys_errmsg_die("realloc(%p, %zu) failed", ptr, size);
+		sys_errmsg_die("out of memory");
 	return ptr;
 }
 
@@ -79,7 +79,7 @@ static char *xstrdup(const char *s)
 		return NULL;
 	t = strdup(s);
 	if (t == NULL)
-		sys_errmsg_die("strdup(%p) failed", s);
+		sys_errmsg_die("out of memory");
 	return t;
 }
 
@@ -97,7 +97,7 @@ static int xasprintf(char **strp, const char *fmt, ...)
 	va_end(ap);
 
 	if (cnt == -1)
-		sys_errmsg_die("asprintf(...) failed");
+		sys_errmsg_die("out of memory");
 
 	return cnt;
 }
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:46:34 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:46:34 -0400
Subject: [PATCH] libmtd: unify some error messages
Message-ID: <1285911994-9747-1-git-send-email-vapier@gentoo.org>

By using the same error message string, we only need one copy of it
in memory at runtime.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 lib/libmtd.c |   27 ++++++++++++++-------------
 1 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/lib/libmtd.c b/lib/libmtd.c
index 1839192..e0c0934 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -785,6 +785,13 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
 	return mtd_get_dev_info1(desc, mtd_num, mtd);
 }
 
+static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
+				  const char *sreq)
+{
+	return sys_errmsg("%s ioctl failed for eraseblock %d (mtd%d)",
+			  sreq, eb, mtd->mtd_num);
+}
+
 static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
 {
 	if (eb < 0 || eb >= mtd->eb_cnt) {
@@ -811,8 +818,7 @@ static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
 
 	ret = ioctl(fd, req, &ei);
 	if (ret < 0)
-		return sys_errmsg("%s ioctl failed for eraseblock %d "
-				  "(mtd%d)", sreq, eb, mtd->mtd_num);
+		return mtd_ioctl_error(mtd, eb, sreq);
 
 	return 0;
 }
@@ -850,9 +856,7 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 
 		if (errno != ENOTTY ||
 		    lib->offs64_ioctls != OFFS64_IOCTLS_UNKNOWN)
-			return sys_errmsg("MEMERASE64 ioctl failed for "
-					  "eraseblock %d (mtd%d)",
-					  eb, mtd->mtd_num);
+			return mtd_ioctl_error(mtd, eb, "MEMERASE64");
 
 		/*
 		 * MEMERASE64 support was added in kernel version 2.6.31, so
@@ -873,8 +877,7 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 	ei.length = ei64.length;
 	ret = ioctl(fd, MEMERASE, &ei);
 	if (ret < 0)
-		return sys_errmsg("MEMERASE ioctl failed for eraseblock %d "
-				  "(mtd%d)", eb, mtd->mtd_num);
+		return mtd_ioctl_error(mtd, eb, "MEMERASE");
 	return 0;
 }
 
@@ -970,8 +973,7 @@ int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb)
 	seek = (loff_t)eb * mtd->eb_size;
 	ret = ioctl(fd, MEMGETBADBLOCK, &seek);
 	if (ret == -1)
-		return sys_errmsg("MEMGETBADBLOCK ioctl failed for "
-				  "eraseblock %d (mtd%d)", eb, mtd->mtd_num);
+		return mtd_ioctl_error(mtd, eb, "MEMGETBADBLOCK");
 	return ret;
 }
 
@@ -992,8 +994,7 @@ int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb)
 	seek = (loff_t)eb * mtd->eb_size;
 	ret = ioctl(fd, MEMSETBADBLOCK, &seek);
 	if (ret == -1)
-		return sys_errmsg("MEMSETBADBLOCK ioctl failed for "
-			          "eraseblock %d (mtd%d)", eb, mtd->mtd_num);
+		return mtd_ioctl_error(mtd, eb, "MEMSETBADBLOCK");
 	return 0;
 }
 
@@ -1196,7 +1197,7 @@ int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
 
 	in_fd = open(img_name, O_RDONLY);
 	if (in_fd == -1)
-		return sys_errmsg("cannot open %s", img_name);
+		return sys_errmsg("cannot open \"%s\"", img_name);
 
 	if (fstat(in_fd, &st)) {
 		sys_errmsg("cannot stat %s", img_name);
@@ -1237,7 +1238,7 @@ int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
 		do {
 			ret = read(in_fd, buf, mtd->eb_size - offs - rd);
 			if (ret == -1) {
-				sys_errmsg("cannot read from %s", img_name);
+				sys_errmsg("cannot read \"%s\"", img_name);
 				goto out_free;
 			}
 			rd += ret;
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 01:49:12 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 01:49:12 -0400
Subject: [PATCH v2] mkfs.jffs2: convert to common.h helpers
In-Reply-To: <1285911810-9555-1-git-send-email-vapier@gentoo.org>
References: <1285911810-9555-1-git-send-email-vapier@gentoo.org>
Message-ID: <1285912152-10188-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- convert a few alloc funcs too

 mkfs.jffs2.c |  159 +++++++++++++++++-----------------------------------------
 1 files changed, 47 insertions(+), 112 deletions(-)

diff --git a/mkfs.jffs2.c b/mkfs.jffs2.c
index 528a7fe..256eec4 100644
--- a/mkfs.jffs2.c
+++ b/mkfs.jffs2.c
@@ -80,7 +80,7 @@
 #undef basename
 
 //#define DMALLOC
-//#define mkfs_debug_msg    error_msg
+//#define mkfs_debug_msg    errmsg
 #define mkfs_debug_msg(a...)	{ }
 
 #define PAD(x) (((x)+3)&~3)
@@ -138,64 +138,6 @@ uint32_t find_hardlink(struct filesystem_entry *e)
 	return 0;
 }
 
-static void verror_msg(const char *s, va_list p)
-{
-	fflush(stdout);
-	fprintf(stderr, "%s: ", PROGRAM_NAME);
-	vfprintf(stderr, s, p);
-}
-static void error_msg(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	verror_msg(s, p);
-	va_end(p);
-	putc('\n', stderr);
-}
-
-static void error_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	verror_msg(s, p);
-	va_end(p);
-	putc('\n', stderr);
-	exit(EXIT_FAILURE);
-}
-
-static void vperror_msg(const char *s, va_list p)
-{
-	int err = errno;
-
-	if (s == 0)
-		s = "";
-	verror_msg(s, p);
-	if (*s)
-		s = ": ";
-	fprintf(stderr, "%s%s\n", s, strerror(err));
-}
-
-static void perror_msg(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	vperror_msg(s, p);
-	va_end(p);
-}
-
-static void perror_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	vperror_msg(s, p);
-	va_end(p);
-	exit(EXIT_FAILURE);
-}
-
 extern char *xreadlink(const char *path)
 {
 	static const int GROWBY = 80; /* how large we will grow strings by */
@@ -207,7 +149,7 @@ extern char *xreadlink(const char *path)
 		buf = xrealloc(buf, bufsize += GROWBY);
 		readsize = readlink(path, buf, bufsize); /* 1st try */
 		if (readsize == -1) {
-			perror_msg("%s:%s", PROGRAM_NAME, path);
+			sys_errmsg("%s:%s", PROGRAM_NAME, path);
 			return NULL;
 		}
 	}
@@ -221,7 +163,7 @@ static FILE *xfopen(const char *path, const char *mode)
 {
 	FILE *fp;
 	if ((fp = fopen(path, mode)) == NULL)
-		perror_msg_and_die("%s", path);
+		sys_errmsg_die("%s", path);
 	return fp;
 }
 
@@ -285,13 +227,13 @@ static struct filesystem_entry *add_host_filesystem_entry(const char *name,
 		 * device nodes), but if they _do_ exist the specified mode had
 		 * better match the actual file or strange things will happen.... */
 		if ((mode & S_IFMT) != (sb.st_mode & S_IFMT)) {
-			error_msg_and_die ("%s: file type does not match specified type!", path);
+			errmsg_die ("%s: file type does not match specified type!", path);
 		}
 		timestamp = sb.st_mtime;
 	} else {
 		/* If this is a regular file, it _must_ exist on disk */
 		if ((mode & S_IFMT) == S_IFREG) {
-			error_msg_and_die("%s: does not exist!", path);
+			errmsg_die("%s: does not exist!", path);
 		}
 	}
 
@@ -370,7 +312,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 
 	if (lstat(hostpath, &sb)) {
-		perror_msg_and_die("%s", hostpath);
+		sys_errmsg_die("%s", hostpath);
 	}
 
 	entry = add_host_filesystem_entry(targetpath, hostpath,
@@ -378,7 +320,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 	n = scandir(hostpath, &namelist, 0, alphasort);
 	if (n < 0) {
-		perror_msg_and_die("opening directory %s", hostpath);
+		sys_errmsg_die("opening directory %s", hostpath);
 	}
 
 	for (i=0; i<n; i++)
@@ -393,7 +335,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 
 		xasprintf(&hpath, "%s/%s", hostpath, dp->d_name);
 		if (lstat(hpath, &sb)) {
-			perror_msg_and_die("%s", hpath);
+			sys_errmsg_die("%s", hpath);
 		}
 		if (strcmp(targetpath, "/") == 0) {
 			xasprintf(&tpath, "%s%s", targetpath, dp->d_name);
@@ -417,7 +359,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 				break;
 
 			default:
-				error_msg("Unknown file type %o for %s", sb.st_mode, hpath);
+				errmsg("Unknown file type %o for %s", sb.st_mode, hpath);
 				break;
 		}
 		free(dp);
@@ -439,7 +381,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 #define GETCWD_SIZE 0
 #else
 #define SCANF_PREFIX "511"
-#define SCANF_STRING(s) (s = malloc(512))
+#define SCANF_STRING(s) (s = xmalloc(512))
 #define GETCWD_SIZE -1
 inline int snprintf(char *str, size_t n, const char *fmt, ...)
 {
@@ -486,7 +428,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 	}
 
 	if (!strcmp(name, "/")) {
-		error_msg_and_die("Device table entries require absolute paths");
+		errmsg_die("Device table entries require absolute paths");
 	}
 
 	xasprintf(&hostpath, "%s%s", rootdir, name);
@@ -512,7 +454,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 			mode |= S_IFLNK;
 			break;
 		default:
-			error_msg_and_die("Unsupported file type '%c'", type);
+			errmsg_die("Unsupported file type '%c'", type);
 	}
 	entry = find_filesystem_entry(root, name, mode);
 	if (entry) {
@@ -532,7 +474,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 		parent = find_filesystem_entry(root, dir, S_IFDIR);
 		free(tmp);
 		if (parent == NULL) {
-			error_msg ("skipping device_table entry '%s': no parent directory!", name);
+			errmsg ("skipping device_table entry '%s': no parent directory!", name);
 			free(name);
 			free(hostpath);
 			return 1;
@@ -571,7 +513,7 @@ static int interpret_table_entry(struct filesystem_entry *root, char *line)
 				}
 				break;
 			default:
-				error_msg_and_die("Unsupported file type '%c'", type);
+				errmsg_die("Unsupported file type '%c'", type);
 		}
 	}
 	free(name);
@@ -684,10 +626,10 @@ static void full_write(int fd, const void *buf, int len)
 		ret = write(fd, buf, len);
 
 		if (ret < 0)
-			perror_msg_and_die("write");
+			sys_errmsg_die("write");
 
 		if (ret == 0)
-			perror_msg_and_die("write returned zero");
+			sys_errmsg_die("write returned zero");
 
 		len -= ret;
 		buf += ret;
@@ -787,12 +729,12 @@ static unsigned int write_regular_file(struct filesystem_entry *e)
 
 	statbuf = &(e->sb);
 	if (statbuf->st_size >= JFFS2_MAX_FILE_SIZE) {
-		error_msg("Skipping file \"%s\" too large.", e->path);
+		errmsg("Skipping file \"%s\" too large.", e->path);
 		return -1;
 	}
 	fd = open(e->hostname, O_RDONLY);
 	if (fd == -1) {
-		perror_msg_and_die("%s: open file", e->hostname);
+		sys_errmsg_die("%s: open file", e->hostname);
 	}
 
 	e->ino = ++ino;
@@ -824,7 +766,7 @@ static unsigned int write_regular_file(struct filesystem_entry *e)
 		unsigned char *tbuf = buf;
 
 		if (len < 0) {
-			perror_msg_and_die("read");
+			sys_errmsg_die("read");
 		}
 
 		while (len) {
@@ -915,7 +857,7 @@ static void write_symlink(struct filesystem_entry *e)
 
 	len = strlen(e->link);
 	if (len > JFFS2_MAX_SYMLINK_LEN) {
-		error_msg("symlink too large. Truncated to %d chars.",
+		errmsg("symlink too large. Truncated to %d chars.",
 				JFFS2_MAX_SYMLINK_LEN);
 		len = JFFS2_MAX_SYMLINK_LEN;
 	}
@@ -1356,7 +1298,7 @@ static void recursive_populate_directory(struct filesystem_entry *dir)
 				}
 				break;
 			default:
-				error_msg("Unknown mode %o for %s", e->sb.st_mode,
+				errmsg("Unknown mode %o for %s", e->sb.st_mode,
 						e->fullname);
 				break;
 		}
@@ -1598,14 +1540,7 @@ void process_buffer(int inp_size) {
 void parse_image(){
 	int ret;
 
-	file_buffer = malloc(erase_block_size);
-
-	if (!file_buffer) {
-		perror("out of memory");
-		close (in_fd);
-		close (out_fd);
-		exit(1);
-	}
+	file_buffer = xmalloc(erase_block_size);
 
 	while ((ret = load_next_block())) {
 		process_buffer(ret);
@@ -1643,15 +1578,15 @@ int main(int argc, char **argv)
 			case 'D':
 				devtable = xfopen(optarg, "r");
 				if (fstat(fileno(devtable), &sb) < 0)
-					perror_msg_and_die(optarg);
+					sys_errmsg_die("%s", optarg);
 				if (sb.st_size < 10)
-					error_msg_and_die("%s: not a proper device table file", optarg);
+					errmsg_die("%s: not a proper device table file", optarg);
 				break;
 
 			case 'r':
 			case 'd':	/* for compatibility with mkfs.jffs, genext2fs, etc... */
 				if (rootdir != default_rootdir) {
-					error_msg_and_die("root directory specified more than once");
+					errmsg_die("root directory specified more than once");
 				}
 				rootdir = xstrdup(optarg);
 				break;
@@ -1663,11 +1598,11 @@ int main(int argc, char **argv)
 
 			case 'o':
 				if (out_fd != -1) {
-					error_msg_and_die("output filename specified more than once");
+					errmsg_die("output filename specified more than once");
 				}
 				out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644);
 				if (out_fd == -1) {
-					perror_msg_and_die("open output file");
+					sys_errmsg_die("open output file");
 				}
 				break;
 
@@ -1690,21 +1625,21 @@ int main(int argc, char **argv)
 
 			case 'h':
 			case '?':
-				error_msg_and_die(helptext);
+				errmsg_die("%s", helptext);
 
 			case 'v':
 				verbose = 1;
 				break;
 
 			case 'V':
-				error_msg_and_die("revision %s\n", revtext);
+				errmsg_die("revision %s\n", revtext);
 
 			case 'e': {
 						  char *next;
 						  unsigned units = 0;
 						  erase_block_size = strtol(optarg, &next, 0);
 						  if (!erase_block_size)
-							  error_msg_and_die("Unrecognisable erase size\n");
+							  errmsg_die("Unrecognisable erase size\n");
 
 						  if (*next) {
 							  if (!strcmp(next, "KiB")) {
@@ -1712,7 +1647,7 @@ int main(int argc, char **argv)
 							  } else if (!strcmp(next, "MiB")) {
 								  units = 1024 * 1024;
 							  } else {
-								  error_msg_and_die("Unknown units in erasesize\n");
+								  errmsg_die("Unknown units in erasesize\n");
 							  }
 						  } else {
 							  if (erase_block_size < 0x1000)
@@ -1751,52 +1686,52 @@ int main(int argc, char **argv)
 			case 'c':
 					  cleanmarker_size = strtol(optarg, NULL, 0);
 					  if (cleanmarker_size < sizeof(cleanmarker)) {
-						  error_msg_and_die("cleanmarker size must be >= 12");
+						  errmsg_die("cleanmarker size must be >= 12");
 					  }
 					  if (cleanmarker_size >= erase_block_size) {
-						  error_msg_and_die("cleanmarker size must be < eraseblock size");
+						  errmsg_die("cleanmarker size must be < eraseblock size");
 					  }
 					  break;
 			case 'm':
 					  if (jffs2_set_compression_mode_name(optarg)) {
-						  error_msg_and_die("Unknown compression mode %s", optarg);
+						  errmsg_die("Unknown compression mode %s", optarg);
 					  }
 					  break;
 			case 'x':
 					  if (jffs2_disable_compressor_name(optarg)) {
-						  error_msg_and_die("Unknown compressor name %s",optarg);
+						  errmsg_die("Unknown compressor name %s",optarg);
 					  }
 					  break;
 			case 'X':
 					  if (jffs2_enable_compressor_name(optarg)) {
-						  error_msg_and_die("Unknown compressor name %s",optarg);
+						  errmsg_die("Unknown compressor name %s",optarg);
 					  }
 					  break;
 			case 'L':
-					  error_msg_and_die("\n%s",jffs2_list_compressors());
+					  errmsg_die("\n%s",jffs2_list_compressors());
 					  break;
 			case 't':
 					  jffs2_compression_check_set(1);
 					  break;
 			case 'y':
-					  compr_name = malloc(strlen(optarg));
+					  compr_name = xmalloc(strlen(optarg));
 					  sscanf(optarg,"%d:%s",&compr_prior,compr_name);
 					  if ((compr_prior>=0)&&(compr_name)) {
 						  if (jffs2_set_compressor_priority(compr_name, compr_prior))
 							  exit(EXIT_FAILURE);
 					  }
 					  else {
-						  error_msg_and_die("Cannot parse %s",optarg);
+						  errmsg_die("Cannot parse %s",optarg);
 					  }
 					  free(compr_name);
 					  break;
 			case 'i':
 					  if (in_fd != -1) {
-						  error_msg_and_die("(incremental) filename specified more than once");
+						  errmsg_die("(incremental) filename specified more than once");
 					  }
 					  in_fd = open(optarg, O_RDONLY);
 					  if (in_fd == -1) {
-						  perror_msg_and_die("cannot open (incremental) file");
+						  sys_errmsg_die("cannot open (incremental) file");
 					  }
 					  break;
 #ifndef WITHOUT_XATTR
@@ -1818,23 +1753,23 @@ int main(int argc, char **argv)
 		}
 	}
 	if (warn_page_size) {
-		error_msg("Page size for this system is by default %d", page_size);
-		error_msg("Use the --pagesize=SIZE option if this is not what you want");
+		errmsg("Page size for this system is by default %d", page_size);
+		errmsg("Use the --pagesize=SIZE option if this is not what you want");
 	}
 	if (out_fd == -1) {
 		if (isatty(1)) {
-			error_msg_and_die(helptext);
+			errmsg_die("%s", helptext);
 		}
 		out_fd = 1;
 	}
 	if (lstat(rootdir, &sb)) {
-		perror_msg_and_die("%s", rootdir);
+		sys_errmsg_die("%s", rootdir);
 	}
 	if (chdir(rootdir))
-		perror_msg_and_die("%s", rootdir);
+		sys_errmsg_die("%s", rootdir);
 
 	if (!(cwd = getcwd(0, GETCWD_SIZE)))
-		perror_msg_and_die("getcwd failed");
+		sys_errmsg_die("getcwd failed");
 
 	if(in_fd != -1)
 		parse_image();
-- 
1.7.3.1



From dedekind1 at gmail.com  Fri Oct  1 02:41:26 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 09:41:26 +0300
Subject: [PATCH] mtd-utils: enable garbage collection of unused
	function/data sections
In-Reply-To: <1285911434-9186-1-git-send-email-vapier@gentoo.org>
References: <1285911434-9186-1-git-send-email-vapier@gentoo.org>
Message-ID: <1285915286.11684.69.camel@localhost>

On Fri, 2010-10-01 at 01:37 -0400, Mike Frysinger wrote:
> On my default build, this cumulatively shaves off ~100KiB of unused
> code and data from the mtd-utils programs.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  common.mk |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)

Pushed all your patches, thanks for cleaning this stuff up!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From imunsie at au1.ibm.com  Fri Oct  1 03:06:08 2010
From: imunsie at au1.ibm.com (Ian Munsie)
Date: Fri,  1 Oct 2010 17:06:08 +1000
Subject: [PATCH 15/18] mtd: Fix endianness issues from device tree
In-Reply-To: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
References: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
Message-ID: <1285916771-18033-16-git-send-email-imunsie@au1.ibm.com>

From: Ian Munsie <imunsie at au1.ibm.com>

This patch adds the appropriate conversions to correct the endianness
issues in the MTD driver whenever it accesses the device tree (which is
always big endian).

Signed-off-by: Ian Munsie <imunsie at au1.ibm.com>
---
 drivers/mtd/maps/physmap_of.c  |   14 +++++++-------
 drivers/mtd/nand/fsl_upm.c     |    8 ++++----
 drivers/mtd/nand/mpc5121_nfc.c |    4 ++--
 drivers/mtd/nand/ndfc.c        |    8 ++++----
 drivers/mtd/ofpart.c           |    6 +++---
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index fe63f6b..ec4011c 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -50,7 +50,7 @@ static int parse_obsolete_partitions(struct platform_device *dev,
 {
 	int i, plen, nr_parts;
 	const struct {
-		u32 offset, len;
+		__be32 offset, len;
 	} *part;
 	const char *names;
 
@@ -69,9 +69,9 @@ static int parse_obsolete_partitions(struct platform_device *dev,
 	names = of_get_property(dp, "partition-names", &plen);
 
 	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = part->offset;
-		info->parts[i].size   = part->len & ~1;
-		if (part->len & 1) /* bit 0 set signifies read only partition */
+		info->parts[i].offset = be32_to_cpu(part->offset);
+		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
+		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
 			info->parts[i].mask_flags = MTD_WRITEABLE;
 
 		if (names && (plen > 0)) {
@@ -226,11 +226,11 @@ static int __devinit of_flash_probe(struct platform_device *dev,
 	struct resource res;
 	struct of_flash *info;
 	const char *probe_type = match->data;
-	const u32 *width;
+	const __be32 *width;
 	int err;
 	int i;
 	int count;
-	const u32 *p;
+	const __be32 *p;
 	int reg_tuple_size;
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
@@ -294,7 +294,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
 		info->list[i].map.name = dev_name(&dev->dev);
 		info->list[i].map.phys = res.start;
 		info->list[i].map.size = res_size;
-		info->list[i].map.bankwidth = *width;
+		info->list[i].map.bankwidth = be32_to_cpup(width);
 
 		err = -ENOMEM;
 		info->list[i].map.virt = ioremap(info->list[i].map.phys,
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 4eff8b2..8da9014 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -222,7 +222,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
 {
 	struct fsl_upm_nand *fun;
 	struct resource io_res;
-	const uint32_t *prop;
+	const __be32 *prop;
 	int rnb_gpio;
 	int ret;
 	int size;
@@ -270,7 +270,7 @@ static int __devinit fun_probe(struct platform_device *ofdev,
 			goto err1;
 		}
 		for (i = 0; i < fun->mchip_count; i++)
-			fun->mchip_offsets[i] = prop[i];
+			fun->mchip_offsets[i] = be32_to_cpu(prop[i]);
 	} else {
 		fun->mchip_count = 1;
 	}
@@ -295,13 +295,13 @@ static int __devinit fun_probe(struct platform_device *ofdev,
 
 	prop = of_get_property(ofdev->dev.of_node, "chip-delay", NULL);
 	if (prop)
-		fun->chip_delay = *prop;
+		fun->chip_delay = be32_to_cpup(prop);
 	else
 		fun->chip_delay = 50;
 
 	prop = of_get_property(ofdev->dev.of_node, "fsl,upm-wait-flags", &size);
 	if (prop && size == sizeof(uint32_t))
-		fun->wait_flags = *prop;
+		fun->wait_flags = be32_to_cpup(prop);
 	else
 		fun->wait_flags = FSL_UPM_WAIT_RUN_PATTERN |
 				  FSL_UPM_WAIT_WRITE_BYTE;
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index df0c1da..aeb27a1 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -660,7 +660,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
 #endif
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
-	const uint *chips_no;
+	const __be32 *chips_no;
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
@@ -803,7 +803,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op,
 	}
 
 	/* Detect NAND chips */
-	if (nand_scan(mtd, *chips_no)) {
+	if (nand_scan(mtd, be32_to_cpup(chips_no))) {
 		dev_err(dev, "NAND Flash not found !\n");
 		devm_free_irq(dev, prv->irq, mtd);
 		retval = -ENXIO;
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 510554e..c9ae0a5 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -229,7 +229,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
 				const struct of_device_id *match)
 {
 	struct ndfc_controller *ndfc = &ndfc_ctrl;
-	const u32 *reg;
+	const __be32 *reg;
 	u32 ccr;
 	int err, len;
 
@@ -244,7 +244,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
 		dev_err(&ofdev->dev, "unable read reg property (%d)\n", len);
 		return -ENOENT;
 	}
-	ndfc->chip_select = reg[0];
+	ndfc->chip_select = be32_to_cpu(reg[0]);
 
 	ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0);
 	if (!ndfc->ndfcbase) {
@@ -257,7 +257,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
 	/* It is ok if ccr does not exist - just default to 0 */
 	reg = of_get_property(ofdev->dev.of_node, "ccr", NULL);
 	if (reg)
-		ccr |= *reg;
+		ccr |= be32_to_cpup(reg);
 
 	out_be32(ndfc->ndfcbase + NDFC_CCR, ccr);
 
@@ -265,7 +265,7 @@ static int __devinit ndfc_probe(struct platform_device *ofdev,
 	reg = of_get_property(ofdev->dev.of_node, "bank-settings", NULL);
 	if (reg) {
 		int offset = NDFC_BCFG0 + (ndfc->chip_select << 2);
-		out_be32(ndfc->ndfcbase + offset, *reg);
+		out_be32(ndfc->ndfcbase + offset, be32_to_cpup(reg));
 	}
 
 	err = ndfc_chip_init(ndfc, ofdev->dev.of_node);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 8bf7dc6..a996718 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -44,7 +44,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 	pp = NULL;
 	i = 0;
 	while ((pp = of_get_next_child(node, pp))) {
-		const u32 *reg;
+		const __be32 *reg;
 		int len;
 
 		reg = of_get_property(pp, "reg", &len);
@@ -53,8 +53,8 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 			continue;
 		}
 
-		(*pparts)[i].offset = reg[0];
-		(*pparts)[i].size = reg[1];
+		(*pparts)[i].offset = be32_to_cpu(reg[0]);
+		(*pparts)[i].size = be32_to_cpu(reg[1]);
 
 		partname = of_get_property(pp, "label", &len);
 		if (!partname)
-- 
1.7.1



From linus.ml.walleij at gmail.com  Fri Oct  1 03:25:09 2010
From: linus.ml.walleij at gmail.com (Linus Walleij)
Date: Fri, 1 Oct 2010 09:25:09 +0200
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <1285910489.31224.14.camel@macbook.infradead.org>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
	<4CA560B7.5080505@st.com>
	<1285910489.31224.14.camel@macbook.infradead.org>
Message-ID: <AANLkTintC=5Mo82QS0xxB143WrHrijqGOqdyZ=2BxCYe@mail.gmail.com>

2010/10/1 David Woodhouse <dwmw2 at infradead.org>:
> On Fri, 2010-10-01 at 09:46 +0530, viresh kumar wrote:

>> Just one query, what should be the location of fsmc.h
>> include/mtd/ or include/linux/mtd ??
>
> We use include/mtd/ for headers which are exported to userspace. Looks
> like this should be include/linux/mtd/

Aha, I'll respin it then.

Yours,
Linus Walleij


From dwmw2 at infradead.org  Fri Oct  1 03:44:32 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Fri, 01 Oct 2010 16:44:32 +0900
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <AANLkTintC=5Mo82QS0xxB143WrHrijqGOqdyZ=2BxCYe@mail.gmail.com>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
	<4CA560B7.5080505@st.com>
	<1285910489.31224.14.camel@macbook.infradead.org>
	<AANLkTintC=5Mo82QS0xxB143WrHrijqGOqdyZ=2BxCYe@mail.gmail.com>
Message-ID: <1285919072.31224.21.camel@macbook.infradead.org>

On Fri, 2010-10-01 at 09:25 +0200, Linus Walleij wrote:
> 2010/10/1 David Woodhouse <dwmw2 at infradead.org>:
> > On Fri, 2010-10-01 at 09:46 +0530, viresh kumar wrote:
> 
> >> Just one query, what should be the location of fsmc.h
> >> include/mtd/ or include/linux/mtd ??
> >
> > We use include/mtd/ for headers which are exported to userspace. Looks
> > like this should be include/linux/mtd/
> 
> Aha, I'll respin it then.

Or perhaps it shouldn't be in a header file at all. Where else does it
get used from?

-- 
dwmw2



From vipin.kumar at st.com  Fri Oct  1 06:52:40 2010
From: vipin.kumar at st.com (Vipin Kumar)
Date: Fri, 1 Oct 2010 16:22:40 +0530
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
Message-ID: <4CA5BD78.9080808@st.com>


Hello David, Linus

> +#include <linux/mtd/nand_ecc.h>
> +#include <linux/platform_device.h>
> +#include <linux/mtd/partitions.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <mtd/fsmc.h>
> +#include <mtd/mtd-abi.h>
> +
> +static struct nand_ecclayout fsmc_ecc1_layout = {
> +       .eccbytes = 24,
> +       .eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
> +               66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
> +       .oobfree = {
> +               {.offset = 8, .length = 8},
> +               {.offset = 24, .length = 8},
> +               {.offset = 40, .length = 8},
> +               {.offset = 56, .length = 8},
> +               {.offset = 72, .length = 8},
> +               {.offset = 88, .length = 8},
> +               {.offset = 104, .length = 8},
> +               {.offset = 120, .length = 8}
> +       }
> +};
> +
> +static struct nand_ecclayout fsmc_ecc4_lp_layout = {
> +       .eccbytes = 104,
> +       .eccpos = {  2,   3,   4,   5,   6,   7,   8,
> +               9,  10,  11,  12,  13,  14,
> +               18,  19,  20,  21,  22,  23,  24,
> +               25,  26,  27,  28,  29,  30,
> +               34,  35,  36,  37,  38,  39,  40,
> +               41,  42,  43,  44,  45,  46,
> +               50,  51,  52,  53,  54,  55,  56,
> +               57,  58,  59,  60,  61,  62,
> +               66,  67,  68,  69,  70,  71,  72,
> +               73,  74,  75,  76,  77,  78,
> +               82,  83,  84,  85,  86,  87,  88,
> +               89,  90,  91,  92,  93,  94,
> +               98,  99, 100, 101, 102, 103, 104,
> +               105, 106, 107, 108, 109, 110,
> +               114, 115, 116, 117, 118, 119, 120,
> +               121, 122, 123, 124, 125, 126
> +       },
> +       .oobfree = {
> +               {.offset = 15, .length = 3},
> +               {.offset = 31, .length = 3},
> +               {.offset = 47, .length = 3},
> +               {.offset = 63, .length = 3},
> +               {.offset = 79, .length = 3},
> +               {.offset = 95, .length = 3},
> +               {.offset = 111, .length = 3},
> +               {.offset = 127, .length = 1}
> +       }
> +};
> +

I just noticed that the above array is based on an earlier patch which increased 
the array size from 64 to 128. 

http://lists.infradead.org/pipermail/linux-arm-kernel/2010-August/024372.html

This patch itself was under the lense of reviewers for a long time. Actually, 
increasing this array breaks mtd abi as pointed by Artem


Quoting from his mail

> The old interface should remain unchanged in that include/mtd/mtd-abi.h.
> If an application using the old interface calls any of the ecc ioctls
> for a nand chip with > 64 bytes ecc it should return an error.

It will, because size of the structure is part of the ioctl number,
even. See the corresponding ioctl macro definition.

> I still think the eccpos field should be a pointer, so that it can
> allocate as much space as is needed for the ecc. This also means that
> the kernel doesn't need to be changed every time a new NAND chips
> appears with a bigger ecc size.

Sure, this is the whole point: go ahead and design the new ioctl, and
then deprecate the old one. Just invest men/hours into that and we are
all right :-)


This means that the patch sent by linus can be added only after a new ioctl
is defined and the old one deprecated

> +#define __MTD_FSMC_H
> +
> +#include <linux/platform_device.h>
> +#include <linux/mtd/physmap.h>
> +#include <linux/types.h>
> +#include <linux/mtd/partitions.h>
> +#include <asm/param.h>

Linus, there is a checkpatch warining here :)

Best Regards
Vipin


From cbouatmailru at gmail.com  Fri Oct  1 07:22:04 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Fri, 1 Oct 2010 15:22:04 +0400
Subject: [PATCH v3 3/7] eSPI: add eSPI controller support
In-Reply-To: <1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com>
References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101001112204.GA16783@oksana.dev.rtsoft.ru>

Hello Mingkai,

There are mostly cosmetic comments down below.

On Thu, Sep 30, 2010 at 04:00:42PM +0800, Mingkai Hu wrote:
[...]
> +/*
> + * Freescale eSPI controller driver.
> + *
> + * Copyright 2010 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 <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/spi/spi.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_spi.h>
> +#include <sysdev/fsl_soc.h>

Please move the sysdev/ include after linux/.
Will make it a bit prettier. :-)

> +#include <linux/interrupt.h>
> +#include <linux/err.h>
> +
> +#include "spi_fsl_lib.h"
[...]
> +static void fsl_espi_change_mode(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> +	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> +	struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;

No need for the type cast. The same for the rest of the code.

> +	__be32 __iomem *mode;
> +	__be32 __iomem *espi_mode = NULL;
> +	u32 tmp;
> +	unsigned long flags;
> +
> +	espi_mode = &reg_base->mode;
> +	mode = &reg_base->csmode[spi->chip_select];

Could save a few lines by turning this into initializers.

> +
> +	/* Turn off IRQs locally to minimize time that SPI is disabled. */
> +	local_irq_save(flags);
> +
> +	/* Turn off SPI unit prior changing mode */
> +	tmp = mpc8xxx_spi_read_reg(espi_mode);
> +	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
> +	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> +	mpc8xxx_spi_write_reg(espi_mode, tmp);
> +
> +	local_irq_restore(flags);
> +}
> +
> +static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
> +{
> +	u32 data;
> +	u16 data_h, data_l;

u16 data_h;
u16 data_l;

> +

No need for this empty line.

> +	const u32 *tx = mpc8xxx_spi->tx;

<- Instead, add an empty line here.

> +	if (!tx)
> +		return 0;
> +
> +	data = *tx++ << mpc8xxx_spi->tx_shift;
> +	data_l = data & 0xffff;
> +	data_h = (data >> 16) & 0xffff;
> +	swab16s(&data_l);
> +	swab16s(&data_h);
> +	data = data_h | data_l;
> +
> +	mpc8xxx_spi->tx = tx;
> +	return data;
> +}
> +
> +static int fsl_espi_setup_transfer(struct spi_device *spi,
> +					struct spi_transfer *t)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	int bits_per_word = 0;
> +	u8 pm;
> +	u32 hz = 0;
> +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;

Stray tab.

> +
> +	mpc8xxx_spi = spi_master_get_devdata(spi->master);

Could move this to the initializer.

> +
> +	if (t) {
> +		bits_per_word = t->bits_per_word;
> +		hz = t->speed_hz;
> +	}
> +
> +	/* spi_transfer level calls that work per-word */
> +	if (!bits_per_word)
> +		bits_per_word = spi->bits_per_word;
> +
> +	/* Make sure its a bit width we support [4..16] */
> +	if ((bits_per_word < 4) || (bits_per_word > 16))
> +		return -EINVAL;
> +
> +	if (!hz)
> +		hz = spi->max_speed_hz;
> +
> +	cs->rx_shift = 0;
> +	cs->tx_shift = 0;
> +	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> +	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> +	if (bits_per_word <= 8) {
> +		cs->rx_shift = 8 - bits_per_word;
> +	} else if (bits_per_word <= 16) {
> +		cs->rx_shift = 16 - bits_per_word;
> +		if (spi->mode & SPI_LSB_FIRST)
> +			cs->get_tx = fsl_espi_tx_buf_lsb;
> +	} else
> +		return -EINVAL;

} else {
}

> +
> +	mpc8xxx_spi->rx_shift = cs->rx_shift;
> +	mpc8xxx_spi->tx_shift = cs->tx_shift;
> +	mpc8xxx_spi->get_rx = cs->get_rx;
> +	mpc8xxx_spi->get_tx = cs->get_tx;
> +
> +	bits_per_word = bits_per_word - 1;
> +
> +	/* mask out bits we are going to set */
> +	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16
> +				  | CSMODE_PM(0xF));

No need to break this statement.

> +
> +	cs->hw_mode |= CSMODE_LEN(bits_per_word);
> +
> +	if ((mpc8xxx_spi->spibrg / hz) > 64) {
> +		cs->hw_mode |= CSMODE_DIV16;
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> +
> +		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
> +			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
> +			  hz, mpc8xxx_spi->spibrg / 1024);
> +		if (pm > 16)
> +			pm = 16;
> +	} else {
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> +	}
> +	if (pm)
> +		pm--;
> +
> +	cs->hw_mode |= CSMODE_PM(pm);
> +
> +	fsl_espi_change_mode(spi);
> +	return 0;
> +}
> +
> +int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
> +		unsigned int len)

Does this need to be global?

> +{
> +	u32 word;
> +	struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;
> +
> +	mspi->count = len;
> +
> +	/* enable rx ints */
> +	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
> +
> +	/* transmit word */
> +	word = mspi->get_tx(mspi);
> +	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
> +
> +	return 0;
> +}
> +
> +static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t,
> +			    bool is_dma_mapped)

No need for the is_dma_mapped argument.

> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	struct fsl_espi_reg *reg_base;
> +	unsigned int len = t->len;
> +	u8 bits_per_word;
> +	int ret;
> +
> +	reg_base = (struct fsl_espi_reg *)mpc8xxx_spi->reg_base;

Better write this as an initializer, no need for the cast.

> +
> +	bits_per_word = spi->bits_per_word;
> +	if (t->bits_per_word)
> +		bits_per_word = t->bits_per_word;
[...]
> +static int fsl_espi_setup(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_espi_reg *reg_base;
> +	int retval;
> +	u32 hw_mode;
> +	u32 loop_mode;
> +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;

Stray tab.

> +
> +	if (!spi->max_speed_hz)
> +		return -EINVAL;
> +
> +	if (!cs) {
> +		cs = kzalloc(sizeof *cs, GFP_KERNEL);
> +		if (!cs)
> +			return -ENOMEM;
> +		spi->controller_state = cs;
> +	}
[...]
> +		rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
> +
> +		if (mspi->rx)
> +			mspi->get_rx(rx_data, mspi);
> +	}
> +
> +	if ((events & SPIE_NF) == 0)

if (!(events & bit)) is a bit more more natural. Also, the if
statement here needs braces.

> +		/* spin until TX is done */
> +		while (((events = mpc8xxx_spi_read_reg(&reg_base->event))
> +					& SPIE_NF) == 0)
> +			cpu_relax();

This is dangerous. There's a handy spin_event_timeout()
in asm/delay.h.

> +
> +	/* Clear the events */
> +	mpc8xxx_spi_write_reg(&reg_base->event, events);
> +
> +	mspi->count -= 1;
> +	if (mspi->count) {
> +		u32 word = mspi->get_tx(mspi);
> +
> +		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
> +	} else {
> +		complete(&mspi->done);
> +	}
> +}
> +
> +static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
> +{
> +	struct mpc8xxx_spi *mspi = context_data;
> +	struct fsl_espi_reg *reg_base = (struct fsl_espi_reg *)mspi->reg_base;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 events;
> +
> +	/* Get interrupt events(tx/rx) */
> +	events = mpc8xxx_spi_read_reg(&reg_base->event);
> +	if (events)
> +		ret = IRQ_HANDLED;
> +
> +	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);

dev_vdbg()

> +
> +	fsl_espi_cpu_irq(mspi, events);
> +
> +	return ret;
> +}
> +
> +static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
> +{
> +	iounmap(mspi->reg_base);
> +}
> +
> +static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
> +		struct resource *mem, unsigned int irq)
> +{
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct spi_master *master;
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_espi_reg *reg_base;
> +	u32 regval;
> +	int i, ret = 0;
> +
> +	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
> +	if (master == NULL) {

Sometimes you check for !allocated, and sometimes allocated == NULL.
Be consistent. (And !allocated is more natural.)

> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	dev_set_drvdata(dev, master);
> +
> +	ret = mpc8xxx_spi_probe(dev, mem, irq);
> +	if (ret)
> +		goto err_probe;
> +
> +	master->setup = fsl_espi_setup;
> +
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
> +	mpc8xxx_spi->spi_remove = fsl_espi_remove;
> +
> +	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
> +	if (mpc8xxx_spi->reg_base == NULL) {

Ditto.

> +		ret = -ENOMEM;
> +		goto err_probe;
> +	}
> +
> +	reg_base = (struct fsl_espi_reg *)mpc8xxx_spi->reg_base;
> +
> +	/* Register for SPI Interrupt */
> +	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
> +			  0, "fsl_espi", mpc8xxx_spi);
> +
> +	if (ret != 0)

Every time someone writes 'if (rc != 0)', a kitty dies.
Simple 'if (rc)' saves kittens.

> +		goto free_irq;
> +
> +	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> +		mpc8xxx_spi->rx_shift = 16;
> +		mpc8xxx_spi->tx_shift = 24;
> +	}
[...]
> +
> +static int __devexit of_fsl_espi_remove(struct platform_device *dev)
> +{
> +	int ret;
> +
> +	ret = mpc8xxx_spi_remove(&dev->dev);
> +	if (ret)
> +		return ret;
> +
> +	return 0;

Just 'return mpc8xxx_spi_remove(&dev->dev);' is sufficient.

Also, I think there's no need for this wrapper nowadays (but
splitting OF and real probe() stuff is still appropriate).

> +}
> +
> +static const struct of_device_id of_fsl_espi_match[] = {
> +	{ .compatible = "fsl,mpc8536-espi" },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> +
> +static struct of_platform_driver fsl_espi_driver = {
> +	.driver = {
> +		.name = "fsl_espi",
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_fsl_espi_match,
> +	},
> +	.probe		= of_fsl_espi_probe,
> +	.remove		= __devexit_p(of_fsl_espi_remove),
> +};
> +
> +static int __init fsl_espi_init(void)
> +{
> +	return of_register_platform_driver(&fsl_espi_driver);
> +}
> +module_init(fsl_espi_init);
> +
> +static void __exit fsl_espi_exit(void)
> +{
> +	of_unregister_platform_driver(&fsl_espi_driver);
> +}
> +module_exit(fsl_espi_exit);
> +
> +MODULE_AUTHOR("Mingkai Hu");
> +MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");

This sounds like that this is an enhanced version of the
Freescale SPI driver, which it is not. ;-)

> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
> index 6ae8949..9c81498 100644
> --- a/drivers/spi/spi_fsl_lib.h
> +++ b/drivers/spi/spi_fsl_lib.h
> @@ -26,6 +26,7 @@ struct mpc8xxx_spi {
>  	/* rx & tx bufs from the spi_transfer */
>  	const void *tx;
>  	void *rx;
> +	int len;

I'd place the #ifdef CONFIG_SPI_ESPI, for documentation purposes.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2


From cbouatmailru at gmail.com  Fri Oct  1 07:22:12 2010
From: cbouatmailru at gmail.com (Anton Vorontsov)
Date: Fri, 1 Oct 2010 15:22:12 +0400
Subject: [PATCH v3 2/7] spi/mpc8xxx: refactor the common code for
	SPI/eSPI controller
In-Reply-To: <1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101001112212.GA17505@oksana.dev.rtsoft.ru>

On Thu, Sep 30, 2010 at 04:00:41PM +0800, Mingkai Hu wrote:
[...]
> -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> +static void fsl_spi_change_mode(struct spi_device *spi)
>  {
>  	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
>  	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> -	__be32 __iomem *mode = &mspi->base->mode;
> +	struct fsl_spi_reg *reg_base = (struct fsl_spi_reg *)mspi->reg_base;

No need for these type casts (the same is for the whole patch).

-- 
Anton Vorontsov
email: cbouatmailru at gmail.com
irc://irc.freenode.net/bd2


From viresh.kumar at st.com  Fri Oct  1 07:55:47 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:47 +0530
Subject: [PATCH V2 27/69] ST SPEAr: Adding Watchdog support
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <f6ad85aed3e22835920ff6bb4461ee082611d0c4.1285933331.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear3xx/spear300_evb.c         |    1 +
 arch/arm/mach-spear3xx/spear310_evb.c         |    1 +
 arch/arm/mach-spear3xx/spear320_evb.c         |    1 +
 arch/arm/mach-spear3xx/spear3xx.c             |   12 ++++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c         |    1 +
 arch/arm/mach-spear6xx/spear6xx.c             |   12 ++++++++++++
 8 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 9317af8..91c0c09 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -33,6 +33,7 @@
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device gpio_device;
 extern struct amba_device uart_device;
+extern struct amba_device wdt_device;
 extern struct platform_device ehci_device;
 extern struct platform_device i2c_device;
 extern struct platform_device ohci0_device;
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index c948289..7bd8963 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -38,6 +38,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&gpio_device,
 	&uart_device,
+	&wdt_device,
 
 	/* spear300 specific devices */
 	&clcd_device,
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 2a88cd2..cd076c9 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -45,6 +45,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&gpio_device,
 	&uart_device,
+	&wdt_device,
 
 	/* spear310 specific devices */
 };
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index d0cfd96..7f7b5dd 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -42,6 +42,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&gpio_device,
 	&uart_device,
+	&wdt_device,
 
 	/* spear320 specific devices */
 	&clcd_device,
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index ff9f6e9..88a6bd4 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -54,6 +54,18 @@ struct amba_device uart_device = {
 	.irq = {IRQ_UART, NO_IRQ},
 };
 
+/* watchdog device registeration */
+struct amba_device wdt_device = {
+	.dev = {
+		.init_name = "wdt",
+	},
+	.res = {
+		.start = SPEAR3XX_ICM3_WDT_BASE,
+		.end = SPEAR3XX_ICM3_WDT_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
 /* i2c device registeration */
 static struct resource i2c_resources[] = {
 	{
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 8aee3ad..f885898 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -32,6 +32,7 @@
 extern struct amba_device clcd_device;
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
+extern struct amba_device wdt_device;
 extern struct platform_device ehci0_device;
 extern struct platform_device ehci1_device;
 extern struct platform_device i2c_device;
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index bd4be34..0eb5f50 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -24,6 +24,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	&gpio_device[2],
 	&uart_device[0],
 	&uart_device[1],
+	&wdt_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 000b3a8..2eec8ac 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -118,6 +118,18 @@ struct amba_device gpio_device[] = {
 	}
 };
 
+/* watchdog device registeration */
+struct amba_device wdt_device = {
+	.dev = {
+		.init_name = "wdt",
+	},
+	.res = {
+		.start = SPEAR6XX_ICM3_WDT_BASE,
+		.end = SPEAR6XX_ICM3_WDT_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
 /* i2c device registeration */
 static struct resource i2c_resources[] = {
 	{
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:00 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:00 +0530
Subject: [PATCH V2 40/69] ST SPEAr : FSMC (Flexible Static Memory Controller)
	NOR interface driver
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <001f1c5109c19d2ef6517c78daf560cc2f300180.1285933332.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

SPEAr1300 SoC supports FSMC to interface with various memories
(NOR/NAND/SRAM). This patch adds the support for FSMC over NOR interface.

The driver being used is driver/mtd/maps/physmap.c

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/Makefile               |    2 +-
 arch/arm/mach-spear13xx/fsmc-nor.c             |   85 ++++++++++++++++++++++++
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   17 +++++
 arch/arm/mach-spear13xx/spear1310_evb.c        |   17 +++++
 arch/arm/mach-spear13xx/spear13xx.c            |   20 ++++++
 arch/arm/plat-spear/include/plat/fsmc.h        |   15 ++++
 include/mtd/fsmc.h                             |    2 +
 8 files changed, 158 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/fsmc-nor.c

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index 838405a..9312fcd 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -3,7 +3,7 @@
 #
 
 # common files
-obj-y					+= spear13xx.o clock.o
+obj-y					+= spear13xx.o clock.o fsmc-nor.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
 obj-$(CONFIG_PCIEPORTBUS)		+= pcie.o
diff --git a/arch/arm/mach-spear13xx/fsmc-nor.c b/arch/arm/mach-spear13xx/fsmc-nor.c
new file mode 100644
index 0000000..03234b6
--- /dev/null
+++ b/arch/arm/mach-spear13xx/fsmc-nor.c
@@ -0,0 +1,85 @@
+/*
+ * arch/arm/mach-spear13xx/fsmc-nor.c
+ *
+ * FSMC (Flexible Static Memory Controller) interface for NOR
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar<vipin.kumar at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <plat/fsmc.h>
+
+int __init fsmc_nor_init(struct platform_device *pdev, unsigned long base,
+		u32 bank, u32 width)
+{
+	void __iomem *fsmc_nor_base;
+	struct fsmc_regs *regs;
+	struct clk *clk;
+	int ret;
+	u32 ctrl;
+
+	if (bank > (FSMC_MAX_NOR_BANKS - 1))
+		return -EINVAL;
+
+	fsmc_nor_base = ioremap(base, FSMC_NOR_REG_SIZE);
+	if (!fsmc_nor_base)
+		return -ENOMEM;
+
+	clk = clk_get(NULL, "fsmc");
+	if (IS_ERR(clk)) {
+		iounmap(fsmc_nor_base);
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		iounmap(fsmc_nor_base);
+		return ret;
+	}
+
+	regs = (struct fsmc_regs *)fsmc_nor_base;
+
+	ctrl = WAIT_ENB | WRT_ENABLE | WPROT | NOR_DEV | BANK_ENABLE;
+
+	switch (width) {
+	case FSMC_FLASH_WIDTH8:
+		ctrl |= WIDTH_8;
+		break;
+
+	case FSMC_FLASH_WIDTH16:
+		ctrl |= WIDTH_16;
+		break;
+
+	case FSMC_FLASH_WIDTH32:
+		ctrl |= WIDTH_32;
+		break;
+
+	default:
+		ctrl |= WIDTH_8;
+		break;
+	}
+
+	writel(ctrl, &regs->nor_bank_regs[bank].ctrl);
+	writel(0x0FFFFFFF, &regs->nor_bank_regs[bank].ctrl_tim);
+	writel(ctrl | RSTPWRDWN, &regs->nor_bank_regs[bank].ctrl);
+
+	iounmap(fsmc_nor_base);
+
+	return 0;
+}
+
+void __init fsmc_init_board_info(struct platform_device *pdev,
+		struct mtd_partition *partitions, unsigned int nr_partitions,
+		unsigned int width)
+{
+	fsmc_nor_set_plat_data(pdev, partitions, nr_partitions, width);
+}
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index cd54e62..9b0f009 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -34,6 +34,7 @@ extern struct amba_device spear13xx_ssp_device;
 extern struct amba_device spear13xx_uart_device;
 extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
+extern struct platform_device spear13xx_fsmc_nor_device;
 extern struct platform_device spear13xx_i2c_device;
 extern struct platform_device spear13xx_kbd_device;
 extern struct platform_device spear13xx_nand_device;
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 269d9b0..e56fbd4 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -22,11 +22,21 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 #include <mach/pcie.h>
+#include <plat/fsmc.h>
 #include <plat/keyboard.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
 #include <plat/spi.h>
 
+#define PARTITION(n, off, sz)	{.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+	PARTITION("X-loader", 0, 1 * 0x20000),
+	PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+	PARTITION("Kernel", 0x80000, 24 * 0x20000),
+	PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[0],
 	&spear13xx_gpio_device[1],
@@ -114,6 +124,13 @@ static void __init spear1300_evb_init(void)
 	enable_pcie0_clk();
 	pcie_init(&spear1300_pcie_port_is_host);
 #endif
+	/* initialize fsmc related data in fsmc plat data */
+	fsmc_init_board_info(&spear13xx_fsmc_nor_device, partition_info,
+			ARRAY_SIZE(partition_info), FSMC_FLASH_WIDTH8);
+
+	/* Initialize fsmc regiters */
+	fsmc_nor_init(&spear13xx_fsmc_nor_device, SPEAR13XX_FSMC_BASE, 0,
+			FSMC_FLASH_WIDTH8);
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index c1227bc..f6b4323 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -27,6 +27,15 @@
 #include <plat/smi.h>
 #include <plat/spi.h>
 
+#define PARTITION(n, off, sz)	{.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+	PARTITION("X-loader", 0, 1 * 0x20000),
+	PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+	PARTITION("Kernel", 0x80000, 24 * 0x20000),
+	PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear13xx specific devices */
 	&spear13xx_gpio_device[0],
@@ -115,6 +124,14 @@ static void __init spear1310_evb_init(void)
 	/* initialize serial nor related data in smi plat data */
 	smi_init_board_info(&spear13xx_smi_device);
 
+	/* initialize fsmc related data in fsmc plat data */
+	fsmc_init_board_info(&spear13xx_fsmc_nor_device, partition_info,
+			ARRAY_SIZE(partition_info), FSMC_FLASH_WIDTH8);
+
+	/* Initialize fsmc regiters */
+	fsmc_nor_init(&spear13xx_fsmc_nor_device, SPEAR13XX_FSMC_BASE, 0,
+			FSMC_FLASH_WIDTH8);
+
 #ifdef CONFIG_PCIEPORTBUS
 	/* Enable PCIE0 clk */
 	enable_pcie0_clk();
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 76920ec..cdf132e 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
+#include <linux/mtd/physmap.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
 #include <mtd/fsmc.h>
@@ -130,6 +131,25 @@ struct platform_device spear13xx_i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* fsmc nor flash device registeration */
+static struct physmap_flash_data fsmc_norflash_data;
+
+static struct resource fsmc_nor_resources[] = {
+	{
+		.start	= SPEAR13XX_FSMC_MEM_BASE,
+		.end	= SPEAR13XX_FSMC_MEM_BASE + SZ_16M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear13xx_fsmc_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.resource = fsmc_nor_resources,
+	.num_resources = ARRAY_SIZE(fsmc_nor_resources),
+	.dev.platform_data = &fsmc_norflash_data,
+};
+
 /* nand device registeration */
 void __init nand_mach_init(u32 busw)
 {
diff --git a/arch/arm/plat-spear/include/plat/fsmc.h b/arch/arm/plat-spear/include/plat/fsmc.h
index bb161fb..6ecf2e7 100644
--- a/arch/arm/plat-spear/include/plat/fsmc.h
+++ b/arch/arm/plat-spear/include/plat/fsmc.h
@@ -14,6 +14,7 @@
 #ifndef __PLAT_FSMC_H
 #define __PLAT_FSMC_H
 
+#include <linux/mtd/physmap.h>
 #include <mtd/fsmc.h>
 
 /* This function is used to set platform data field of pdev->dev */
@@ -33,4 +34,18 @@ static inline void fsmc_nand_set_plat_data(struct platform_device *pdev,
 	plat_data->width = width;
 }
 
+static inline void fsmc_nor_set_plat_data(struct platform_device *pdev,
+		struct mtd_partition *partitions, unsigned int nr_partitions,
+		unsigned int width)
+{
+	struct physmap_flash_data *plat_data;
+	plat_data = dev_get_platdata(&pdev->dev);
+
+	if (partitions) {
+		plat_data->parts = partitions;
+		plat_data->nr_parts = nr_partitions;
+	}
+
+	plat_data->width = width;
+}
 #endif /* __PLAT_FSMC_H */
diff --git a/include/mtd/fsmc.h b/include/mtd/fsmc.h
index 7b8921b..95725d9 100644
--- a/include/mtd/fsmc.h
+++ b/include/mtd/fsmc.h
@@ -44,6 +44,7 @@
 
 #define FSMC_FLASH_WIDTH8	1
 #define FSMC_FLASH_WIDTH16	2
+#define FSMC_FLASH_WIDTH32	4
 
 struct fsmc_nor_bank_regs {
 	u32 ctrl;
@@ -56,6 +57,7 @@ struct fsmc_nor_bank_regs {
 #define NOR_DEV			(2 << 2)
 #define WIDTH_8			(0 << 4)
 #define WIDTH_16		(1 << 4)
+#define WIDTH_32		(2 << 4)
 #define RSTPWRDWN		(1 << 6)
 #define WPROT			(1 << 7)
 #define WRT_ENABLE		(1 << 12)
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:57 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:57 +0530
Subject: [PATCH V2 37/69] ST SPEAr 13xx : Adding support for SPEAr1310
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <99ee2c24fa9e2ec42bbb71ea3f21d4b67ad8634b.1285933332.git.viresh.kumar@st.com>

From: Bhupesh Sharma <bhupesh.sharma at st.com>

This patch adds support for SPEAr1310 Machine and evaluation board

Signed-off-by: Bhupesh Sharma <bhupesh.sharma at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/Makefile                                |    1 +
 arch/arm/configs/spear13xx_defconfig             |    1 +
 arch/arm/mach-spear13xx/Kconfig                  |   11 ++
 arch/arm/mach-spear13xx/Makefile                 |    6 +
 arch/arm/mach-spear13xx/include/mach/generic.h   |   21 +++-
 arch/arm/mach-spear13xx/include/mach/irqs.h      |   37 ++++++
 arch/arm/mach-spear13xx/include/mach/spear.h     |    1 +
 arch/arm/mach-spear13xx/include/mach/spear1310.h |   31 +++++
 arch/arm/mach-spear13xx/spear1310.c              |   62 ++++++++++
 arch/arm/mach-spear13xx/spear1310_evb.c          |  140 ++++++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h    |    2 +
 arch/arm/mach-spear3xx/spear320.c                |   37 ++++++
 arch/arm/mach-spear3xx/spear320_evb.c            |    2 +
 arch/arm/plat-spear/Makefile                     |    1 +
 14 files changed, 350 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/spear1310.h
 create mode 100644 arch/arm/mach-spear13xx/spear1310.c
 create mode 100644 arch/arm/mach-spear13xx/spear1310_evb.c

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index d5177d7..950a9b5 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -192,6 +192,7 @@ machine-$(CONFIG_ARCH_W90X900)		:= w90x900
 machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
 machine-$(CONFIG_MACH_SPEAR1300)	:= spear13xx
+machine-$(CONFIG_MACH_SPEAR1310)	:= spear13xx
 machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
 machine-$(CONFIG_MACH_SPEAR320)		:= spear3xx
diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 10b1cf5..9f3baf8 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -9,6 +9,7 @@ CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_BOARD_SPEAR1300_EVB=y
+CONFIG_BOARD_SPEAR1310_EVB=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
diff --git a/arch/arm/mach-spear13xx/Kconfig b/arch/arm/mach-spear13xx/Kconfig
index 3ea463d..229ef93 100644
--- a/arch/arm/mach-spear13xx/Kconfig
+++ b/arch/arm/mach-spear13xx/Kconfig
@@ -11,6 +11,12 @@ config BOARD_SPEAR1300_EVB
 	help
 	  Supports ST SPEAr1300 Evaluation Board
 
+config BOARD_SPEAR1310_EVB
+	bool "SPEAr1310 Evaluation Board"
+	select MACH_SPEAR1310
+	help
+	  Supports ST SPEAr1310 Evaluation Board
+
 endmenu
 
 config MACH_SPEAR1300
@@ -18,4 +24,9 @@ config MACH_SPEAR1300
 	help
 	  Supports ST SPEAr1300 Machine
 
+config MACH_SPEAR1310
+	bool "SPEAr1310"
+	help
+	  Supports ST SPEAr1310 Machine
+
 endif #ARCH_SPEAR13XX
diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index 4f1cbc5..838405a 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -13,3 +13,9 @@ obj-$(CONFIG_MACH_SPEAR1300)		+= spear1300.o
 
 # spear1300 boards files
 obj-$(CONFIG_BOARD_SPEAR1300_EVB)	+= spear1300_evb.o
+
+# spear1310 specific files
+obj-$(CONFIG_MACH_SPEAR1310)		+= spear1310.o
+
+# spear1310 boards files
+obj-$(CONFIG_BOARD_SPEAR1310_EVB)	+= spear1310_evb.o
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index bfd0667..83be1f2 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -44,17 +44,32 @@ extern struct platform_device spear13xx_sdhci_device;
 extern struct platform_device spear13xx_smi_device;
 extern struct sys_timer spear13xx_timer;
 
-/* Add spear1300 machine device structure declarations here */
-
 /* Add spear13xx family function declarations here */
 void __init clk_init(void);
 void __init i2c_register_board_devices(void);
 void __init spear_setup_timer(void);
-void __init spear1300_init(void);
 void __init spear13xx_map_io(void);
 void __init spear13xx_init_irq(void);
 void __init spear13xx_init(void);
 void __init nand_mach_init(u32 busw);
 void spear13xx_secondary_startup(void);
 
+/* spear1300 declarations */
+#ifdef CONFIG_MACH_SPEAR1300
+/* Add spear1300 machine function declarations here */
+void __init spear1300_init(void);
+
+#endif /* CONFIG_MACH_SPEAR1300 */
+
+/* spear1310 declarations */
+#ifdef CONFIG_MACH_SPEAR1310
+/* Add spear1310 machine device structure declarations here */
+extern struct platform_device spear1310_can0_device;
+extern struct platform_device spear1310_can1_device;
+
+/* Add spear1310 machine function declarations here */
+void __init spear1310_init(void);
+
+#endif /* CONFIG_MACH_SPEAR1310 */
+
 #endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/irqs.h b/arch/arm/mach-spear13xx/include/mach/irqs.h
index d2bfbb1..1ca70a6 100644
--- a/arch/arm/mach-spear13xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear13xx/include/mach/irqs.h
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2010 ST Microelectronics
  * Shiraz Hashim <shiraz.hashim at st.com>
+ * Bhupesh Sharma <bhupesh.sharma at st.com>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
@@ -84,6 +85,42 @@
 #define IRQ_PCIE1		(IRQ_SHPI_START + 69)
 #define IRQ_PCIE2		(IRQ_SHPI_START + 70)
 
+/* Add spear1310 specific IRQs here */
+#ifdef CONFIG_MACH_SPEAR1310
+#define IRQ_FSMC_PC1		(IRQ_SHPI_START + 76)
+#define IRQ_FSMC_PC2		(IRQ_SHPI_START + 77)
+#define IRQ_FSMC_PC3		(IRQ_SHPI_START + 78)
+#define IRQ_FSMC_PC4		(IRQ_SHPI_START + 79)
+#define IRQ_RS4850		(IRQ_SHPI_START + 80)
+#define IRQ_RS4851		(IRQ_SHPI_START + 81)
+#define IRQ_CCAN0		(IRQ_SHPI_START + 82)
+#define IRQ_CCAN1		(IRQ_SHPI_START + 83)
+#define IRQ_TDM0		(IRQ_SHPI_START + 84)
+#define IRQ_TDM1		(IRQ_SHPI_START + 85)
+#define IRQ_UART0		(IRQ_SHPI_START + 86)
+#define IRQ_UART1		(IRQ_SHPI_START + 87)
+#define IRQ_UART2		(IRQ_SHPI_START + 88)
+#define IRQ_UART3		(IRQ_SHPI_START + 89)
+#define IRQ_UART4		(IRQ_SHPI_START + 90)
+#define IRQ_I2C_CNTR		(IRQ_SHPI_START + 91)
+#define IRQ_GMAC0_SBD		(IRQ_SHPI_START + 92)
+#define IRQ_GMAC0_PMT		(IRQ_SHPI_START + 93)
+#define IRQ_GMAC1_SBD		(IRQ_SHPI_START + 94)
+#define IRQ_GMAC1_PMT		(IRQ_SHPI_START + 95)
+#define IRQ_GMAC2_SBD		(IRQ_SHPI_START + 96)
+#define IRQ_GMAC2_PMT		(IRQ_SHPI_START + 97)
+#define IRQ_GMAC3_SBD		(IRQ_SHPI_START + 98)
+#define IRQ_GMAC3_PMT		(IRQ_SHPI_START + 99)
+#define IRQ_GPIO		(IRQ_SHPI_START + 100)
+#define IRQ_PCI_BRDG_HOST_FATAL (IRQ_SHPI_START + 101)
+#define IRQ_PCI_INTA		(IRQ_SHPI_START + 102)
+#define IRQ_PCI_INTB		(IRQ_SHPI_START + 103)
+#define IRQ_PCI_INTC		(IRQ_SHPI_START + 104)
+#define IRQ_PCI_INTD		(IRQ_SHPI_START + 105)
+#define IRQ_PCI_ME_TO_ARM	(IRQ_SHPI_START + 106)
+#define IRQ_PCI_SERR_TO_ARM	(IRQ_SHPI_START + 107)
+#endif /* CONFIG_MACH_SPEAR1310 */
+
 #define IRQ_GIC_END		(IRQ_SHPI_START + 128)
 
 #define VIRQ_START		IRQ_GIC_END
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 1a1af72..cf25eb5 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -16,6 +16,7 @@
 
 #include <asm/memory.h>
 #include <mach/spear1300.h>
+#include <mach/spear1310.h>
 
 #define SPEAR13XX_L2CC_BASE		UL(0xED000000)
 
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310.h b/arch/arm/mach-spear13xx/include/mach/spear1310.h
new file mode 100644
index 0000000..e57c99a
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/spear1310.h
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/spear1310.h
+ *
+ * SPEAr1310 Machine specific definition
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifdef CONFIG_MACH_SPEAR1310
+
+#ifndef __MACH_SPEAR1310_H
+#define __MACH_SPEAR1310_H
+
+#define SPEAR1310_CAN0_BASE		UL(0x6DA00000)
+#define SPEAR1310_CAN1_BASE		UL(0x6DB00000)
+#define SPEAR1310_RAS_BASE		UL(0x6C800000)
+
+/* RAS Area Control Register */
+#define SPEAR1310_RAS_CTRL_REG0		(SPEAR1310_RAS_BASE + 0x0)
+#define SPEAR1310_RAS_CTRL_REG1		(SPEAR1310_RAS_BASE + 0x4)
+#define SPEAR1310_PHY_CLK_MASK		0xF
+#define SPEAR1310_PHY_CLK_SHIFT		0
+
+#endif /* __MACH_SPEAR1310_H */
+
+#endif /* CONFIG_MACH_SPEAR1310 */
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
new file mode 100644
index 0000000..648dabc
--- /dev/null
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -0,0 +1,62 @@
+/*
+ * arch/arm/mach-spear13xx/spear1310.c
+ *
+ * SPEAr1310 machine source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/ptrace.h>
+#include <asm/irq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
+
+/* Add spear1310 specific devices here */
+
+/* CAN device registeration */
+static struct resource can0_resources[] = {
+	{
+		.start = SPEAR1310_CAN0_BASE,
+		.end = SPEAR1310_CAN0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_CCAN0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear1310_can0_device = {
+	.name = "spear_can",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(can0_resources),
+	.resource = can0_resources,
+};
+
+static struct resource can1_resources[] = {
+	{
+		.start = SPEAR1310_CAN1_BASE,
+		.end = SPEAR1310_CAN1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_CCAN1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear1310_can1_device = {
+	.name = "spear_can",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(can1_resources),
+	.resource = can1_resources,
+};
+
+void __init spear1310_init(void)
+{
+	/* call spear13xx family common init function */
+	spear13xx_init();
+}
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
new file mode 100644
index 0000000..c1227bc
--- /dev/null
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -0,0 +1,140 @@
+/*
+ * arch/arm/mach-spear13xx/spear1310_evb.c
+ *
+ * SPEAr1310 evaluation board source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/gpio.h>
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <mach/generic.h>
+#include <mach/spear.h>
+#include <mach/pcie.h>
+#include <plat/keyboard.h>
+#include <plat/fsmc.h>
+#include <plat/smi.h>
+#include <plat/spi.h>
+
+static struct amba_device *amba_devs[] __initdata = {
+	/* spear13xx specific devices */
+	&spear13xx_gpio_device[0],
+	&spear13xx_gpio_device[1],
+	&spear13xx_ssp_device,
+	&spear13xx_uart_device,
+};
+
+static struct platform_device *plat_devs[] __initdata = {
+	/* spear13xx specific devices */
+	&spear13xx_ehci0_device,
+	&spear13xx_ehci1_device,
+	&spear13xx_i2c_device,
+	&spear13xx_kbd_device,
+	&spear13xx_nand_device,
+	&spear13xx_ohci0_device,
+	&spear13xx_ohci1_device,
+	&spear13xx_rtc_device,
+	&spear13xx_sdhci_device,
+	&spear13xx_smi_device,
+
+	/* spear1310 specific devices */
+	&spear1310_can0_device,
+	&spear1310_can1_device,
+};
+
+/* keyboard specific platform data */
+static DECLARE_KEYMAP(spear_keymap);
+
+static struct kbd_platform_data kbd_data = {
+	.keymap = spear_keymap,
+	.keymapsize = ARRAY_SIZE(spear_keymap),
+	.rep = 1,
+};
+
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
+#ifdef CONFIG_PCIEPORTBUS
+/* this function is needed for PCIE host and device driver. Same
+ * controller can not be programmed as host as well as device. So host
+ * driver must call this function and if this function returns 1 then
+ * only host should add that particular port as RC.
+ * A port to be added as device, one must also add device's information
+ * in plat_devs array defined in this file.
+ * it is the responsibility of calling function to not send port number
+ * greter than max no of controller(3)
+ */
+int spear1310_pcie_port_is_host(int port)
+{
+	switch (port) {
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	case 2:
+		return 1;
+	}
+	return -EINVAL;
+}
+#endif
+
+static void __init spear1310_evb_init(void)
+{
+	unsigned int i;
+
+	/* set keyboard plat data */
+	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
+
+	/* set nand device's plat data */
+	fsmc_nand_set_plat_data(&spear13xx_nand_device, NULL, 0,
+			NAND_SKIP_BBTSCAN, FSMC_NAND_BW8);
+	nand_mach_init(FSMC_NAND_BW8);
+
+	/* call spear1310 machine init function */
+	spear1310_init();
+
+	/* Register slave devices on the I2C buses */
+	i2c_register_board_devices();
+
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&spear13xx_smi_device);
+
+#ifdef CONFIG_PCIEPORTBUS
+	/* Enable PCIE0 clk */
+	enable_pcie0_clk();
+	pcie_init(&spear1310_pcie_port_is_host);
+#endif
+
+	/* Add Platform Devices */
+	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
+
+	/* Add Amba Devices */
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
+		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
+}
+
+MACHINE_START(SPEAR1310, "ST-SPEAR1310-EVB")
+	.boot_params	=	0x00000100,
+	.map_io		=	spear13xx_map_io,
+	.init_irq	=	spear13xx_init_irq,
+	.timer		=	&spear13xx_timer,
+	.init_machine	=	spear1310_evb_init,
+MACHINE_END
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index ea170a6..0f7648b 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -189,6 +189,8 @@ extern struct amba_device clcd_device;
 extern struct amba_device ssp_device[];
 extern struct amba_device uart1_device;
 extern struct amba_device uart2_device;
+extern struct platform_device can0_device;
+extern struct platform_device can1_device;
 extern struct platform_device i2c1_device;
 extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 8ecad40..a6aa487 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -480,6 +480,43 @@ static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_count = SPEAR_PLGPIO_COUNT,
 };
 
+/* CAN device registeration */
+static struct resource can0_resources[] = {
+	{
+		.start = SPEAR320_CAN0_BASE,
+		.end = SPEAR320_CAN0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = VIRQ_CANU,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device can0_device = {
+	.name = "spear_can",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(can0_resources),
+	.resource = can0_resources,
+};
+
+static struct resource can1_resources[] = {
+	{
+		.start = SPEAR320_CAN1_BASE,
+		.end = SPEAR320_CAN1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = VIRQ_CANL,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device can1_device = {
+	.name = "spear_can",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(can1_resources),
+	.resource = can1_resources,
+};
+
 /* i2c1 device registeration */
 static struct resource i2c1_resources[] = {
 	{
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 2142ad9..1131f9b 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -67,6 +67,8 @@ static struct platform_device *plat_devs[] __initdata = {
 	&smi_device,
 
 	/* spear320 specific devices */
+	&can0_device,
+	&can1_device,
 	&i2c1_device,
 	&plgpio_device,
 	&pwm_device,
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index b8a7403..50c680c 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 obj-$(CONFIG_SPEAR_PWM)		+= pwm.o
 
+obj-$(CONFIG_BOARD_SPEAR1310_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR1300_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR300_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR310_EVB)	+= i2c_eval_board.o
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:45 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:45 +0530
Subject: [PATCH V2 25/69] ST SPEAr: Add smi driver for serial NOR flash
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <238bd0ff57f8530c597157bc07f6c46dc362e1bc.1285933331.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

SPEAr platforms(spear3xx/spear6xx/spear13xx) provide SMI(Serial Memory
Interface) controller to access serial NOR flash. SMI provides a simple
interface for SPI/serial NOR flashes and has certain inbuilt commands
and features to support these flashes easily. It also makes it possible
to map an address range in order to directly access (read/write) the SNOR
over address bus. This patch intends to provide serial nor driver support
for spear platforms which are accessed through SMI.

Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/plat-spear/include/plat/smi.h |   68 ++
 drivers/mtd/devices/Kconfig            |    7 +
 drivers/mtd/devices/Makefile           |    1 +
 drivers/mtd/devices/spear_smi.c        | 1122 ++++++++++++++++++++++++++++++++
 4 files changed, 1198 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-spear/include/plat/smi.h
 create mode 100644 drivers/mtd/devices/spear_smi.c

diff --git a/arch/arm/plat-spear/include/plat/smi.h b/arch/arm/plat-spear/include/plat/smi.h
new file mode 100644
index 0000000..4c74df7
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/smi.h
@@ -0,0 +1,68 @@
+/*
+ * arch/arm/plat-spear/include/plat/smi.h
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_SMI_H
+#define __PLAT_SMI_H
+
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+
+/* macro to define partitions for flash devices */
+#define DEFINE_PARTS(n, of, s)		\
+{					\
+	.name = n,			\
+	.offset = of,			\
+	.size = s,			\
+}
+
+/**
+ * struct spear_smi_flash_info - platform structure for passing flash
+ * information
+ *
+ * name: name of the serial nor flash for identification
+ * mem_base: the memory base on which the flash is mapped
+ * size: size of the flash in bytes
+ * num_parts: number of partitions
+ * parts: parition details
+ * fast_mode: whether flash supports fast mode
+ */
+
+struct spear_smi_flash_info {
+	char *name;
+	unsigned long mem_base;
+	unsigned long size;
+	int num_parts;
+	struct mtd_partition *parts;
+	u8 fast_mode;
+};
+
+/**
+ * struct spear_smi_plat_data - platform structure for configuring smi
+ *
+ * clk_rate: clk rate at which SMI must operate
+ * num_flashes: number of flashes present on board
+ * board_flash_info: specific details of each flash present on board
+ */
+struct spear_smi_plat_data {
+	unsigned long clk_rate;
+	int num_flashes;
+	struct spear_smi_flash_info *board_flash_info;
+};
+
+static inline void smi_set_plat_data(struct platform_device *pdev,
+		struct spear_smi_plat_data *pdata)
+{
+	pdev->dev.platform_data = pdata;
+}
+
+#endif /* __PLAT_SMI_H */
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 35081ce..83daf23 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -102,6 +102,13 @@ config M25PXX_USE_FAST_READ
 	help
 	  This option enables FAST_READ access supported by ST M25Pxx.
 
+config MTD_SPEAR_SMI
+	tristate "SPEAR MTD NOR Support through SMI controller"
+	depends on PLAT_SPEAR
+	default y
+	help
+	  This enable SNOR support on SPEAR platforms using SMI controller
+
 config MTD_SST25L
 	tristate "Support SST25L (non JEDEC) SPI Flash chips"
 	depends on SPI_MASTER
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index f3226b1..6e9063b 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -16,4 +16,5 @@ obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
+obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
new file mode 100644
index 0000000..6dd7de1
--- /dev/null
+++ b/drivers/mtd/devices/spear_smi.c
@@ -0,0 +1,1122 @@
+/*
+ * linux/drivers/mtd/devices/spear_smi.c
+ *
+ * SMI (Serial Memory Controller) device driver for Serial NOR Flash on
+ * SPEAr platform
+ * The serial nor interface is largely based on drivers/mtd/m25p80.c,
+ * however the SPI interface has been replaced by SMI.
+ *
+ * Copyright (C) 2010 STMicroelectronics.
+ * Ashish Priyadarshi
+ * Shiraz Hashim <shiraz.hashim at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <plat/smi.h>
+
+/* max possible slots for serial-nor flash chip in the SMI controller */
+#define MAX_NUM_FLASH_CHIP	4
+
+/* SMI clock rate */
+#define SMI_MAX_CLOCK_FREQ	50000000 /* 50 MHz */
+
+/* MAX time out to safely come out of a erase or write busy conditions */
+#define SMI_PROBE_TIMEOUT	(HZ / 10)
+#define SMI_MAX_TIME_OUT	(3 * HZ)
+
+/* timeout for command completion */
+#define SMI_CMD_TIMEOUT		(HZ / 10)
+
+/* registers of smi */
+#define SMI_CR1		0x0	/* SMI control register 1 */
+#define SMI_CR2		0x4	/* SMI control register 2 */
+#define SMI_SR		0x8	/* SMI status register */
+#define SMI_TR		0xC	/* SMI transmit register */
+#define SMI_RR		0x10	/* SMI receive register */
+
+/* defines for control_reg 1 */
+#define BANK_EN		(0xF << 0)	/* enables all banks */
+#define DSEL_TIME	(0x6 << 4)	/* Deselect time 6 + 1 SMI_CK periods */
+#define SW_MODE		(0x1 << 28)	/* enables SW Mode */
+#define WB_MODE		(0x1 << 29)	/* Write Burst Mode */
+#define FAST_MODE	(0x1 << 15)	/* Fast Mode */
+#define HOLD1		(0x1 << 16)	/* Clock Hold period selection */
+
+/* defines for control_reg 2 */
+#define SEND		(0x1 << 7)	/* Send data */
+#define TFIE		(0x1 << 8)	/* Transmission Flag Interrupt Enable */
+#define WCIE		(0x1 << 9)	/* Write Complete Interrupt Enable */
+#define RD_STATUS_REG	(0x1 << 10)	/* reads status reg */
+#define WE		(0x1 << 11)	/* Write Enable */
+
+#define TX_LEN_SHIFT	0
+#define RX_LEN_SHIFT	4
+#define BANK_SHIFT	12
+
+/* defines for status register */
+#define SR_WIP		0x1	/* Write in progress */
+#define SR_WEL		0x2	/* Write enable latch */
+#define SR_BP0		0x4	/* Block protect 0 */
+#define SR_BP1		0x8	/* Block protect 1 */
+#define SR_BP2		0x10	/* Block protect 2 */
+#define SR_SRWD		0x80	/* SR write protect */
+#define TFF		0x100	/* Transfer Finished Flag */
+#define WCF		0x200	/* Transfer Finished Flag */
+#define ERF1		0x400	/* Forbidden Write Request */
+#define ERF2		0x800	/* Forbidden Access */
+
+#define WM_SHIFT	12
+
+/* flash opcodes */
+#define OPCODE_RDID	0x9f	/* Read JEDEC ID */
+
+/* Flash Device Ids maintenance section */
+
+/* data structure to maintain flash ids from different vendors */
+struct flash_device {
+	char *name;
+	u8 erase_cmd;
+	u32 device_id;
+	u32 pagesize;
+	unsigned long sectorsize;
+	unsigned long size_in_bytes;
+};
+
+#define FLASH_ID(n, es, id, psize, ssize, size)	\
+{				\
+	.name = n,		\
+	.erase_cmd = es,	\
+	.device_id = id,	\
+	.pagesize = psize,	\
+	.sectorsize = ssize,	\
+	.size_in_bytes = size	\
+}
+
+static struct flash_device flash_devices[] = {
+	FLASH_ID("st m25p16"     , 0xd8, 0x00152020, 0x100, 0x10000, 0x200000),
+	FLASH_ID("st m25p32"     , 0xd8, 0x00162020, 0x100, 0x10000, 0x400000),
+	FLASH_ID("st m25p64"     , 0xd8, 0x00172020, 0x100, 0x10000, 0x800000),
+	FLASH_ID("st m25p128"    , 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000),
+	FLASH_ID("st m25p05"     , 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000),
+	FLASH_ID("st m25p10"     , 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000),
+	FLASH_ID("st m25p20"     , 0xd8, 0x00122020, 0x100, 0x10000, 0x40000),
+	FLASH_ID("st m25p40"     , 0xd8, 0x00132020, 0x100, 0x10000, 0x80000),
+	FLASH_ID("st m25p80"     , 0xd8, 0x00142020, 0x100, 0x10000, 0x100000),
+	FLASH_ID("st m45pe10"    , 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
+	FLASH_ID("st m45pe20"    , 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
+	FLASH_ID("st m45pe40"    , 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
+	FLASH_ID("st m45pe80"    , 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
+	FLASH_ID("sp s25fl004"   , 0xd8, 0x00120201, 0x100, 0x10000, 0x80000),
+	FLASH_ID("sp s25fl008"   , 0xd8, 0x00130201, 0x100, 0x10000, 0x100000),
+	FLASH_ID("sp s25fl016"   , 0xd8, 0x00140201, 0x100, 0x10000, 0x200000),
+	FLASH_ID("sp s25fl032"   , 0xd8, 0x00150201, 0x100, 0x10000, 0x400000),
+	FLASH_ID("sp s25fl064"   , 0xd8, 0x00160201, 0x100, 0x10000, 0x800000),
+	FLASH_ID("atmel 25f512"  , 0x52, 0x0065001F, 0x80 , 0x8000 , 0x10000),
+	FLASH_ID("atmel 25f1024" , 0x52, 0x0060001F, 0x100, 0x8000 , 0x20000),
+	FLASH_ID("atmel 25f2048" , 0x52, 0x0063001F, 0x100, 0x10000, 0x40000),
+	FLASH_ID("atmel 25f4096" , 0x52, 0x0064001F, 0x100, 0x10000, 0x80000),
+	FLASH_ID("atmel 25fs040" , 0xd7, 0x0004661F, 0x100, 0x10000, 0x80000),
+	FLASH_ID("mac 25l512"    , 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000),
+	FLASH_ID("mac 25l1005"   , 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000),
+	FLASH_ID("mac 25l2005"   , 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000),
+	FLASH_ID("mac 25l4005"   , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+	FLASH_ID("mac 25l4005a"  , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+	FLASH_ID("mac 25l8005"   , 0xd8, 0x001420C2, 0x010, 0x10000, 0x100000),
+	FLASH_ID("mac 25l1605"   , 0xd8, 0x001520C2, 0x100, 0x10000, 0x200000),
+	FLASH_ID("mac 25l1605a"  , 0xd8, 0x001520C2, 0x010, 0x10000, 0x200000),
+	FLASH_ID("mac 25l3205"   , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+	FLASH_ID("mac 25l3205a"  , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+	FLASH_ID("mac 25l6405"   , 0xd8, 0x001720C2, 0x100, 0x10000, 0x800000),
+};
+
+/* These partitions would be used if platform doesn't pass one */
+static struct mtd_partition part_info_8M[] = {
+	DEFINE_PARTS("Xloader", 0x00, 0x10000),
+	DEFINE_PARTS("UBoot", 0x10000, 0x40000),
+	DEFINE_PARTS("Kernel", 0x50000, 0x2C0000),
+	DEFINE_PARTS("Root File System", 0x310000, 0x4F0000),
+};
+
+static struct mtd_partition part_info_16M[] = {
+	DEFINE_PARTS("Xloader", 0x00, 0x40000),
+	DEFINE_PARTS("UBoot", 0x40000, 0x100000),
+	DEFINE_PARTS("Kernel", 0x140000, 0x300000),
+	DEFINE_PARTS("Root File System", 0x440000, 0xBC0000),
+};
+
+/* Define spear specific structures */
+
+struct spear_snor_flash;
+
+/**
+ * struct spear_smi - Structure for SMI Device
+ *
+ * @clk: functional clock
+ * @status: current status register of SMI.
+ * @clk_rate: functional clock rate of SMI (default: SMI_MAX_CLOCK_FREQ)
+ * @lock: lock to prevent parallel access of SMI.
+ * @io_base: base address for registers of SMI.
+ * @pdev: platform device
+ * @cmd_complete: queue to wait for command completion of NOR-flash.
+ * @num_flashes: number of flashes actually present on board.
+ * @flash: separate structure for each Serial NOR-flash attached to SMI.
+ */
+struct spear_smi {
+	struct clk *clk;
+	u32 status;
+	unsigned long clk_rate;
+	struct mutex lock;
+	void __iomem *io_base;
+	struct platform_device *pdev;
+	wait_queue_head_t cmd_complete;
+	u32 num_flashes;
+	struct spear_snor_flash *flash[MAX_NUM_FLASH_CHIP];
+};
+
+/**
+ * struct spear_snor_flash - Structure for Serial NOR Flash
+ *
+ * @bank: Bank number(0, 1, 2, 3) for each NOR-flash.
+ * @dev_id: Device ID of NOR-flash.
+ * @lock: lock to manage flash read, write and erase operations
+ * @mtd: MTD info for each NOR-flash.
+ * @num_parts: Total number of partition in each bank of NOR-flash.
+ * @parts: Partition info for each bank of NOR-flash.
+ * @page_size: Page size of NOR-flash.
+ * @base_addr: Base address of NOR-flash.
+ * @erase_cmd: erase command may vary on different flash types
+ * @fast_mode: flash supports read in fast mode
+ */
+struct spear_snor_flash {
+	u32 bank;
+	u32 dev_id;
+	struct mutex lock;
+	struct mtd_info mtd;
+	u32 num_parts;
+	struct mtd_partition *parts;
+	u32 page_size;
+	void __iomem *base_addr;
+	u8 erase_cmd;
+	u8 fast_mode;
+};
+
+static inline struct spear_snor_flash *get_flash_data(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct spear_snor_flash, mtd);
+}
+
+/**
+ * spear_smi_read_sr - Read status register of flash through SMI
+ * @dev: structure of SMI information.
+ * @bank: bank to which flash is connected
+ *
+ * This routine will return the status register of the flash chip present at the
+ * given bank.
+ */
+static int spear_smi_read_sr(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	mutex_lock(&dev->lock);
+	dev->status = 0; /* Will be set in interrupt handler */
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	/* program smi in hw mode */
+	writel(ctrlreg1 & ~(SW_MODE | WB_MODE), dev->io_base + SMI_CR1);
+
+	/* performing a rsr instruction in hw mode */
+	writel((bank << BANK_SHIFT) | RD_STATUS_REG | TFIE,
+			dev->io_base + SMI_CR2);
+
+	/* wait for tff */
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	/* copy dev->status (lower 16 bits) in order to release lock */
+	if (ret > 0)
+		ret = dev->status & 0xffff;
+	else
+		ret = -EIO;
+
+	/* restore the ctrl regs state */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+/**
+ * spear_smi_wait_till_ready - wait till flash is ready
+ * @dev: structure of SMI information.
+ * @bank: flash corresponding to this bank
+ * @timeout: timeout for busy wait condition
+ *
+ * This routine checks for WIP (write in progress) bit in Status register
+ * If successful the routine returns 0 else -EBUSY
+ */
+static int spear_smi_wait_till_ready(struct spear_smi *dev, u32 bank,
+		unsigned long timeout)
+{
+	unsigned long finish;
+	int status;
+
+	finish = jiffies + timeout;
+	do {
+		status = spear_smi_read_sr(dev, bank);
+		if (status < 0)
+			continue; /* try till timeout */
+		else if (!(status & SR_WIP))
+			return 0;
+
+		cond_resched();
+	} while (!time_after_eq(jiffies, finish));
+
+	dev_err(&dev->pdev->dev, "smi controller is busy, timeout\n");
+	return status;
+}
+
+/**
+ * spear_smi_int_handler - SMI Interrupt Handler.
+ * @irq: irq number
+ * @dev_id: structure of SMI device, embedded in dev_id.
+ *
+ * The handler clears all interrupt conditions and records the status in
+ * dev->status which is used by the driver later.
+ */
+static irqreturn_t spear_smi_int_handler(int irq, void *dev_id)
+{
+	u32 status = 0;
+	struct spear_smi *dev = dev_id;
+
+	status = readl(dev->io_base + SMI_SR);
+
+	if (unlikely(!status))
+		return IRQ_NONE;
+
+	/* clear all interrupt conditions */
+	writel(0, dev->io_base + SMI_SR);
+
+	/* copy the status register in dev->status */
+	dev->status |= status;
+
+	/* send the completion */
+	wake_up_interruptible(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * spear_smi_hw_init - initializes the smi controller.
+ * @dev: structure of smi device
+ *
+ * this routine initializes the smi controller wit the default values
+ */
+static void spear_smi_hw_init(struct spear_smi *dev)
+{
+	unsigned long rate = 0;
+	u32 prescale = 0;
+	u32 val;
+
+	rate = clk_get_rate(dev->clk);
+
+	/* functional clock of smi */
+	prescale = DIV_ROUND_UP(rate, dev->clk_rate);
+
+	/*
+	 * setting the standard values, fast mode, prescaler for
+	 * SMI_MAX_CLOCK_FREQ (50MHz) operation and bank enable
+	 */
+	val = HOLD1 | BANK_EN | DSEL_TIME | (prescale << 8);
+
+	mutex_lock(&dev->lock);
+	writel(val, dev->io_base + SMI_CR1);
+	mutex_unlock(&dev->lock);
+}
+
+/**
+ * get_flash_index - match chip id from a flash list.
+ * @flash_id: a valid nor flash chip id obtained from board.
+ *
+ * try to validate the chip id by matching from a list, if not found then simply
+ * returns negative. In case of success returns index in to the flash devices
+ * array.
+ */
+static int get_flash_index(u32 flash_id)
+{
+	int index;
+
+	/* Matches chip-id to entire list of 'serial-nor flash' ids */
+	for (index = 0; index < ARRAY_SIZE(flash_devices); index++) {
+		if (flash_devices[index].device_id == flash_id)
+			return index;
+	}
+
+	/* Memory chip is not listed and not supported */
+	return -ENODEV;
+}
+
+/**
+ * spear_smi_write_enable - Enable the flash to do write operation
+ * @dev: structure of SMI device
+ * @bank: enable write for flash connected to this bank
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns 0 on success.
+ */
+static int spear_smi_write_enable(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	mutex_lock(&dev->lock);
+	dev->status = 0; /* Will be set in interrupt handler */
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	/* program smi in h/w mode */
+	writel(ctrlreg1 & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	/* give the flash, write enable command */
+	writel((bank << BANK_SHIFT) | WE | TFIE, dev->io_base + SMI_CR2);
+
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	/* restore the ctrl regs state */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+
+	if (ret <= 0) {
+		ret = -EIO;
+		dev_err(&dev->pdev->dev,
+			"smi controller failed on write enable\n");
+	} else {
+		/* check whether write mode status is set for required bank */
+		if (dev->status & (1 << (bank + WM_SHIFT)))
+			ret = 0;
+		else {
+			dev_err(&dev->pdev->dev, "couldn't enable write\n");
+			ret = -EIO;
+		}
+	}
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static inline u32
+get_sector_erase_cmd(struct spear_snor_flash *flash, u32 offset)
+{
+	u32 cmd;
+	u8 *x = (u8 *)&cmd;
+
+	x[0] = flash->erase_cmd;
+	x[1] = offset >> 16;
+	x[2] = offset >> 8;
+	x[3] = offset;
+
+	return cmd;
+}
+
+/**
+ * spear_smi_erase_sector - erase one sector of flash
+ * @dev: structure of SMI information
+ * @command: erase command to be send
+ * @bank: bank to which this command needs to be send
+ * @bytes: size of command
+ *
+ * Erase one sector of flash memory at offset ``offset'' which is any
+ * address within the sector which should be erased.
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int spear_smi_erase_sector(struct spear_smi *dev,
+		u32 bank, u32 command, u32 bytes)
+{
+	u32 ctrlreg1 = 0;
+	int ret;
+
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_MAX_TIME_OUT);
+	if (ret)
+		return ret;
+
+	ret = spear_smi_write_enable(dev, bank);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->lock);
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	writel((ctrlreg1 | SW_MODE) & ~WB_MODE, dev->io_base + SMI_CR1);
+
+	/* send command in sw mode */
+	writel(command, dev->io_base + SMI_TR);
+
+	writel((bank << BANK_SHIFT) | SEND | TFIE | (bytes << TX_LEN_SHIFT),
+			dev->io_base + SMI_CR2);
+
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	if (ret <= 0) {
+		ret = -EIO;
+		dev_err(&dev->pdev->dev, "sector erase failed\n");
+	} else
+		ret = 0; /* success */
+
+	/* restore ctrl regs */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+/**
+ * spear_mtd_erase - perform flash erase operation as requested by user
+ * @mtd: Provides the memory characteristics
+ * @e_info: Provides the erase information
+ *
+ * Erase an address range on the flash chip. The address range may extend
+ * one or more erase sectors. Return an error is there is a problem erasing.
+ */
+static int spear_mtd_erase(struct mtd_info *mtd, struct erase_info *e_info)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	u32 addr, command, bank;
+	int len, ret;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	/* do not allow erase past end of device */
+	if (e_info->addr + e_info->len > flash->mtd.size)
+		return -EINVAL;
+
+	bank = flash->bank;
+	if (bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	addr = e_info->addr;
+	len = e_info->len;
+
+	mutex_lock(&flash->lock);
+
+	/* now erase sectors in loop */
+	while (len) {
+		command = get_sector_erase_cmd(flash, addr);
+		/* preparing the command for flash */
+		ret = spear_smi_erase_sector(dev, bank, command, 4);
+		if (ret) {
+			e_info->state = MTD_ERASE_FAILED;
+			mutex_unlock(&flash->lock);
+			return ret;
+		}
+		addr += mtd->erasesize;
+		len -= mtd->erasesize;
+	}
+
+	mutex_unlock(&flash->lock);
+	e_info->state = MTD_ERASE_DONE;
+	mtd_erase_callback(e_info);
+
+	return 0;
+}
+
+/**
+ * spear_mtd_read - performs flash read operation as requested by the user
+ * @mtd: MTD information of the memory bank
+ * @from: Address from which to start read
+ * @len: Number of bytes to be read
+ * @retlen: Fills the Number of bytes actually read
+ * @buf: Fills this after reading
+ *
+ * Read an address range from the flash chip. The address range
+ * may be any size provided it is within the physical boundaries.
+ * Returns 0 on success, non zero otherwise
+ */
+static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u8 *buf)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	void *src;
+	u32 ctrlreg1, val;
+	int ret;
+
+	if (!len)
+		return 0;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	/* do not allow reads past end of device */
+	if (from + len > flash->mtd.size)
+		return -EINVAL;
+
+	if (flash->bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	if (!retlen)
+		return -EINVAL;
+	else
+		*retlen = 0;
+
+	/* select address as per bank number */
+	src = flash->base_addr + from;
+
+	mutex_lock(&flash->lock);
+
+	/* wait till previous write/erase is done. */
+	ret = spear_smi_wait_till_ready(dev, flash->bank, SMI_MAX_TIME_OUT);
+	if (ret) {
+		mutex_unlock(&flash->lock);
+		return ret;
+	}
+
+	mutex_lock(&dev->lock);
+	/* put smi in hw mode not wbt mode */
+	ctrlreg1 = val = readl(dev->io_base + SMI_CR1);
+	val &= ~(SW_MODE | WB_MODE);
+	if (flash->fast_mode)
+		val |= FAST_MODE;
+
+	writel(val, dev->io_base + SMI_CR1);
+
+	memcpy_fromio(buf, (u8 *)src, len);
+
+	/* restore ctrl reg1 */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	mutex_unlock(&dev->lock);
+
+	*retlen = len;
+	mutex_unlock(&flash->lock);
+
+	return 0;
+}
+
+static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
+		void *dest, const void *src, size_t len)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	/* wait until finished previous write command. */
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_MAX_TIME_OUT);
+	if (ret)
+		return ret;
+
+	/* put smi in write enable */
+	ret = spear_smi_write_enable(dev, bank);
+	if (ret)
+		return ret;
+
+	/* put smi in hw, write burst mode */
+	mutex_lock(&dev->lock);
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	memcpy_toio(dest, src, len);
+
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+/**
+ * spear_mtd_write - performs write operation as requested by the user.
+ * @mtd: MTD information of the memory bank.
+ * @to:	Address to write.
+ * @len: Number of bytes to be written.
+ * @retlen: Number of bytes actually wrote.
+ * @buf: Buffer from which the data to be taken.
+ *
+ * Write an address range to the flash chip. Data must be written in
+ * flash_page_size chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ * Returns 0 on success, non zero otherwise
+ */
+static int spear_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u8 *buf)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	void *dest;
+	u32 page_offset, page_size;
+	int ret;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	if (!len)
+		return 0;
+
+	/* do not allow write past end of page */
+	if (to + len > flash->mtd.size)
+		return -EINVAL;
+
+	if (flash->bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	if (!retlen)
+		return -EINVAL;
+	else
+		*retlen = 0;
+
+	/* select address as per bank number */
+	dest = flash->base_addr + to;
+	mutex_lock(&flash->lock);
+
+	page_offset = (u32)to % flash->page_size;
+
+	/* do if all the bytes fit onto one page */
+	if (page_offset + len <= flash->page_size) {
+		ret = spear_smi_cpy_toio(dev, flash->bank, dest, buf, len);
+		if (!ret)
+			*retlen += len;
+	} else {
+		u32 i;
+
+		/* the size of data remaining on the first page */
+		page_size = flash->page_size - page_offset;
+
+		ret = spear_smi_cpy_toio(dev, flash->bank, dest, buf,
+				page_size);
+		if (ret)
+			goto err_write;
+		else
+			*retlen += page_size;
+
+		/* write everything in pagesize chunks */
+		for (i = page_size; i < len; i += page_size) {
+			page_size = len - i;
+			if (page_size > flash->page_size)
+				page_size = flash->page_size;
+
+			ret = spear_smi_cpy_toio(dev, flash->bank, dest + i,
+					buf + i, page_size);
+			if (ret)
+				break;
+			else
+				*retlen += page_size;
+		}
+	}
+
+err_write:
+	mutex_unlock(&flash->lock);
+
+	return ret;
+}
+
+/**
+ * spear_smi_probe_flash - Detects the NOR Flash chip.
+ * @dev: structure of SMI information.
+ * @bank: bank on which flash must be probed
+ *
+ * This routine will check whether there exists a flash chip on a given memory
+ * bank ID.
+ * Return index of the probed flash in flash devices structure
+ */
+static int spear_smi_probe_flash(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 val = 0;
+
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_PROBE_TIMEOUT);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->lock);
+
+	dev->status = 0; /* Will be set in interrupt handler */
+	/* put smi in sw mode */
+	val = readl(dev->io_base + SMI_CR1);
+	writel(val | SW_MODE, dev->io_base + SMI_CR1);
+
+	/* send readid command in sw mode */
+	writel(OPCODE_RDID, dev->io_base + SMI_TR);
+
+	val = (bank << BANK_SHIFT) | SEND | (1 << TX_LEN_SHIFT) |
+		(3 << RX_LEN_SHIFT) | TFIE;
+	writel(val, dev->io_base + SMI_CR2);
+
+	/* wait for TFF */
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+	if (ret <= 0) {
+		ret = -ENODEV;
+		goto err_probe;
+	}
+
+	/* get memory chip id */
+	val = readl(dev->io_base + SMI_RR);
+	val &= 0x00ffffff;
+	ret = get_flash_index(val);
+
+err_probe:
+	/* clear sw mode */
+	val = readl(dev->io_base + SMI_CR1);
+	writel(val & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank)
+{
+	const char *part_probes[] = {"cmdlinepart", NULL};
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+	struct spear_smi_flash_info *flash_info;
+	struct spear_smi_plat_data *pdata;
+	struct spear_snor_flash *flash;
+	int flash_index;
+	int ret = 0;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (bank > pdata->num_flashes - 1)
+		return -EINVAL;
+
+	flash_info = &pdata->board_flash_info[bank];
+	if (!flash_info)
+		return -ENODEV;
+
+	flash = kzalloc(sizeof(*flash), GFP_ATOMIC);
+	if (!flash)
+		return -ENOMEM;
+	flash->bank = bank;
+	flash->fast_mode = flash_info->fast_mode ? 1 : 0;
+	mutex_init(&flash->lock);
+
+	/* verify whether nor flash is really present on board */
+	flash_index = spear_smi_probe_flash(dev, bank);
+	if (flash_index < 0) {
+		dev_info(&dev->pdev->dev, "smi-nor%d not found\n", bank);
+		kfree(flash);
+		return flash_index;
+	}
+	/* map the memory for nor flash chip */
+	flash->base_addr = ioremap(flash_info->mem_base, flash_info->size);
+	if (!flash->base_addr) {
+		kfree(flash);
+		return -EIO;
+	}
+
+	dev->flash[bank] = flash;
+	flash->mtd.priv = dev;
+
+	if (flash_info->name)
+		flash->mtd.name = flash_info->name;
+	else
+		flash->mtd.name = flash_devices[flash_index].name;
+
+	flash->mtd.type = MTD_NORFLASH;
+	flash->mtd.writesize = 1;
+	flash->mtd.flags = MTD_CAP_NORFLASH;
+	flash->mtd.size = flash_info->size;
+	flash->mtd.erasesize = flash_devices[flash_index].sectorsize;
+	flash->page_size = flash_devices[flash_index].pagesize;
+	flash->erase_cmd = flash_devices[flash_index].erase_cmd;
+	flash->mtd.erase = spear_mtd_erase;
+	flash->mtd.read = spear_mtd_read;
+	flash->mtd.write = spear_mtd_write;
+	flash->dev_id = flash_devices[flash_index].device_id;
+
+	dev_info(&dev->pdev->dev, "mtd .name=%s .size=%llx(%lluM)\n",
+			flash->mtd.name, flash->mtd.size,
+			flash->mtd.size / (1024 * 1024));
+
+	dev_info(&dev->pdev->dev, ".erasesize = 0x%x(%uK)\n",
+			flash->mtd.erasesize, flash->mtd.erasesize / 1024);
+
+	if (!mtd_has_partitions()) {
+		ret = add_mtd_device(&flash->mtd);
+		return ret;
+	}
+
+	flash->num_parts = 0;
+	if (mtd_has_cmdlinepart()) {
+		flash->num_parts = parse_mtd_partitions(&flash->mtd,
+				part_probes, &flash->parts, 0);
+	}
+
+	if (flash->num_parts <= 0) {
+		if (flash_info->parts) {
+			flash->parts = flash_info->parts;
+			flash->num_parts = flash_info->num_parts;
+		} else {
+			/* choose from default ones */
+			switch (flash->mtd.size) {
+			case 0x800000:/* 8MB */
+				flash->parts = part_info_8M;
+				flash->num_parts =
+					ARRAY_SIZE(part_info_8M);
+				break;
+			case 0x1000000:/* 16MB */
+				flash->parts = part_info_16M;
+				flash->num_parts =
+					ARRAY_SIZE(part_info_16M);
+				break;
+			default:
+				dev_err(&pdev->dev, "undefined partition\n");
+			}
+		}
+	}
+
+	/* Register the partitions */
+	ret = add_mtd_partitions(&flash->mtd, flash->parts, flash->num_parts);
+	if (ret)
+		dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret);
+
+	return ret;
+}
+
+/**
+ * spear_smi_probe - Entry routine
+ * @pdev: platform device structure
+ *
+ * This is the first routine which gets invoked during booting and does all
+ * initialization/allocation work. The routine looks for available memory banks,
+ * and do proper init for any found one.
+ * Returns 0 on success, non zero otherwise
+ */
+static int __devinit spear_smi_probe(struct platform_device *pdev)
+{
+	struct spear_smi_plat_data *pdata;
+	struct spear_smi *dev;
+	struct resource *smi_base;
+	int irq, ret = 0;
+	int i;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata < 0) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "no platform data\n");
+		goto err;
+	}
+
+	smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!smi_base) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "invalid smi base address\n");
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "invalid smi irq\n");
+		goto err;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!dev) {
+		ret = -ENOMEM;
+		dev_err(&pdev->dev, "mem alloc fail\n");
+		goto err;
+	}
+
+	smi_base = request_mem_region(smi_base->start, resource_size(smi_base),
+			pdev->name);
+	if (!smi_base) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "request mem region fail\n");
+		goto err_mem;
+	}
+
+	dev->io_base = ioremap(smi_base->start, resource_size(smi_base));
+	if (!dev->io_base) {
+		ret = -EIO;
+		dev_err(&pdev->dev, "ioremap fail\n");
+		goto err_ioremap;
+	}
+
+	dev->pdev = pdev;
+	dev->clk_rate = pdata->clk_rate;
+
+	if (dev->clk_rate < 0 || dev->clk_rate > SMI_MAX_CLOCK_FREQ)
+		dev->clk_rate = SMI_MAX_CLOCK_FREQ;
+
+	dev->num_flashes = pdata->num_flashes;
+
+	if (dev->num_flashes > MAX_NUM_FLASH_CHIP) {
+		dev_err(&pdev->dev, "exceeding max number of flashes\n");
+		dev->num_flashes = MAX_NUM_FLASH_CHIP;
+	}
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		ret = PTR_ERR(dev->clk);
+		goto err_clk;
+	}
+
+	ret = clk_enable(dev->clk);
+	if (ret)
+		goto err_clk_enable;
+
+	ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "SMI IRQ allocation failed\n");
+		goto err_irq;
+	}
+
+	mutex_init(&dev->lock);
+	init_waitqueue_head(&dev->cmd_complete);
+	spear_smi_hw_init(dev);
+	platform_set_drvdata(pdev, dev);
+
+	/* loop for each serial nor-flash which is connected to smi */
+	for (i = 0; i < dev->num_flashes; i++) {
+		ret = spear_smi_setup_banks(pdev, i);
+		if (ret) {
+			dev_err(&dev->pdev->dev, "bank setup failed\n");
+			goto err_bank_setup;
+		}
+	}
+
+	return 0;
+
+err_bank_setup:
+	free_irq(irq, dev);
+	platform_set_drvdata(pdev, NULL);
+err_irq:
+	clk_disable(dev->clk);
+err_clk_enable:
+	clk_put(dev->clk);
+err_clk:
+	iounmap(dev->io_base);
+err_ioremap:
+	release_mem_region(smi_base->start, resource_size(smi_base));
+err_mem:
+	kfree(dev);
+err:
+	return ret;
+}
+
+/**
+ * spear_smi_remove - Exit routine
+ * @pdev: platform device structure
+ *
+ * free all allocations and delete the partitions.
+ */
+static int __devexit spear_smi_remove(struct platform_device *pdev)
+{
+	struct spear_smi *dev;
+	struct spear_snor_flash *flash;
+	int ret;
+	int i, irq;
+
+	dev = platform_get_drvdata(pdev);
+	if (!dev) {
+		dev_err(&pdev->dev, "dev is null\n");
+		return -ENODEV;
+	}
+
+	/* clean up for all nor flash */
+	for (i = 0; i < dev->num_flashes; i++) {
+		flash = dev->flash[i];
+		if (!flash)
+			continue;
+
+		/* clean up mtd stuff */
+		if (mtd_has_partitions())
+			ret = del_mtd_partitions(&flash->mtd);
+		else
+			ret = del_mtd_device(&flash->mtd);
+
+		if (ret)
+			dev_err(&pdev->dev, "error removing mtd\n");
+
+		iounmap(flash->base_addr);
+		kfree(flash);
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	iounmap(dev->io_base);
+	kfree(dev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+int spear_smi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+
+	if (dev && dev->clk)
+		clk_disable(dev->clk);
+
+	return 0;
+}
+
+int spear_smi_resume(struct platform_device *pdev)
+{
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+	int ret = -EPERM;
+
+	if (dev && dev->clk)
+		ret = clk_enable(dev->clk);
+
+	return ret;
+}
+
+static struct platform_driver spear_smi_driver = {
+	.driver = {
+		.name = "smi",
+		.bus = &platform_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = spear_smi_probe,
+	.remove = __devexit_p(spear_smi_remove),
+	.suspend = spear_smi_suspend,
+	.resume = spear_smi_resume,
+};
+
+static int spear_smi_init(void)
+{
+	return platform_driver_register(&spear_smi_driver);
+}
+module_init(spear_smi_init);
+
+static void spear_smi_exit(void)
+{
+	platform_driver_unregister(&spear_smi_driver);
+}
+module_exit(spear_smi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim at st.com>");
+MODULE_DESCRIPTION("MTD SMI driver for serial nor flash chips");
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:07 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:07 +0530
Subject: [PATCH V2 47/69] ST SPEAr13xx: Adding CPU hotplug support added for
	SMP platforms
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <af8b5622bfb525dd1bcb2f09bfabc70fe6012f8c.1285933332.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri at st.com>

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/Makefile  |    1 +
 arch/arm/mach-spear13xx/hotplug.c |  135 +++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/hotplug.c

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index 799eefa..869afb4 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -5,6 +5,7 @@
 # common files
 obj-y					+= spear13xx.o clock.o fsmc-nor.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
 obj-$(CONFIG_PCIEPORTBUS)		+= pcie.o
 obj-$(CONFIG_PM)			+= pm.o sleep.o
diff --git a/arch/arm/mach-spear13xx/hotplug.c b/arch/arm/mach-spear13xx/hotplug.c
new file mode 100644
index 0000000..a3259bf
--- /dev/null
+++ b/arch/arm/mach-spear13xx/hotplug.c
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/mach-spear13xx/hotplug.c
+ *
+ * Copyright (C) 2010 ST Microelectronics Ltd.
+ * Deepak Sikri <deepak.sikri at st.com>
+ *
+ * based upon linux/arch/arm/mach-realview/hotplug.c
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+
+extern volatile int pen_release;
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	dsb\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, #0x04\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0)
+	  : "cc", "memory");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile("mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, #0x04\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  :
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+	for (;;) {
+		wfi();
+
+		if (pen_release == cpu) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+
+		/*
+		 * getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * The trouble is, letting people know about this is not really
+		 * possible, since we are currently running incoherently, and
+		 * therefore cannot safely call printk() or anything else
+		 */
+#ifdef DEBUG
+		pr_crit("CPU%u: spurious wakeup call\n", cpu);
+#endif
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __cpuinit platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+	unsigned int this_cpu = hard_smp_processor_id();
+
+	if (cpu != this_cpu) {
+		pr_crit("Eek! platform_cpu_die running on %u, should\
+				be %u\n", this_cpu, cpu);
+		BUG();
+	}
+#endif
+
+	printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+	complete(&cpu_killed);
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:53 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:53 +0530
Subject: [PATCH V2 33/69] ST SPEAr: Changing resource size of amba devices to
	SZ_4K
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <1243c267fb4511427b22adaf6824d9cad25d3b36.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
---
 arch/arm/mach-spear3xx/spear300.c |    2 +-
 arch/arm/mach-spear3xx/spear320.c |    2 +-
 arch/arm/mach-spear3xx/spear3xx.c |    2 +-
 arch/arm/mach-spear6xx/spear6xx.c |    8 +++-----
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index fd83f53..c299e52 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -382,7 +382,7 @@ struct amba_device clcd_device = {
 	},
 	.res = {
 		.start = SPEAR300_CLCD_BASE,
-		.end = SPEAR300_CLCD_BASE + SPEAR300_CLCD_SIZE - 1,
+		.end = SPEAR300_CLCD_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.dma_mask = ~0,
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index e14e201..c228286 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -399,7 +399,7 @@ struct amba_device clcd_device = {
 	},
 	.res = {
 		.start = SPEAR320_CLCD_BASE,
-		.end = SPEAR320_CLCD_BASE + SPEAR320_CLCD_SIZE - 1,
+		.end = SPEAR320_CLCD_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.dma_mask = ~0,
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index b4c3ad7..34d8286 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -79,7 +79,7 @@ struct amba_device uart_device = {
 	},
 	.res = {
 		.start = SPEAR3XX_ICM1_UART_BASE,
-		.end = SPEAR3XX_ICM1_UART_BASE + SPEAR3XX_ICM1_UART_SIZE - 1,
+		.end = SPEAR3XX_ICM1_UART_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.irq = {IRQ_UART, NO_IRQ},
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 82788e1..e64fc57 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -35,7 +35,7 @@ struct amba_device clcd_device = {
 	},
 	.res = {
 		.start = SPEAR6XX_ICM3_CLCD_BASE,
-		.end = SPEAR6XX_ICM3_CLCD_BASE + SPEAR6XX_ICM3_CLCD_SIZE - 1,
+		.end = SPEAR6XX_ICM3_CLCD_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.dma_mask = ~0,
@@ -117,8 +117,7 @@ struct amba_device uart_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART0_BASE,
-			.end = SPEAR6XX_ICM1_UART0_BASE +
-				SPEAR6XX_ICM1_UART0_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART0_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_0, NO_IRQ},
@@ -128,8 +127,7 @@ struct amba_device uart_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART1_BASE,
-			.end = SPEAR6XX_ICM1_UART1_BASE +
-				SPEAR6XX_ICM1_UART1_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART1_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_1, NO_IRQ},
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:15 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:15 +0530
Subject: [PATCH V2 55/69] ST SPEAr3xx: Passing pmx devices address from
	machine *.c files
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <694da64e36590aafeb8aa214a85f396a1b4dd542.1285933332.git.viresh.kumar@st.com>

All spear3xx machines have different pad mux register addresses.
In order to have single image for all spear3xx boards, we need to pass
this address from machine specific files to fix addresses of pmx devs found
in spear3xx.c

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |   11 +++---
 arch/arm/mach-spear3xx/spear300.c             |   27 +++-----------
 arch/arm/mach-spear3xx/spear310.c             |   11 ++----
 arch/arm/mach-spear3xx/spear320.c             |   31 ++--------------
 arch/arm/mach-spear3xx/spear3xx.c             |   48 +++++++++---------------
 5 files changed, 36 insertions(+), 92 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 1b97ba8..0412808 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -50,6 +50,7 @@ void __init spear_setup_timer(void);
 void __init spear3xx_map_io(void);
 void __init spear3xx_init_irq(void);
 void __init spear3xx_init(void);
+void spear3xx_pmx_init_addr(struct pmx_driver *driver, unsigned int addr);
 
 /* pad mux declarations */
 #define PMX_FIRDA_MASK		(1 << 14)
@@ -150,8 +151,8 @@ extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
 
 /* pad multiplexing support */
-#define PAD_MUX_CONFIG_REG	0x99000000
-#define MODE_CONFIG_REG		0x99000004
+#define SPEAR300_PAD_MUX_CONFIG_REG	0x99000000
+#define SPEAR300_MODE_CONFIG_REG	0x99000004
 
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
@@ -183,7 +184,7 @@ extern struct pmx_dev pmx_uart3_4_5;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_rs485_0_1;
 extern struct pmx_dev pmx_tdm0;
-#define PAD_MUX_CONFIG_REG	0xB4000008
+#define SPEAR310_PAD_MUX_CONFIG_REG	0xB4000008
 
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
@@ -235,8 +236,8 @@ extern struct pmx_dev pmx_smii1;
 extern struct pmx_dev pmx_i2c1;
 
 /* pad multiplexing support */
-#define PAD_MUX_CONFIG_REG	0xB300000C
-#define MODE_CONFIG_REG		0xB3000010
+#define SPEAR320_PAD_MUX_CONFIG_REG	0xB300000C
+#define SPEAR320_MODE_CONFIG_REG	0xB3000010
 
 /* Add spear320 machine function declarations here */
 void __init spear320_init(void);
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 2671cfd..9885fe9 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -118,7 +118,6 @@ struct pmx_mode caml_lcd_mode = {
 /* Pad multiplexing for FSMC 2 NAND devices */
 static struct pmx_mux_reg pmx_fsmc_2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -142,7 +141,6 @@ struct pmx_dev pmx_fsmc_2_chips = {
 /* Pad multiplexing for FSMC 4 NAND devices */
 static struct pmx_mux_reg pmx_fsmc_4_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
 		.value = 0,
 	},
@@ -166,7 +164,6 @@ struct pmx_dev pmx_fsmc_4_chips = {
 /* Pad multiplexing for Keyboard device */
 static struct pmx_mux_reg pmx_kbd_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -192,7 +189,6 @@ struct pmx_dev pmx_keyboard = {
 /* Pad multiplexing for CLCD device */
 static struct pmx_mux_reg pmx_clcd_pfmode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -200,7 +196,6 @@ static struct pmx_mux_reg pmx_clcd_pfmode_mux[] = {
 
 static struct pmx_mux_reg pmx_clcd_lcdmode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -228,7 +223,6 @@ struct pmx_dev pmx_clcd = {
 /* Pad multiplexing for Telecom GPIO device */
 static struct pmx_mux_reg pmx_gpio_lcdmode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -236,7 +230,6 @@ static struct pmx_mux_reg pmx_gpio_lcdmode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_fonemode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -244,7 +237,6 @@ static struct pmx_mux_reg pmx_gpio_fonemode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_atai2smode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -252,7 +244,6 @@ static struct pmx_mux_reg pmx_gpio_atai2smode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_lendfonemode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -260,7 +251,6 @@ static struct pmx_mux_reg pmx_gpio_lendfonemode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_atawi2smode_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
 			| PMX_UART0_MODEM_MASK,
 		.value = 0,
@@ -300,7 +290,6 @@ struct pmx_dev pmx_telecom_gpio = {
 /* Pad multiplexing for TDM device */
 static struct pmx_mux_reg pmx_tdm_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -327,7 +316,6 @@ struct pmx_dev pmx_telecom_tdm = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_spi_cs_i2c_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -352,7 +340,6 @@ struct pmx_dev pmx_telecom_spi_cs_i2c_clk = {
 
 static struct pmx_mux_reg pmx_caml_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -360,7 +347,6 @@ static struct pmx_mux_reg pmx_caml_mux[] = {
 
 static struct pmx_mux_reg pmx_camu_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
 		.value = 0,
 	},
@@ -387,7 +373,6 @@ struct pmx_dev pmx_telecom_camera = {
 /* Pad multiplexing for dac device */
 static struct pmx_mux_reg pmx_dac_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -411,7 +396,6 @@ struct pmx_dev pmx_telecom_dac = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_i2s_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -437,7 +421,6 @@ struct pmx_dev pmx_telecom_i2s = {
 /* Pad multiplexing for bootpins device */
 static struct pmx_mux_reg pmx_bootpins_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
 		.value = 0,
@@ -461,7 +444,6 @@ struct pmx_dev pmx_telecom_boot_pins = {
 /* Pad multiplexing for sdhci 4bit device */
 static struct pmx_mux_reg pmx_sdhci_4bit_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
 			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
@@ -490,7 +472,6 @@ struct pmx_dev pmx_telecom_sdhci_4bit = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_sdhci_8bit_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
 			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
@@ -518,7 +499,6 @@ struct pmx_dev pmx_telecom_sdhci_8bit = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_gpio1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
 		.value = 0,
@@ -541,7 +521,7 @@ struct pmx_dev pmx_gpio1 = {
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
-	.mode_reg = {.address = MODE_CONFIG_REG, .mask = 0x0000000f},
+	.mode_reg = {.address = SPEAR300_MODE_CONFIG_REG, .mask = 0x0000000f},
 };
 
 /* Add spear300 specific devices here */
@@ -777,7 +757,7 @@ struct spear_shirq shirq_ras1 = {
 void sdhci_i2s_mem_enable(u8 mask)
 {
 	u32 val;
-	void __iomem *config = ioremap(MODE_CONFIG_REG, SZ_16);
+	void __iomem *config = ioremap(SPEAR300_MODE_CONFIG_REG, SZ_16);
 	if (!config) {
 		pr_debug("sdhci_i2s_enb: ioremap fail\n");
 		return;
@@ -809,6 +789,9 @@ void __init spear300_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ\n");
 	}
 
+	/* This fixes addresses of all pmx devices for spear300 */
+	spear3xx_pmx_init_addr(&pmx_driver, SPEAR300_PAD_MUX_CONFIG_REG);
+
 	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 79f7105..be2f9de 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -26,7 +26,6 @@
 /* Pad multiplexing for emi_cs_0_1_4_5 devices */
 static struct pmx_mux_reg pmx_emi_cs_0_1_4_5_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -48,7 +47,6 @@ struct pmx_dev pmx_emi_cs_0_1_4_5 = {
 /* Pad multiplexing for emi_cs_2_3 devices */
 static struct pmx_mux_reg pmx_emi_cs_2_3_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -70,7 +68,6 @@ struct pmx_dev pmx_emi_cs_2_3 = {
 /* Pad multiplexing for uart1 device */
 static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -92,7 +89,6 @@ struct pmx_dev pmx_uart1 = {
 /* Pad multiplexing for uart2 device */
 static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -114,7 +110,6 @@ struct pmx_dev pmx_uart2 = {
 /* Pad multiplexing for uart3_4_5 devices */
 static struct pmx_mux_reg pmx_uart3_4_5_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -136,7 +131,6 @@ struct pmx_dev pmx_uart3_4_5 = {
 /* Pad multiplexing for fsmc device */
 static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -158,7 +152,6 @@ struct pmx_dev pmx_fsmc = {
 /* Pad multiplexing for rs485_0_1 devices */
 static struct pmx_mux_reg pmx_rs485_0_1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -180,7 +173,6 @@ struct pmx_dev pmx_rs485_0_1 = {
 /* Pad multiplexing for tdm0 device */
 static struct pmx_mux_reg pmx_tdm0_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -523,6 +515,9 @@ void __init spear310_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
 
+	/* This fixes addresses of all pmx devices for spear310 */
+	spear3xx_pmx_init_addr(&pmx_driver, SPEAR310_PAD_MUX_CONFIG_REG);
+
 	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 8481955..bd308b8 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -58,7 +58,6 @@ struct pmx_mode small_printers_mode = {
 /* Pad multiplexing for CLCD device */
 static struct pmx_mux_reg pmx_clcd_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -81,7 +80,6 @@ struct pmx_dev pmx_clcd = {
 /* Pad multiplexing for EMI (Parallel NOR flash) device */
 static struct pmx_mux_reg pmx_emi_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -104,7 +102,6 @@ struct pmx_dev pmx_emi = {
 /* Pad multiplexing for FSMC (NAND flash) device */
 static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -127,7 +124,6 @@ struct pmx_dev pmx_fsmc = {
 /* Pad multiplexing for SPP device */
 static struct pmx_mux_reg pmx_spp_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -150,7 +146,6 @@ struct pmx_dev pmx_spp = {
 /* Pad multiplexing for SDHCI device */
 static struct pmx_mux_reg pmx_sdhci_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -174,7 +169,6 @@ struct pmx_dev pmx_sdhci = {
 /* Pad multiplexing for I2S device */
 static struct pmx_mux_reg pmx_i2s_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -197,7 +191,6 @@ struct pmx_dev pmx_i2s = {
 /* Pad multiplexing for UART1 device */
 static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
 		.value = 0,
 	},
@@ -220,7 +213,6 @@ struct pmx_dev pmx_uart1 = {
 /* Pad multiplexing for UART1 Modem device */
 static struct pmx_mux_reg pmx_uart1_modem_autoexp_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK |
 			PMX_SSP_CS_MASK,
 		.value = 0,
@@ -229,7 +221,6 @@ static struct pmx_mux_reg pmx_uart1_modem_autoexp_mux[] = {
 
 static struct pmx_mux_reg pmx_uart1_modem_smallpri_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
 			PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
 		.value = 0,
@@ -257,7 +248,6 @@ struct pmx_dev pmx_uart1_modem = {
 /* Pad multiplexing for UART2 device */
 static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -280,7 +270,6 @@ struct pmx_dev pmx_uart2 = {
 /* Pad multiplexing for Touchscreen device */
 static struct pmx_mux_reg pmx_touchscreen_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -303,7 +292,6 @@ struct pmx_dev pmx_touchscreen = {
 /* Pad multiplexing for CAN device */
 static struct pmx_mux_reg pmx_can_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
 		.value = 0,
@@ -327,7 +315,6 @@ struct pmx_dev pmx_can = {
 /* Pad multiplexing for SDHCI LED device */
 static struct pmx_mux_reg pmx_sdhci_led_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -350,7 +337,6 @@ struct pmx_dev pmx_sdhci_led = {
 /* Pad multiplexing for PWM0 device */
 static struct pmx_mux_reg pmx_pwm0_net_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -358,7 +344,6 @@ static struct pmx_mux_reg pmx_pwm0_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm0_autoexpsmallpri_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -385,7 +370,6 @@ struct pmx_dev pmx_pwm0 = {
 /* Pad multiplexing for PWM1 device */
 static struct pmx_mux_reg pmx_pwm1_net_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -393,7 +377,6 @@ static struct pmx_mux_reg pmx_pwm1_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm1_autoexpsmallpri_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -420,7 +403,6 @@ struct pmx_dev pmx_pwm1 = {
 /* Pad multiplexing for PWM2 device */
 static struct pmx_mux_reg pmx_pwm2_net_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -428,7 +410,6 @@ static struct pmx_mux_reg pmx_pwm2_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm2_autoexpsmallpri_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -455,7 +436,6 @@ struct pmx_dev pmx_pwm2 = {
 /* Pad multiplexing for PWM3 device */
 static struct pmx_mux_reg pmx_pwm3_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -478,7 +458,6 @@ struct pmx_dev pmx_pwm3 = {
 /* Pad multiplexing for SSP1 device */
 static struct pmx_mux_reg pmx_ssp1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -501,7 +480,6 @@ struct pmx_dev pmx_ssp1 = {
 /* Pad multiplexing for SSP2 device */
 static struct pmx_mux_reg pmx_ssp2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -524,7 +502,6 @@ struct pmx_dev pmx_ssp2 = {
 /* Pad multiplexing for mii1 device */
 static struct pmx_mux_reg pmx_mii1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -547,7 +524,6 @@ struct pmx_dev pmx_mii1 = {
 /* Pad multiplexing for smii0 device */
 static struct pmx_mux_reg pmx_smii0_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -570,7 +546,6 @@ struct pmx_dev pmx_smii0 = {
 /* Pad multiplexing for smii1 device */
 static struct pmx_mux_reg pmx_smii1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -593,7 +568,6 @@ struct pmx_dev pmx_smii1 = {
 /* Pad multiplexing for i2c1 device */
 static struct pmx_mux_reg pmx_i2c1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -615,7 +589,7 @@ struct pmx_dev pmx_i2c1 = {
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
-	.mode_reg = {.address = MODE_CONFIG_REG, .mask = 0x00000007},
+	.mode_reg = {.address = SPEAR320_MODE_CONFIG_REG, .mask = 0x00000007},
 };
 
 /* Add spear320 specific devices here */
@@ -1015,6 +989,9 @@ void __init spear320_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
 
+	/* This fixes addresses of all pmx devices for spear320 */
+	spear3xx_pmx_init_addr(&pmx_driver, SPEAR320_PAD_MUX_CONFIG_REG);
+
 	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 45a0774..ec1340c 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -297,7 +297,6 @@ void __init spear3xx_map_io(void)
 /* Pad multiplexing for firda device */
 static struct pmx_mux_reg pmx_firda_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = PMX_FIRDA_MASK,
 	},
@@ -320,7 +319,6 @@ struct pmx_dev pmx_firda = {
 /* Pad multiplexing for i2c device */
 static struct pmx_mux_reg pmx_i2c_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
 		.value = PMX_I2C_MASK,
 	},
@@ -343,7 +341,6 @@ struct pmx_dev pmx_i2c = {
 /* Pad multiplexing for firda device */
 static struct pmx_mux_reg pmx_ssp_cs_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = PMX_SSP_CS_MASK,
 	},
@@ -366,7 +363,6 @@ struct pmx_dev pmx_ssp_cs = {
 /* Pad multiplexing for ssp device */
 static struct pmx_mux_reg pmx_ssp_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
 		.value = PMX_SSP_MASK,
 	},
@@ -389,7 +385,6 @@ struct pmx_dev pmx_ssp = {
 /* Pad multiplexing for mii device */
 static struct pmx_mux_reg pmx_mii_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = PMX_MII_MASK,
 	},
@@ -412,7 +407,6 @@ struct pmx_dev pmx_mii = {
 /* Pad multiplexing for gpio pin0 device */
 static struct pmx_mux_reg pmx_gpio_pin0_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
 		.value = PMX_GPIO_PIN0_MASK,
 	},
@@ -435,7 +429,6 @@ struct pmx_dev pmx_gpio_pin0 = {
 /* Pad multiplexing for gpio pin1 device */
 static struct pmx_mux_reg pmx_gpio_pin1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
 		.value = PMX_GPIO_PIN1_MASK,
 	},
@@ -458,7 +451,6 @@ struct pmx_dev pmx_gpio_pin1 = {
 /* Pad multiplexing for gpio pin2 device */
 static struct pmx_mux_reg pmx_gpio_pin2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
 		.value = PMX_GPIO_PIN2_MASK,
 	},
@@ -481,7 +473,6 @@ struct pmx_dev pmx_gpio_pin2 = {
 /* Pad multiplexing for gpio pin3 device */
 static struct pmx_mux_reg pmx_gpio_pin3_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
 		.value = PMX_GPIO_PIN3_MASK,
 	},
@@ -504,7 +495,6 @@ struct pmx_dev pmx_gpio_pin3 = {
 /* Pad multiplexing for gpio pin4 device */
 static struct pmx_mux_reg pmx_gpio_pin4_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
 		.value = PMX_GPIO_PIN4_MASK,
 	},
@@ -527,7 +517,6 @@ struct pmx_dev pmx_gpio_pin4 = {
 /* Pad multiplexing for gpio pin5 device */
 static struct pmx_mux_reg pmx_gpio_pin5_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
 		.value = PMX_GPIO_PIN5_MASK,
 	},
@@ -550,7 +539,6 @@ struct pmx_dev pmx_gpio_pin5 = {
 /* Pad multiplexing for uart0 modem device */
 static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = PMX_UART0_MODEM_MASK,
 	},
@@ -573,7 +561,6 @@ struct pmx_dev pmx_uart0_modem = {
 /* Pad multiplexing for uart0 device */
 static struct pmx_mux_reg pmx_uart0_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
 		.value = PMX_UART0_MASK,
 	},
@@ -596,7 +583,6 @@ struct pmx_dev pmx_uart0 = {
 /* Pad multiplexing for timer 3, 4 device */
 static struct pmx_mux_reg pmx_timer_3_4_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = PMX_TIMER_3_4_MASK,
 	},
@@ -619,7 +605,6 @@ struct pmx_dev pmx_timer_3_4 = {
 /* Pad multiplexing for gpio pin0 device */
 static struct pmx_mux_reg pmx_timer_1_2_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = PMX_TIMER_1_2_MASK,
 	},
@@ -644,7 +629,6 @@ struct pmx_dev pmx_timer_1_2 = {
 /* Pad multiplexing for plgpio_0_1 devices */
 static struct pmx_mux_reg pmx_plgpio_0_1_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -667,7 +651,6 @@ struct pmx_dev pmx_plgpio_0_1 = {
 /* Pad multiplexing for plgpio_2_3 devices */
 static struct pmx_mux_reg pmx_plgpio_2_3_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
 		.value = 0,
 	},
@@ -690,7 +673,6 @@ struct pmx_dev pmx_plgpio_2_3 = {
 /* Pad multiplexing for plgpio_4_5 devices */
 static struct pmx_mux_reg pmx_plgpio_4_5_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
 		.value = 0,
 	},
@@ -713,7 +695,6 @@ struct pmx_dev pmx_plgpio_4_5 = {
 /* Pad multiplexing for plgpio_6_9 devices */
 static struct pmx_mux_reg pmx_plgpio_6_9_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
 		.value = 0,
 	},
@@ -736,7 +717,6 @@ struct pmx_dev pmx_plgpio_6_9 = {
 /* Pad multiplexing for plgpio_10_27 devices */
 static struct pmx_mux_reg pmx_plgpio_10_27_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -759,7 +739,6 @@ struct pmx_dev pmx_plgpio_10_27 = {
 /* Pad multiplexing for plgpio_28 devices */
 static struct pmx_mux_reg pmx_plgpio_28_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
 		.value = 0,
 	},
@@ -782,7 +761,6 @@ struct pmx_dev pmx_plgpio_28 = {
 /* Pad multiplexing for plgpio_29 devices */
 static struct pmx_mux_reg pmx_plgpio_29_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
 		.value = 0,
 	},
@@ -805,7 +783,6 @@ struct pmx_dev pmx_plgpio_29 = {
 /* Pad multiplexing for plgpio_30 device */
 static struct pmx_mux_reg pmx_plgpio_30_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
 		.value = 0,
 	},
@@ -828,7 +805,6 @@ struct pmx_dev pmx_plgpio_30 = {
 /* Pad multiplexing for plgpio_31 device */
 static struct pmx_mux_reg pmx_plgpio_31_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
 		.value = 0,
 	},
@@ -851,7 +827,6 @@ struct pmx_dev pmx_plgpio_31 = {
 /* Pad multiplexing for plgpio_32 device */
 static struct pmx_mux_reg pmx_plgpio_32_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
 		.value = 0,
 	},
@@ -874,7 +849,6 @@ struct pmx_dev pmx_plgpio_32 = {
 /* Pad multiplexing for plgpio_33 device */
 static struct pmx_mux_reg pmx_plgpio_33_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
 		.value = 0,
 	},
@@ -897,7 +871,6 @@ struct pmx_dev pmx_plgpio_33 = {
 /* Pad multiplexing for plgpio_34_36 device */
 static struct pmx_mux_reg pmx_plgpio_34_36_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -920,7 +893,6 @@ struct pmx_dev pmx_plgpio_34_36 = {
 /* Pad multiplexing for plgpio_37_42 device */
 static struct pmx_mux_reg pmx_plgpio_37_42_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -943,7 +915,6 @@ struct pmx_dev pmx_plgpio_37_42 = {
 /* Pad multiplexing for plgpio_43_44_47_48 device */
 static struct pmx_mux_reg pmx_plgpio_43_44_47_48_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -966,7 +937,6 @@ struct pmx_dev pmx_plgpio_43_44_47_48 = {
 /* Pad multiplexing for plgpio_45_46_49_50 device */
 static struct pmx_mux_reg pmx_plgpio_45_46_49_50_mux[] = {
 	{
-		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -1017,3 +987,21 @@ static void __init spear3xx_timer_init(void)
 struct sys_timer spear3xx_timer = {
 	.init = spear3xx_timer_init,
 };
+
+/* This fixes addresses of all pmx devices for different machines */
+void spear3xx_pmx_init_addr(struct pmx_driver *driver, unsigned int addr)
+{
+	int i;
+	for (i = 0; i < driver->devs_count; i++) {
+		int j;
+		struct pmx_dev *pdev = driver->devs[i];
+
+		for (j = 0; j < pdev->mode_count; j++) {
+			int k;
+			struct pmx_dev_mode *mode = &pdev->modes[j];
+
+			for (k = 0; k < mode->mux_reg_cnt; k++)
+				mode->mux_regs[k].address = addr;
+		}
+	}
+}
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:05 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:05 +0530
Subject: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <c91308e26397dbe49f384c7d3cf168593e1fe8b0.1285933332.git.viresh.kumar@st.com>

From: Pratyush Anand <pratyush.anand at st.com>

This is a configurable gadget. can be configured by sysfs interface. Any
IP available at PCIE bus can be programmed to be used by host
controller.It supoorts both INTX and MSI.
By default, gadget is configured for INTX and SYSRAM1 is mapped to BAR0
with size 0x1000

Signed-off-by: Pratyush Anand <pratyush.anand at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 drivers/misc/Kconfig                 |   10 +
 drivers/misc/Makefile                |    1 +
 drivers/misc/spear13xx_pcie_gadget.c |  888 ++++++++++++++++++++++++++++++++++
 3 files changed, 899 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/spear13xx_pcie_gadget.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index b743312..e19deda 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -344,6 +344,16 @@ config DS1682
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1682.
 
+config SPEAR13XX_PCIE_GADGET
+	bool "PCIE gadget support for SPEAr13XX platform"
+	depends on ARCH_SPEAR13XX
+	default n
+	help
+	 This option enables gadget support for PCIE controller. If
+	 board file defines any controller as PCIE endpoint then a sysfs
+	 entry will be created for that controller. User can use these
+	 sysfs node to configure PCIE EP as per his requirements.
+
 config TI_DAC7512
 	tristate "Texas Instruments DAC7512"
 	depends on SPI && SYSFS
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 42eab95..9408f23 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -33,5 +33,6 @@ obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
+obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)	+= spear13xx_pcie_gadget.o
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
new file mode 100644
index 0000000..dc63a28
--- /dev/null
+++ b/drivers/misc/spear13xx_pcie_gadget.c
@@ -0,0 +1,888 @@
+/*
+ * drivers/misc/spear13xx_pcie_gadget.c
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Pratyush Anand<pratyush.anand at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/pci_regs.h>
+#include <mach/pcie.h>
+#include <mach/misc_regs.h>
+
+#define IN0_MEM_SIZE	(200 * 1024 * 1024 - 1)
+/* In current implementation address translation is done using IN0 only.
+ * So IN1 start address and IN0 end address has been kept same
+*/
+#define IN1_MEM_SIZE	(0 * 1024 * 1024 - 1)
+#define IN_IO_SIZE	(20 * 1024 * 1024 - 1)
+#define IN_CFG0_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_CFG1_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_MSG_SIZE	(12 * 1024 * 1024 - 1)
+/* Keep default BAR size as 4K*/
+/* AORAM would be mapped by default*/
+#define INBOUND_ADDR_MASK	(SPEAR13XX_SYSRAM1_SIZE - 1)
+
+#define INT_TYPE_NO_INT	0
+#define INT_TYPE_INTX	1
+#define INT_TYPE_MSI	2
+struct spear_pcie_gadget_config {
+	void __iomem *base;
+	void __iomem *va_app_base;
+	void __iomem *va_dbi_base;
+	char int_type[10];
+	u32 requested_msi;
+	u32 configured_msi;
+	u32 bar0_size;
+	u32 bar0_rw_offset;
+	u32 va_bar0_address;
+};
+
+static void enable_dbi_access(struct pcie_app_reg *app_reg)
+{
+	/* Enable DBI access */
+	writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void disable_dbi_access(struct pcie_app_reg *app_reg)
+{
+	/* disable DBI access */
+	writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 *val)
+{
+	struct pcie_app_reg *app_reg
+		= (struct pcie_app_reg *) config->va_app_base;
+	u32 va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (u32)config->va_dbi_base + (where & ~0x3);
+
+	*val = readl(va_address);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 val)
+{
+	struct pcie_app_reg *app_reg
+		= (struct pcie_app_reg *) config->va_app_base;
+	u32 va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (u32)config->va_dbi_base + (where & ~0x3);
+
+	if (size == 4)
+		writel(val, va_address);
+	else if (size == 2)
+		writew(val, va_address + (where & 2));
+	else if (size == 1)
+		writeb(val, va_address + (where & 3));
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+#define PCI_FIND_CAP_TTL	48
+
+static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config,
+		u32 pos, int cap, int *ttl)
+{
+	u32 id;
+
+	while ((*ttl)--) {
+		spear_dbi_read_reg(config, pos, 1, &pos);
+		if (pos < 0x40)
+			break;
+		pos &= ~3;
+		spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos += PCI_CAP_LIST_NEXT;
+	}
+	return 0;
+}
+
+static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config,
+			u32 pos, int cap)
+{
+	int ttl = PCI_FIND_CAP_TTL;
+
+	return pci_find_own_next_cap_ttl(config, pos, cap, &ttl);
+}
+
+static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config,
+				u8 hdr_type)
+{
+	u32 status;
+
+	spear_dbi_read_reg(config, PCI_STATUS, 2, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+
+	switch (hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+	case PCI_HEADER_TYPE_BRIDGE:
+		return PCI_CAPABILITY_LIST;
+	case PCI_HEADER_TYPE_CARDBUS:
+		return PCI_CB_CAPABILITY_LIST;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+/**
+ * Tell if a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it. Possible values for @cap:
+ *
+ * %PCI_CAP_ID_PM	Power Management
+ * %PCI_CAP_ID_AGP	Accelerated Graphics Port
+ * %PCI_CAP_ID_VPD	Vital Product Data
+ * %PCI_CAP_ID_SLOTID	Slot Identification
+ * %PCI_CAP_ID_MSI	Message Signalled Interrupts
+ * %PCI_CAP_ID_CHSWP	CompactPCI HotSwap
+ * %PCI_CAP_ID_PCIX	PCI-X
+ * %PCI_CAP_ID_EXP	PCI Express
+ */
+static int pci_find_own_capability(struct spear_pcie_gadget_config *config,
+		int cap)
+{
+	u32 pos;
+	u32 hdr_type;
+
+	spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type);
+
+	pos = pci_find_own_cap_start(config, hdr_type);
+	if (pos)
+		pos = pci_find_own_next_cap(config, pos, cap);
+
+	return pos;
+}
+
+static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
+{
+	return 0;
+}
+
+static ssize_t pcie_gadget_show_link(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+
+	if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
+		return sprintf(buf, "UP");
+	else
+		return sprintf(buf, "DOWN");
+}
+
+static ssize_t pcie_gadget_store_link(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+	char link[10];
+
+	if (sscanf(buf, "%s", link) != 1)
+		return -EINVAL;
+
+	if (!strcmp(link, "UP"))
+		writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
+			&app_reg->app_ctrl_0);
+	else
+		writel(readl(&app_reg->app_ctrl_0)
+				& ~(1 << APP_LTSSM_ENABLE_ID),
+				&app_reg->app_ctrl_0);
+	return count;
+}
+
+static DEVICE_ATTR(link, S_IWUSR | S_IRUGO, pcie_gadget_show_link,
+		pcie_gadget_store_link);
+
+static ssize_t pcie_gadget_show_int_type(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s", config->int_type);
+}
+
+static ssize_t pcie_gadget_store_int_type(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	char int_type[10];
+	u32 cap, vector, vec, flags;
+
+	if (sscanf(buf, "%s", int_type) != 1)
+		return -EINVAL;
+
+	if (!strcmp(int_type, "INTA"))
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+
+	else if (!strcmp(int_type, "MSI")) {
+		vector = config->requested_msi;
+		vec = 0;
+		while (vector > 1) {
+			vector /= 2;
+			vec++;
+		}
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QMASK;
+		flags |= vec << 1;
+		spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
+	}
+
+	strcpy(config->int_type, int_type);
+
+	return count;
+}
+
+static DEVICE_ATTR(int_type, S_IWUSR | S_IRUGO, pcie_gadget_show_int_type,
+		pcie_gadget_store_int_type);
+
+static ssize_t pcie_gadget_show_no_of_msi(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+	u32 cap, vector, vec, flags;
+
+	if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
+			!= (1 << CFG_MSI_EN_ID))
+		vector = 0;
+	else {
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QSIZE;
+		vec = flags >> 4;
+		vector = 1;
+		while (vec--)
+			vector *= 2;
+	}
+	config->configured_msi = vector;
+
+	return sprintf(buf, "%u", vector);
+}
+
+static ssize_t pcie_gadget_store_no_of_msi(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+
+	if (sscanf(buf, "%u", &config->requested_msi) != 1)
+		return -EINVAL;
+	if (config->requested_msi > 32)
+		config->requested_msi = 32;
+
+	return count;
+}
+
+static DEVICE_ATTR(no_of_msi, S_IWUSR | S_IRUGO, pcie_gadget_show_no_of_msi,
+		pcie_gadget_store_no_of_msi);
+
+static ssize_t pcie_gadget_store_inta(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+	int en;
+
+	if (sscanf(buf, "%d", &en) != 1)
+		return -EINVAL;
+
+	if (en)
+		writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+	else
+		writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+
+	return count;
+}
+
+static DEVICE_ATTR(inta, S_IWUSR, NULL, pcie_gadget_store_inta);
+
+static ssize_t pcie_gadget_store_send_msi(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+	int vector;
+	u32 ven_msi;
+
+	if (sscanf(buf, "%d", &vector) != 1)
+		return -EINVAL;
+
+	if (!config->configured_msi)
+		return -EINVAL;
+
+	if (vector >= config->configured_msi)
+		return -EINVAL;
+
+	ven_msi = readl(&app_reg->ven_msi_1);
+	ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
+	ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
+	ven_msi &= ~VEN_MSI_TC_MASK;
+	ven_msi |= 0 << VEN_MSI_TC_ID;
+	ven_msi &= ~VEN_MSI_VECTOR_MASK;
+	ven_msi |= vector << VEN_MSI_VECTOR_ID;
+
+	/*generating interrupt for msi vector*/
+	ven_msi |= VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+	/*need to wait till this bit is cleared, it is not cleared
+	 * autometically[Bug RTL] TBD*/
+	udelay(1);
+	ven_msi &= ~VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+
+	return count;
+}
+
+static DEVICE_ATTR(send_msi, S_IWUSR, NULL, pcie_gadget_store_send_msi);
+
+static ssize_t pcie_gadget_show_vendor_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_vendor_id(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 id;
+
+	if (sscanf(buf, "%x", &id) != 1)
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
+
+	return count;
+}
+
+static DEVICE_ATTR(vendor_id, S_IWUSR | S_IRUGO, pcie_gadget_show_vendor_id,
+		pcie_gadget_store_vendor_id);
+
+static ssize_t pcie_gadget_show_device_id(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_device_id(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 id;
+
+	if (sscanf(buf, "%x", &id) != 1)
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
+
+	return count;
+}
+
+static DEVICE_ATTR(device_id, S_IWUSR | S_IRUGO, pcie_gadget_show_device_id,
+		pcie_gadget_store_device_id);
+
+static ssize_t pcie_gadget_show_bar0_size(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%x", config->bar0_size);
+}
+
+static ssize_t pcie_gadget_store_bar0_size(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 size, pos, pos1;
+	u32 no_of_bit = 0;
+
+	if (sscanf(buf, "%x", &size) != 1)
+		return -EINVAL;
+	/* as per PCIE specs, min bar size supported is 128 bytes. But
+	 * our controller supports min as 256*/
+	if (size <= 0x100)
+		size = 0x100;
+	/* max bar size is 1MB*/
+	else if (size >= 0x100000)
+		size = 0x100000;
+	else {
+		pos = 0;
+		pos1 = 0;
+		while (pos < 21) {
+			pos = find_next_bit((unsigned long *)&size, 21, pos);
+			if (pos != 21)
+				pos1 = pos + 1;
+			pos++;
+			no_of_bit++;
+		}
+		if (no_of_bit == 2)
+			pos1--;
+
+		size = 1 << pos1;
+	}
+	config->bar0_size = size;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
+
+	return count;
+}
+
+static DEVICE_ATTR(bar0_size, S_IWUSR | S_IRUGO, pcie_gadget_show_bar0_size,
+		pcie_gadget_store_bar0_size);
+
+static ssize_t pcie_gadget_show_bar0_address(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+
+	u32 address = readl(&app_reg->pim0_mem_addr_start);
+
+	return sprintf(buf, "%x", address);
+}
+
+static ssize_t pcie_gadget_store_bar0_address(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+	u32 address;
+
+	if (sscanf(buf, "%x", &address) != 1)
+		return -EINVAL;
+
+	address &= ~(config->bar0_size - 1);
+	if (config->va_bar0_address)
+		iounmap((void *)config->va_bar0_address);
+	config->va_bar0_address = (u32)ioremap(address, config->bar0_size);
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(address, &app_reg->pim0_mem_addr_start);
+
+	return count;
+}
+
+static DEVICE_ATTR(bar0_address, S_IWUSR | S_IRUGO,
+		pcie_gadget_show_bar0_address, pcie_gadget_store_bar0_address);
+
+static ssize_t pcie_gadget_show_bar0_rw_offset(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%x", config->bar0_rw_offset);
+}
+
+static ssize_t pcie_gadget_store_bar0_rw_offset(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 offset;
+
+	if (sscanf(buf, "%x", &offset) != 1)
+		return -EINVAL;
+
+	if (offset % 4)
+		return -EINVAL;
+
+	config->bar0_rw_offset = offset;
+
+	return count;
+}
+
+static DEVICE_ATTR(bar0_rw_offset, S_IWUSR | S_IRUGO,
+	pcie_gadget_show_bar0_rw_offset, pcie_gadget_store_bar0_rw_offset);
+
+static ssize_t pcie_gadget_show_bar0_data(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 data;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	data = readl(config->va_bar0_address + config->bar0_rw_offset);
+
+	return sprintf(buf, "%x", data);
+}
+
+static ssize_t pcie_gadget_store_bar0_data(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
+	u32 data;
+
+	if (sscanf(buf, "%x", &data) != 1)
+		return -EINVAL;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(data, config->va_bar0_address + config->bar0_rw_offset);
+
+	return count;
+}
+
+static DEVICE_ATTR(bar0_data, S_IWUSR | S_IRUGO,
+		pcie_gadget_show_bar0_data, pcie_gadget_store_bar0_data);
+
+static ssize_t pcie_gadget_show_help(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	char text[] = "\t\tlink read->ltssm status\n \
+		link write->arg1 = UP to enable ltsmm DOWN to disable\n \
+		int_type read->type of supported interrupt\n \
+		int_type write->arg1 = interrupt type to be configured and\n \
+		can be INTA, MSI or NO_INT\n \
+		(select MSI only when you have programmed no_of_msi)\n \
+		no_of_msi read->zero if MSI is not enabled by host\n \
+		and positive value is the number of MSI vector granted\n \
+		no_of_msi write->arg1 = number of MSI vector needed\n \
+		inta write->arg1 = 1 to assert INTA and 0 to de-assert\n \
+		send_msi write->arg1 = MSI vector to be send\n \
+		vendor_id read->programmed vendor id (hex)\n\
+		vendor_id write->arg1 = vendor id(hex) to be programmed\n \
+		device_id read->programmed device id(hex)\n \
+		device_id write->arg1 = device id(hex) to be programmed\n \
+		bar0_size read->size of bar0 in hex\n \
+		bar0_size write->arg1= size of bar0 in hex\n \
+		(default bar0 size is 1000 (hex) bytes)\n \
+		bar0_address read->address of bar0 mapped area in hex\n \
+		bar0_address write->arg1 = address of bar0 mapped area in hex\n\
+		(default mapping of bar0 is SYSRAM1(E0800000)\n \
+		(always program bar size before bar address)\n \
+		(kernel might modify bar size and address to align)\n \
+		(read back bar size and address after writing to check)\n \
+		bar0_rw_offset read->offset of bar0 for which bar0_data \n \
+		will return value\n \
+		bar0_rw_offset write->arg1 = offset of bar0 for which\n \
+		bar0_data will write value\n \
+		bar0_data read->data at bar0_rw_offset\n \
+		bar0_data write->arg1 = data to be written at\n \
+		bar0_rw_offset\n";
+
+	int size = (sizeof(text) < PAGE_SIZE) ? sizeof(text) : PAGE_SIZE;
+
+	return snprintf(buf, size, "%s", text);
+}
+
+static DEVICE_ATTR(help, S_IRUGO, pcie_gadget_show_help, NULL);
+
+static struct attribute *pcie_gadget_attributes[] = {
+	&dev_attr_link.attr,
+	&dev_attr_int_type.attr,
+	&dev_attr_no_of_msi.attr,
+	&dev_attr_inta.attr,
+	&dev_attr_send_msi.attr,
+	&dev_attr_vendor_id.attr,
+	&dev_attr_device_id.attr,
+	&dev_attr_bar0_size.attr,
+	&dev_attr_bar0_address.attr,
+	&dev_attr_bar0_rw_offset.attr,
+	&dev_attr_bar0_data.attr,
+	&dev_attr_help.attr,
+	NULL
+};
+
+static const struct attribute_group pcie_gadget_attr_group = {
+	.attrs = pcie_gadget_attributes,
+};
+
+static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
+{
+	struct pcie_app_reg *app_reg =
+		(struct pcie_app_reg *)config->va_app_base;
+
+	/*setup registers for outbound translation */
+
+	writel(config->base, &app_reg->in0_mem_addr_start);
+	writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
+			&app_reg->in0_mem_addr_limit);
+	writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
+			&app_reg->in1_mem_addr_limit);
+	writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
+	writel(app_reg->in_io_addr_start + IN_IO_SIZE,
+			&app_reg->in_io_addr_limit);
+	writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
+	writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
+			&app_reg->in_cfg0_addr_limit);
+	writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
+	writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
+			&app_reg->in_cfg1_addr_limit);
+	writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
+	writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
+			&app_reg->in_msg_addr_limit);
+
+	writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
+	writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
+
+	/*setup registers for inbound translation */
+
+	/* Keep AORAM mapped at BAR0 as default */
+	config->bar0_size = INBOUND_ADDR_MASK + 1;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
+	spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC);
+	config->va_bar0_address = (u32)ioremap(SPEAR13XX_SYSRAM1_BASE,
+			config->bar0_size);
+
+	writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start);
+	writel(0, &app_reg->pim1_mem_addr_start);
+	writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
+
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_rom_addr_start);
+
+	writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+	/* disable all rx interrupts */
+	writel(0, &app_reg->int_mask);
+
+	/* Select INTA as default*/
+	spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+}
+
+static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	struct spear_pcie_gadget_config *config;
+	unsigned int status = 0;
+	int irq;
+	struct clk *clk;
+
+	/* get resource for application registers*/
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res0) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		return -EBUSY;
+	}
+	if (!request_mem_region(res0->start, resource_size(res0),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		return -EBUSY;
+	}
+	/* get resource for dbi registers*/
+
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res1) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		goto err_rel_res0;
+	}
+	if (!request_mem_region(res1->start, resource_size(res1),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		goto err_rel_res0;
+	}
+
+	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	if (!config) {
+		dev_err(&pdev->dev, "out of memory\n");
+		status = -ENOMEM;
+		goto err_rel_res;
+	}
+
+	config->va_app_base = ioremap(res0->start, resource_size(res0));
+	if (!config->va_app_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	config->base = (void *)res1->start;
+
+	config->va_dbi_base = ioremap(res1->start, resource_size(res1));
+	if (!config->va_dbi_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_iounmap_app;
+	}
+
+	dev_set_drvdata(&pdev->dev, config);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no update irq?\n");
+		status = irq;
+		goto err_iounmap;
+	}
+
+	status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
+	if (status) {
+		dev_err(&pdev->dev, "pcie gadget interrupt IRQ%d already \
+				claimed\n", irq);
+		goto err_get_irq;
+	}
+	/* Register sysfs hooks */
+	status = sysfs_create_group(&pdev->dev.kobj, &pcie_gadget_attr_group);
+	if (status)
+		goto err_irq;
+
+	/* init basic pcie application registers*/
+	/* do not enable clock if it is PCIE0.Ideally , all controller should
+	 * have been independent from others with respect to clock. But PCIE1
+	 * and 2 depends on PCIE0.So PCIE0 clk is provided during board init.*/
+	if (pdev->id == 1) {
+		/* Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne*/
+		clk = clk_get_sys("pcie1", NULL);
+		if (!clk) {
+			pr_err("%s:couldn't get clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+	} else if (pdev->id == 2) {
+		/* Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne*/
+		clk = clk_get_sys("pcie2", NULL);
+		if (!clk) {
+			pr_err("%s:couldn't get clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+	}
+	spear13xx_pcie_device_init(config);
+
+	return 0;
+err_irq:
+	free_irq(irq, NULL);
+err_get_irq:
+	dev_set_drvdata(&pdev->dev, NULL);
+err_iounmap:
+	iounmap(config->va_dbi_base);
+err_iounmap_app:
+	iounmap(config->va_app_base);
+err_kzalloc:
+	kfree(config);
+err_rel_res:
+	release_mem_region(res1->start, resource_size(res1));
+err_rel_res0:
+	release_mem_region(res0->start, resource_size(res0));
+	return status;
+}
+
+static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	struct spear_pcie_gadget_config *config;
+	int irq;
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irq = platform_get_irq(pdev, 0);
+	config = dev_get_drvdata(&pdev->dev);
+
+	free_irq(irq, NULL);
+	dev_set_drvdata(&pdev->dev, NULL);
+	iounmap(config->va_dbi_base);
+	iounmap(config->va_app_base);
+	kfree(config);
+	release_mem_region(res1->start, resource_size(res1));
+	release_mem_region(res0->start, resource_size(res0));
+	sysfs_remove_group(&pdev->dev.kobj, &pcie_gadget_attr_group);
+
+	return 0;
+}
+
+static void spear_pcie_gadget_shutdown(struct platform_device *pdev)
+{
+}
+
+static struct platform_driver spear_pcie_gadget_driver = {
+	.probe = spear_pcie_gadget_probe,
+	.remove = spear_pcie_gadget_remove,
+	.shutdown = spear_pcie_gadget_shutdown,
+	.driver = {
+		.name = "pcie-gadget-spear",
+		.bus = &platform_bus_type
+	},
+};
+
+static int __init spear_pcie_gadget_init(void)
+{
+	return platform_driver_register(&spear_pcie_gadget_driver);
+}
+module_init(spear_pcie_gadget_init);
+
+static void __exit spear_pcie_gadget_exit(void)
+{
+	platform_driver_unregister(&spear_pcie_gadget_driver);
+}
+module_exit(spear_pcie_gadget_exit);
+
+MODULE_ALIAS("pcie-gadget-spear");
+MODULE_AUTHOR("Pratyush Anand");
+MODULE_LICENSE("GPL");
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:12 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:12 +0530
Subject: [PATCH V2 52/69] SPEAr : Pad multiplexing handling modified
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <010fe2ef7c21169330673f980543ae15d9a8149e.1285933332.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

Until now, the platform code assumed 1 32 bit register to be used for pad
multiplexing. This assumption is not true for SPEAr13xx devices, so the generic
implementation of pad multiplexing adopts a new concepts of multiple
multiplexing registers.

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |    3 +
 arch/arm/mach-spear3xx/spear300.c             |  314 ++++++++++++++----
 arch/arm/mach-spear3xx/spear310.c             |  118 +++++--
 arch/arm/mach-spear3xx/spear320.c             |  387 +++++++++++++++++-----
 arch/arm/mach-spear3xx/spear3xx.c             |  451 ++++++++++++++++++++-----
 arch/arm/plat-spear/include/plat/padmux.h     |   28 ++-
 arch/arm/plat-spear/padmux.c                  |   28 +-
 7 files changed, 1040 insertions(+), 289 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 1462944..1acb93d 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -148,6 +148,7 @@ extern struct pmx_dev pmx_telecom_boot_pins;
 extern struct pmx_dev pmx_telecom_sdhci_4bit;
 extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
+#define PAD_MUX_CONFIG_REG	0x00
 
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
@@ -179,6 +180,7 @@ extern struct pmx_dev pmx_uart3_4_5;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_rs485_0_1;
 extern struct pmx_dev pmx_tdm0;
+#define PAD_MUX_CONFIG_REG	0x08
 
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
@@ -228,6 +230,7 @@ extern struct pmx_dev pmx_mii1;
 extern struct pmx_dev pmx_smii0;
 extern struct pmx_dev pmx_smii1;
 extern struct pmx_dev pmx_i2c1;
+#define PAD_MUX_CONFIG_REG	0x0C
 
 /* Add spear320 machine function declarations here */
 void __init spear320_init(void);
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 03e050b..0a0485d 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -21,8 +21,6 @@
 #include <plat/shirq.h>
 
 /* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG	0x00
 #define MODE_CONFIG_REG		0x04
 
 /* modes */
@@ -44,87 +42,97 @@
 struct pmx_mode nand_mode = {
 	.id = NAND_MODE,
 	.name = "nand mode",
-	.mask = 0x00,
+	.value = 0x00,
 };
 
 struct pmx_mode nor_mode = {
 	.id = NOR_MODE,
 	.name = "nor mode",
-	.mask = 0x01,
+	.value = 0x01,
 };
 
 struct pmx_mode photo_frame_mode = {
 	.id = PHOTO_FRAME_MODE,
 	.name = "photo frame mode",
-	.mask = 0x02,
+	.value = 0x02,
 };
 
 struct pmx_mode lend_ip_phone_mode = {
 	.id = LEND_IP_PHONE_MODE,
 	.name = "lend ip phone mode",
-	.mask = 0x03,
+	.value = 0x03,
 };
 
 struct pmx_mode hend_ip_phone_mode = {
 	.id = HEND_IP_PHONE_MODE,
 	.name = "hend ip phone mode",
-	.mask = 0x04,
+	.value = 0x04,
 };
 
 struct pmx_mode lend_wifi_phone_mode = {
 	.id = LEND_WIFI_PHONE_MODE,
 	.name = "lend wifi phone mode",
-	.mask = 0x05,
+	.value = 0x05,
 };
 
 struct pmx_mode hend_wifi_phone_mode = {
 	.id = HEND_WIFI_PHONE_MODE,
 	.name = "hend wifi phone mode",
-	.mask = 0x06,
+	.value = 0x06,
 };
 
 struct pmx_mode ata_pabx_wi2s_mode = {
 	.id = ATA_PABX_WI2S_MODE,
 	.name = "ata pabx wi2s mode",
-	.mask = 0x07,
+	.value = 0x07,
 };
 
 struct pmx_mode ata_pabx_i2s_mode = {
 	.id = ATA_PABX_I2S_MODE,
 	.name = "ata pabx i2s mode",
-	.mask = 0x08,
+	.value = 0x08,
 };
 
 struct pmx_mode caml_lcdw_mode = {
 	.id = CAML_LCDW_MODE,
 	.name = "caml lcdw mode",
-	.mask = 0x0C,
+	.value = 0x0C,
 };
 
 struct pmx_mode camu_lcd_mode = {
 	.id = CAMU_LCD_MODE,
 	.name = "camu lcd mode",
-	.mask = 0x0D,
+	.value = 0x0D,
 };
 
 struct pmx_mode camu_wlcd_mode = {
 	.id = CAMU_WLCD_MODE,
 	.name = "camu wlcd mode",
-	.mask = 0x0E,
+	.value = 0x0E,
 };
 
 struct pmx_mode caml_lcd_mode = {
 	.id = CAML_LCD_MODE,
 	.name = "caml lcd mode",
-	.mask = 0x0F,
+	.value = 0x0F,
 };
 
 /* devices */
-struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = {
+/* Pad multiplexing for FSMC 2 NAND devices */
+static struct pmx_mux_reg pmx_fsmc_2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_FIRDA_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = {
 	{
 		.ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
 			ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
-		.mask = PMX_FIRDA_MASK,
+		.mux_regs = pmx_fsmc_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc_2_mux),
 	},
 };
 
@@ -132,14 +140,23 @@ struct pmx_dev pmx_fsmc_2_chips = {
 	.name = "fsmc_2_chips",
 	.modes = pmx_fsmc_2_chips_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_2_chips_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = {
+/* Pad multiplexing for FSMC 4 NAND devices */
+static struct pmx_mux_reg pmx_fsmc_4_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = {
 	{
 		.ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
 			ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
-		.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
+		.mux_regs = pmx_fsmc_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc_4_mux),
 	},
 };
 
@@ -147,16 +164,25 @@ struct pmx_dev pmx_fsmc_4_chips = {
 	.name = "fsmc_4_chips",
 	.modes = pmx_fsmc_4_chips_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_4_chips_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_keyboard_modes[] = {
+/* Pad multiplexing for Keyboard device */
+static struct pmx_mux_reg pmx_kbd_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_keyboard_modes[] = {
 	{
 		.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
 			LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
 			CAML_LCDW_MODE | CAMU_LCD_MODE | CAMU_WLCD_MODE |
 			CAML_LCD_MODE,
-		.mask = 0x0,
+		.mux_regs = pmx_kbd_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_kbd_mux),
 	},
 };
 
@@ -164,17 +190,35 @@ struct pmx_dev pmx_keyboard = {
 	.name = "keyboard",
 	.modes = pmx_keyboard_modes,
 	.mode_count = ARRAY_SIZE(pmx_keyboard_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_clcd_modes[] = {
+/* Pad multiplexing for CLCD device */
+static struct pmx_mux_reg pmx_clcd_pfmode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_clcd_lcdmode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE,
-		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK ,
+		.mux_regs = pmx_clcd_pfmode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_pfmode_mux),
 	}, {
 		.ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
 			CAMU_LCD_MODE | CAML_LCD_MODE,
-		.mask = PMX_TIMER_3_4_MASK,
+		.mux_regs = pmx_clcd_lcdmode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_lcdmode_mux),
 	},
 };
 
@@ -182,26 +226,71 @@ struct pmx_dev pmx_clcd = {
 	.name = "clcd",
 	.modes = pmx_clcd_modes,
 	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_gpio_modes[] = {
+/* Pad multiplexing for Telecom GPIO device */
+static struct pmx_mux_reg pmx_gpio_lcdmode_mux[] = {
 	{
-		.ids = PHOTO_FRAME_MODE | CAMU_LCD_MODE | CAML_LCD_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_gpio_fonemode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_gpio_atai2smode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_gpio_lendfonemode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_gpio_atawi2smode_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
+			| PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_gpio_modes[] = {
+	{
+		.ids = PHOTO_FRAME_MODE | CAMU_LCD_MODE | CAML_LCD_MODE,
+		.mux_regs = pmx_gpio_lcdmode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_lcdmode_mux),
 	}, {
 		.ids = LEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE,
-		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.mux_regs = pmx_gpio_fonemode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_fonemode_mux),
 	}, {
 		.ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_WLCD_MODE,
-		.mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
+		.mux_regs = pmx_gpio_atai2smode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_atai2smode_mux),
 	}, {
 		.ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE,
-		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
+		.mux_regs = pmx_gpio_lendfonemode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_lendfonemode_mux),
 	}, {
 		.ids = ATA_PABX_WI2S_MODE,
-		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
-			| PMX_UART0_MODEM_MASK,
+		.mux_regs = pmx_gpio_atawi2smode_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_atawi2smode_mux),
 	},
 };
 
@@ -209,17 +298,26 @@ struct pmx_dev pmx_telecom_gpio = {
 	.name = "telecom_gpio",
 	.modes = pmx_telecom_gpio_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_gpio_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_tdm_modes[] = {
+/* Pad multiplexing for TDM device */
+static struct pmx_mux_reg pmx_tdm_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_tdm_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
 			| HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
 			| ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
 			| CAMU_WLCD_MODE | CAML_LCD_MODE,
-		.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
+		.mux_regs = pmx_tdm_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_tdm_mux),
 	},
 };
 
@@ -227,16 +325,25 @@ struct pmx_dev pmx_telecom_tdm = {
 	.name = "telecom_tdm",
 	.modes = pmx_telecom_tdm_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_tdm_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = {
+/* Pad multiplexing for spi cs i2c device */
+static struct pmx_mux_reg pmx_spi_cs_i2c_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = {
 	{
 		.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
 			LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE
 			| ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE |
 			CAML_LCDW_MODE | CAML_LCD_MODE,
-		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.mux_regs = pmx_spi_cs_i2c_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_spi_cs_i2c_mux),
 	},
 };
 
@@ -244,16 +351,33 @@ struct pmx_dev pmx_telecom_spi_cs_i2c_clk = {
 	.name = "telecom_spi_cs_i2c_clk",
 	.modes = pmx_telecom_spi_cs_i2c_clk_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_spi_cs_i2c_clk_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_camera_modes[] = {
+static struct pmx_mux_reg pmx_caml_mux[] = {
 	{
-		.ids = CAML_LCDW_MODE | CAML_LCD_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_camu_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_camera_modes[] = {
+	{
+		.ids = CAML_LCDW_MODE | CAML_LCD_MODE,
+		.mux_regs = pmx_caml_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_caml_mux),
 	}, {
 		.ids = CAMU_LCD_MODE | CAMU_WLCD_MODE,
-		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
+		.mux_regs = pmx_camu_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_camu_mux),
 	},
 };
 
@@ -261,14 +385,23 @@ struct pmx_dev pmx_telecom_camera = {
 	.name = "telecom_camera",
 	.modes = pmx_telecom_camera_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_camera_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_dac_modes[] = {
+/* Pad multiplexing for dac device */
+static struct pmx_mux_reg pmx_dac_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_1_2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_dac_modes[] = {
 	{
 		.ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
 			| CAMU_WLCD_MODE | CAML_LCD_MODE,
-		.mask = PMX_TIMER_1_2_MASK,
+		.mux_regs = pmx_dac_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_dac_mux),
 	},
 };
 
@@ -276,16 +409,25 @@ struct pmx_dev pmx_telecom_dac = {
 	.name = "telecom_dac",
 	.modes = pmx_telecom_dac_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_dac_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_i2s_modes[] = {
+/* Pad multiplexing for spi cs i2c device */
+static struct pmx_mux_reg pmx_i2s_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_i2s_modes[] = {
 	{
 		.ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
 			| LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
 			ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
 			| CAMU_WLCD_MODE | CAML_LCD_MODE,
-		.mask = PMX_UART0_MODEM_MASK,
+		.mux_regs = pmx_i2s_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s_mux),
 	},
 };
 
@@ -293,14 +435,23 @@ struct pmx_dev pmx_telecom_i2s = {
 	.name = "telecom_i2s",
 	.modes = pmx_telecom_i2s_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_i2s_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = {
+/* Pad multiplexing for bootpins device */
+static struct pmx_mux_reg pmx_bootpins_mux[] = {
 	{
-		.ids = NAND_MODE | NOR_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = {
+	{
+		.ids = NAND_MODE | NOR_MODE,
+		.mux_regs = pmx_bootpins_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_bootpins_mux),
 	},
 };
 
@@ -308,19 +459,28 @@ struct pmx_dev pmx_telecom_boot_pins = {
 	.name = "telecom_boot_pins",
 	.modes = pmx_telecom_boot_pins_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_boot_pins_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
+/* Pad multiplexing for sdhci 4bit device */
+static struct pmx_mux_reg pmx_sdhci_4bit_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
+			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
+			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
 			HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
 			CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE |
 			ATA_PABX_I2S_MODE,
-		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
-			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
-			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
+		.mux_regs = pmx_sdhci_4bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_sdhci_4bit_mux),
 	},
 };
 
@@ -328,18 +488,27 @@ struct pmx_dev pmx_telecom_sdhci_4bit = {
 	.name = "telecom_sdhci_4bit",
 	.modes = pmx_telecom_sdhci_4bit_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
+/* Pad multiplexing for spi cs i2c device */
+static struct pmx_mux_reg pmx_sdhci_8bit_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
+			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
+			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
 			HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
 			CAMU_WLCD_MODE | CAML_LCD_MODE,
-		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
-			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
-			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
+		.mux_regs = pmx_sdhci_8bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_sdhci_8bit_mux),
 	},
 };
 
@@ -347,14 +516,23 @@ struct pmx_dev pmx_telecom_sdhci_8bit = {
 	.name = "telecom_sdhci_8bit",
 	.modes = pmx_telecom_sdhci_8bit_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_gpio1_modes[] = {
+/* Pad multiplexing for spi cs i2c device */
+static struct pmx_mux_reg pmx_gpio1_mux[] = {
 	{
-		.ids = PHOTO_FRAME_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio1_modes[] = {
+	{
+		.ids = PHOTO_FRAME_MODE,
+		.mux_regs = pmx_gpio1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio1_mux),
 	},
 };
 
@@ -362,13 +540,11 @@ struct pmx_dev pmx_gpio1 = {
 	.name = "arm gpio1",
 	.modes = pmx_gpio1_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio1_modes),
-	.enb_on_reset = 1,
 };
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
 	.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x0000000f},
-	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
 /* Add spear300 specific devices here */
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 0d12ee3..548ad56 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -21,14 +21,21 @@
 #include <plat/shirq.h>
 
 /* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG	0x08
 
 /* devices */
-struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = {
+/* Pad multiplexing for emi_cs_0_1_4_5 devices */
+static struct pmx_mux_reg pmx_emi_cs_0_1_4_5_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = {
+	{
+		.mux_regs = pmx_emi_cs_0_1_4_5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_mux),
 	},
 };
 
@@ -36,13 +43,21 @@ struct pmx_dev pmx_emi_cs_0_1_4_5 = {
 	.name = "emi_cs_0_1_4_5",
 	.modes = pmx_emi_cs_0_1_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = {
+/* Pad multiplexing for emi_cs_2_3 devices */
+static struct pmx_mux_reg pmx_emi_cs_2_3_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = {
+	{
+		.mux_regs = pmx_emi_cs_2_3_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_emi_cs_2_3_mux),
 	},
 };
 
@@ -50,13 +65,21 @@ struct pmx_dev pmx_emi_cs_2_3 = {
 	.name = "emi_cs_2_3",
 	.modes = pmx_emi_cs_2_3_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_cs_2_3_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart1_modes[] = {
+/* Pad multiplexing for uart1 device */
+static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modes[] = {
+	{
+		.mux_regs = pmx_uart1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_mux),
 	},
 };
 
@@ -64,13 +87,21 @@ struct pmx_dev pmx_uart1 = {
 	.name = "uart1",
 	.modes = pmx_uart1_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart2_modes[] = {
+/* Pad multiplexing for uart2 device */
+static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart2_modes[] = {
+	{
+		.mux_regs = pmx_uart2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart2_mux),
 	},
 };
 
@@ -78,13 +109,21 @@ struct pmx_dev pmx_uart2 = {
 	.name = "uart2",
 	.modes = pmx_uart2_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart3_4_5_modes[] = {
+/* Pad multiplexing for uart3_4_5 devices */
+static struct pmx_mux_reg pmx_uart3_4_5_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart3_4_5_modes[] = {
+	{
+		.mux_regs = pmx_uart3_4_5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart3_4_5_mux),
 	},
 };
 
@@ -92,13 +131,21 @@ struct pmx_dev pmx_uart3_4_5 = {
 	.name = "uart3_4_5",
 	.modes = pmx_uart3_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart3_4_5_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_fsmc_modes[] = {
+/* Pad multiplexing for fsmc device */
+static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc_modes[] = {
+	{
+		.mux_regs = pmx_fsmc_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc_mux),
 	},
 };
 
@@ -106,13 +153,21 @@ struct pmx_dev pmx_fsmc = {
 	.name = "fsmc",
 	.modes = pmx_fsmc_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_rs485_0_1_modes[] = {
+/* Pad multiplexing for rs485_0_1 devices */
+static struct pmx_mux_reg pmx_rs485_0_1_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_rs485_0_1_modes[] = {
+	{
+		.mux_regs = pmx_rs485_0_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_rs485_0_1_mux),
 	},
 };
 
@@ -120,13 +175,21 @@ struct pmx_dev pmx_rs485_0_1 = {
 	.name = "rs485_0_1",
 	.modes = pmx_rs485_0_1_modes,
 	.mode_count = ARRAY_SIZE(pmx_rs485_0_1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_tdm0_modes[] = {
+/* Pad multiplexing for tdm0 device */
+static struct pmx_mux_reg pmx_tdm0_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_tdm0_modes[] = {
+	{
+		.mux_regs = pmx_tdm0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_tdm0_mux),
 	},
 };
 
@@ -134,13 +197,10 @@ struct pmx_dev pmx_tdm0 = {
 	.name = "tdm0",
 	.modes = pmx_tdm0_modes,
 	.mode_count = ARRAY_SIZE(pmx_tdm0_modes),
-	.enb_on_reset = 1,
 };
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver = {
-	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
-};
+struct pmx_driver pmx_driver;
 
 /* Add spear310 specific devices here */
 /* uart1 device registeration */
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index ae09245..c9f5737c 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -24,8 +24,6 @@
 #include <plat/shirq.h>
 
 /* pad multiplexing support */
-/* muxing registers */
-#define PAD_MUX_CONFIG_REG	0x0C
 #define MODE_CONFIG_REG		0x10
 
 /* modes */
@@ -38,32 +36,42 @@
 struct pmx_mode auto_net_smii_mode = {
 	.id = AUTO_NET_SMII_MODE,
 	.name = "Automation Networking SMII Mode",
-	.mask = 0x00,
+	.value = 0x00,
 };
 
 struct pmx_mode auto_net_mii_mode = {
 	.id = AUTO_NET_MII_MODE,
 	.name = "Automation Networking MII Mode",
-	.mask = 0x01,
+	.value = 0x01,
 };
 
 struct pmx_mode auto_exp_mode = {
 	.id = AUTO_EXP_MODE,
 	.name = "Automation Expanded Mode",
-	.mask = 0x02,
+	.value = 0x02,
 };
 
 struct pmx_mode small_printers_mode = {
 	.id = SMALL_PRINTERS_MODE,
 	.name = "Small Printers Mode",
-	.mask = 0x03,
+	.value = 0x03,
 };
 
 /* devices */
-struct pmx_dev_mode pmx_clcd_modes[] = {
+/* Pad multiplexing for CLCD device */
+static struct pmx_mux_reg pmx_clcd_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE,
+		.mux_regs = pmx_clcd_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_mux),
 	},
 };
 
@@ -71,13 +79,22 @@ struct pmx_dev pmx_clcd = {
 	.name = "clcd",
 	.modes = pmx_clcd_modes,
 	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_emi_modes[] = {
+/* Pad multiplexing for EMI (Parallel NOR flash) device */
+static struct pmx_mux_reg pmx_emi_mux[] = {
 	{
-		.ids = AUTO_EXP_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_emi_modes[] = {
+	{
+		.ids = AUTO_EXP_MODE,
+		.mux_regs = pmx_emi_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_emi_mux),
 	},
 };
 
@@ -85,13 +102,22 @@ struct pmx_dev pmx_emi = {
 	.name = "emi",
 	.modes = pmx_emi_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_fsmc_modes[] = {
+/* Pad multiplexing for FSMC (NAND flash) device */
+static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.ids = ALL_MODES,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc_modes[] = {
+	{
+		.ids = ALL_MODES,
+		.mux_regs = pmx_fsmc_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc_mux),
 	},
 };
 
@@ -99,13 +125,22 @@ struct pmx_dev pmx_fsmc = {
 	.name = "fsmc",
 	.modes = pmx_fsmc_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_spp_modes[] = {
+/* Pad multiplexing for SPP device */
+static struct pmx_mux_reg pmx_spp_mux[] = {
 	{
-		.ids = SMALL_PRINTERS_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_spp_modes[] = {
+	{
+		.ids = SMALL_PRINTERS_MODE,
+		.mux_regs = pmx_spp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_spp_mux),
 	},
 };
 
@@ -113,14 +148,23 @@ struct pmx_dev pmx_spp = {
 	.name = "spp",
 	.modes = pmx_spp_modes,
 	.mode_count = ARRAY_SIZE(pmx_spp_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdhci_modes[] = {
+/* Pad multiplexing for SDHCI device */
+static struct pmx_mux_reg pmx_sdhci_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_sdhci_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
 			SMALL_PRINTERS_MODE,
-		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
+		.mux_regs = pmx_sdhci_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_sdhci_mux),
 	},
 };
 
@@ -128,13 +172,22 @@ struct pmx_dev pmx_sdhci = {
 	.name = "sdhci",
 	.modes = pmx_sdhci_modes,
 	.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_i2s_modes[] = {
+/* Pad multiplexing for I2S device */
+static struct pmx_mux_reg pmx_i2s_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2s_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.mux_regs = pmx_i2s_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s_mux),
 	},
 };
 
@@ -142,13 +195,22 @@ struct pmx_dev pmx_i2s = {
 	.name = "i2s",
 	.modes = pmx_i2s_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2s_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart1_modes[] = {
+/* Pad multiplexing for UART1 device */
+static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.ids = ALL_MODES,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modes[] = {
+	{
+		.ids = ALL_MODES,
+		.mux_regs = pmx_uart1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_mux),
 	},
 };
 
@@ -156,18 +218,36 @@ struct pmx_dev pmx_uart1 = {
 	.name = "uart1",
 	.modes = pmx_uart1_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart1_modem_modes[] = {
+/* Pad multiplexing for UART1 Modem device */
+static struct pmx_mux_reg pmx_uart1_modem_autoexp_mux[] = {
 	{
-		.ids = AUTO_EXP_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK |
 			PMX_SSP_CS_MASK,
-	}, {
-		.ids = SMALL_PRINTERS_MODE,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_uart1_modem_smallpri_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
 			PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
+	{
+		.ids = AUTO_EXP_MODE,
+		.mux_regs = pmx_uart1_modem_autoexp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_modem_autoexp_mux),
+	}, {
+		.ids = SMALL_PRINTERS_MODE,
+		.mux_regs = pmx_uart1_modem_smallpri_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_modem_smallpri_mux),
 	},
 };
 
@@ -175,13 +255,22 @@ struct pmx_dev pmx_uart1_modem = {
 	.name = "uart1_modem",
 	.modes = pmx_uart1_modem_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_uart2_modes[] = {
+/* Pad multiplexing for UART2 device */
+static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.ids = ALL_MODES,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart2_modes[] = {
+	{
+		.ids = ALL_MODES,
+		.mux_regs = pmx_uart2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart2_mux),
 	},
 };
 
@@ -189,13 +278,22 @@ struct pmx_dev pmx_uart2 = {
 	.name = "uart2",
 	.modes = pmx_uart2_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_touchscreen_modes[] = {
+/* Pad multiplexing for Touchscreen device */
+static struct pmx_mux_reg pmx_touchscreen_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_touchscreen_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE,
+		.mux_regs = pmx_touchscreen_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_touchscreen_mux),
 	},
 };
 
@@ -203,14 +301,23 @@ struct pmx_dev pmx_touchscreen = {
 	.name = "touchscreen",
 	.modes = pmx_touchscreen_modes,
 	.mode_count = ARRAY_SIZE(pmx_touchscreen_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_can_modes[] = {
+/* Pad multiplexing for CAN device */
+static struct pmx_mux_reg pmx_can_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_can_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE,
+		.mux_regs = pmx_can_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_can_mux),
 	},
 };
 
@@ -218,13 +325,22 @@ struct pmx_dev pmx_can = {
 	.name = "can",
 	.modes = pmx_can_modes,
 	.mode_count = ARRAY_SIZE(pmx_can_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdhci_led_modes[] = {
+/* Pad multiplexing for SDHCI LED device */
+static struct pmx_mux_reg pmx_sdhci_led_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_sdhci_led_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.mux_regs = pmx_sdhci_led_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_sdhci_led_mux),
 	},
 };
 
@@ -232,16 +348,34 @@ struct pmx_dev pmx_sdhci_led = {
 	.name = "sdhci_led",
 	.modes = pmx_sdhci_led_modes,
 	.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_pwm0_modes[] = {
+/* Pad multiplexing for PWM0 device */
+static struct pmx_mux_reg pmx_pwm0_net_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_pwm0_autoexpsmallpri_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pwm0_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.mux_regs = pmx_pwm0_net_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm0_net_mux),
 	}, {
 		.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
-		.mask = PMX_MII_MASK,
+		.mux_regs = pmx_pwm0_autoexpsmallpri_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm0_autoexpsmallpri_mux),
 	},
 };
 
@@ -249,16 +383,34 @@ struct pmx_dev pmx_pwm0 = {
 	.name = "pwm0",
 	.modes = pmx_pwm0_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm0_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_pwm1_modes[] = {
+/* Pad multiplexing for PWM1 device */
+static struct pmx_mux_reg pmx_pwm1_net_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_pwm1_autoexpsmallpri_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pwm1_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.mux_regs = pmx_pwm1_net_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm1_net_mux),
 	}, {
 		.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
-		.mask = PMX_MII_MASK,
+		.mux_regs = pmx_pwm1_autoexpsmallpri_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm1_autoexpsmallpri_mux),
 	},
 };
 
@@ -266,16 +418,34 @@ struct pmx_dev pmx_pwm1 = {
 	.name = "pwm1",
 	.modes = pmx_pwm1_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_pwm2_modes[] = {
+/* Pad multiplexing for PWM2 device */
+static struct pmx_mux_reg pmx_pwm2_net_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_mux_reg pmx_pwm2_autoexpsmallpri_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG,
+		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pwm2_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
+		.mux_regs = pmx_pwm2_net_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm2_net_mux),
 	}, {
 		.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
-		.mask = PMX_MII_MASK,
+		.mux_regs = pmx_pwm2_autoexpsmallpri_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm2_autoexpsmallpri_mux),
 	},
 };
 
@@ -283,13 +453,22 @@ struct pmx_dev pmx_pwm2 = {
 	.name = "pwm2",
 	.modes = pmx_pwm2_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm2_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_pwm3_modes[] = {
+/* Pad multiplexing for PWM3 device */
+static struct pmx_mux_reg pmx_pwm3_mux[] = {
 	{
-		.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pwm3_modes[] = {
+	{
+		.ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
+		.mux_regs = pmx_pwm3_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pwm3_mux),
 	},
 };
 
@@ -297,13 +476,22 @@ struct pmx_dev pmx_pwm3 = {
 	.name = "pwm3",
 	.modes = pmx_pwm3_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm3_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_ssp1_modes[] = {
+/* Pad multiplexing for SSP1 device */
+static struct pmx_mux_reg pmx_ssp1_mux[] = {
 	{
-		.ids = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp1_modes[] = {
+	{
+		.ids = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE,
+		.mux_regs = pmx_ssp1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp1_mux),
 	},
 };
 
@@ -311,13 +499,22 @@ struct pmx_dev pmx_ssp1 = {
 	.name = "ssp1",
 	.modes = pmx_ssp1_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_ssp2_modes[] = {
+/* Pad multiplexing for SSP2 device */
+static struct pmx_mux_reg pmx_ssp2_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp2_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE,
+		.mux_regs = pmx_ssp2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp2_mux),
 	},
 };
 
@@ -325,13 +522,22 @@ struct pmx_dev pmx_ssp2 = {
 	.name = "ssp2",
 	.modes = pmx_ssp2_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp2_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_mii1_modes[] = {
+/* Pad multiplexing for mii1 device */
+static struct pmx_mux_reg pmx_mii1_mux[] = {
 	{
-		.ids = AUTO_NET_MII_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_mii1_modes[] = {
+	{
+		.ids = AUTO_NET_MII_MODE,
+		.mux_regs = pmx_mii1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_mii1_mux),
 	},
 };
 
@@ -339,13 +545,22 @@ struct pmx_dev pmx_mii1 = {
 	.name = "mii1",
 	.modes = pmx_mii1_modes,
 	.mode_count = ARRAY_SIZE(pmx_mii1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_smii0_modes[] = {
+/* Pad multiplexing for smii0 device */
+static struct pmx_mux_reg pmx_smii0_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_smii0_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | AUTO_EXP_MODE | SMALL_PRINTERS_MODE,
+		.mux_regs = pmx_smii0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smii0_mux),
 	},
 };
 
@@ -353,13 +568,22 @@ struct pmx_dev pmx_smii0 = {
 	.name = "smii0",
 	.modes = pmx_smii0_modes,
 	.mode_count = ARRAY_SIZE(pmx_smii0_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_smii1_modes[] = {
+/* Pad multiplexing for smii1 device */
+static struct pmx_mux_reg pmx_smii1_mux[] = {
 	{
-		.ids = AUTO_NET_SMII_MODE | SMALL_PRINTERS_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_smii1_modes[] = {
+	{
+		.ids = AUTO_NET_SMII_MODE | SMALL_PRINTERS_MODE,
+		.mux_regs = pmx_smii1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smii1_mux),
 	},
 };
 
@@ -367,13 +591,22 @@ struct pmx_dev pmx_smii1 = {
 	.name = "smii1",
 	.modes = pmx_smii1_modes,
 	.mode_count = ARRAY_SIZE(pmx_smii1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_i2c1_modes[] = {
+/* Pad multiplexing for i2c1 device */
+static struct pmx_mux_reg pmx_i2c1_mux[] = {
 	{
-		.ids = AUTO_EXP_MODE,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c1_modes[] = {
+	{
+		.ids = AUTO_EXP_MODE,
+		.mux_regs = pmx_i2c1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c1_mux),
 	},
 };
 
@@ -381,13 +614,11 @@ struct pmx_dev pmx_i2c1 = {
 	.name = "i2c1",
 	.modes = pmx_i2c1_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2c1_modes),
-	.enb_on_reset = 1,
 };
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
 	.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x00000007},
-	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
 /* Add spear320 specific devices here */
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 2dfa9d5..30e3ab8 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -293,10 +293,21 @@ void __init spear3xx_map_io(void)
 
 /* pad multiplexing support */
 /* devices */
-struct pmx_dev_mode pmx_firda_modes[] = {
+
+/* Pad multiplexing for firda device */
+static struct pmx_mux_reg pmx_firda_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
+		.value = PMX_FIRDA_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_firda_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_firda_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_firda_mux),
 	},
 };
 
@@ -304,13 +315,22 @@ struct pmx_dev pmx_firda = {
 	.name = "firda",
 	.modes = pmx_firda_modes,
 	.mode_count = ARRAY_SIZE(pmx_firda_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_i2c_modes[] = {
+/* Pad multiplexing for i2c device */
+static struct pmx_mux_reg pmx_i2c_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
+		.value = PMX_I2C_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_i2c_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c_mux),
 	},
 };
 
@@ -318,13 +338,22 @@ struct pmx_dev pmx_i2c = {
 	.name = "i2c",
 	.modes = pmx_i2c_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2c_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_ssp_cs_modes[] = {
+/* Pad multiplexing for firda device */
+static struct pmx_mux_reg pmx_ssp_cs_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = PMX_SSP_CS_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp_cs_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_ssp_cs_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp_cs_mux),
 	},
 };
 
@@ -332,13 +361,22 @@ struct pmx_dev pmx_ssp_cs = {
 	.name = "ssp_chip_selects",
 	.modes = pmx_ssp_cs_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp_cs_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_ssp_modes[] = {
+/* Pad multiplexing for ssp device */
+static struct pmx_mux_reg pmx_ssp_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
+		.value = PMX_SSP_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_ssp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp_mux),
 	},
 };
 
@@ -346,13 +384,22 @@ struct pmx_dev pmx_ssp = {
 	.name = "ssp",
 	.modes = pmx_ssp_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_mii_modes[] = {
+/* Pad multiplexing for mii device */
+static struct pmx_mux_reg pmx_mii_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = PMX_MII_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_mii_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_mii_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_mii_mux),
 	},
 };
 
@@ -360,13 +407,22 @@ struct pmx_dev pmx_mii = {
 	.name = "mii",
 	.modes = pmx_mii_modes,
 	.mode_count = ARRAY_SIZE(pmx_mii_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin0_modes[] = {
+/* Pad multiplexing for gpio pin0 device */
+static struct pmx_mux_reg pmx_gpio_pin0_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
+		.value = PMX_GPIO_PIN0_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin0_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin0_mux),
 	},
 };
 
@@ -374,13 +430,22 @@ struct pmx_dev pmx_gpio_pin0 = {
 	.name = "gpio_pin0",
 	.modes = pmx_gpio_pin0_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin0_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin1_modes[] = {
+/* Pad multiplexing for gpio pin1 device */
+static struct pmx_mux_reg pmx_gpio_pin1_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
+		.value = PMX_GPIO_PIN1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin1_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin1_mux),
 	},
 };
 
@@ -388,13 +453,22 @@ struct pmx_dev pmx_gpio_pin1 = {
 	.name = "gpio_pin1",
 	.modes = pmx_gpio_pin1_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin1_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin2_modes[] = {
+/* Pad multiplexing for gpio pin2 device */
+static struct pmx_mux_reg pmx_gpio_pin2_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
+		.value = PMX_GPIO_PIN2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin2_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin2_mux),
 	},
 };
 
@@ -402,13 +476,22 @@ struct pmx_dev pmx_gpio_pin2 = {
 	.name = "gpio_pin2",
 	.modes = pmx_gpio_pin2_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin2_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin3_modes[] = {
+/* Pad multiplexing for gpio pin3 device */
+static struct pmx_mux_reg pmx_gpio_pin3_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
+		.value = PMX_GPIO_PIN3_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin3_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin3_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin3_mux),
 	},
 };
 
@@ -416,13 +499,22 @@ struct pmx_dev pmx_gpio_pin3 = {
 	.name = "gpio_pin3",
 	.modes = pmx_gpio_pin3_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin3_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin4_modes[] = {
+/* Pad multiplexing for gpio pin4 device */
+static struct pmx_mux_reg pmx_gpio_pin4_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
+		.value = PMX_GPIO_PIN4_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin4_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin4_mux),
 	},
 };
 
@@ -430,13 +522,22 @@ struct pmx_dev pmx_gpio_pin4 = {
 	.name = "gpio_pin4",
 	.modes = pmx_gpio_pin4_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin4_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_gpio_pin5_modes[] = {
+/* Pad multiplexing for gpio pin5 device */
+static struct pmx_mux_reg pmx_gpio_pin5_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
+		.value = PMX_GPIO_PIN5_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpio_pin5_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_gpio_pin5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpio_pin5_mux),
 	},
 };
 
@@ -444,13 +545,22 @@ struct pmx_dev pmx_gpio_pin5 = {
 	.name = "gpio_pin5",
 	.modes = pmx_gpio_pin5_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin5_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_uart0_modem_modes[] = {
+/* Pad multiplexing for uart0 modem device */
+static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = PMX_UART0_MODEM_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_uart0_modem_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_modem_mux),
 	},
 };
 
@@ -458,13 +568,22 @@ struct pmx_dev pmx_uart0_modem = {
 	.name = "uart0_modem",
 	.modes = pmx_uart0_modem_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_uart0_modes[] = {
+/* Pad multiplexing for uart0 device */
+static struct pmx_mux_reg pmx_uart0_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
+		.value = PMX_UART0_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_uart0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_mux),
 	},
 };
 
@@ -472,13 +591,22 @@ struct pmx_dev pmx_uart0 = {
 	.name = "uart0",
 	.modes = pmx_uart0_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart0_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_timer_3_4_modes[] = {
+/* Pad multiplexing for timer 3, 4 device */
+static struct pmx_mux_reg pmx_timer_3_4_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
+		.value = PMX_TIMER_3_4_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_timer_3_4_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_timer_3_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_timer_3_4_mux),
 	},
 };
 
@@ -486,13 +614,22 @@ struct pmx_dev pmx_timer_3_4 = {
 	.name = "timer_3_4",
 	.modes = pmx_timer_3_4_modes,
 	.mode_count = ARRAY_SIZE(pmx_timer_3_4_modes),
-	.enb_on_reset = 0,
 };
 
-struct pmx_dev_mode pmx_timer_1_2_modes[] = {
+/* Pad multiplexing for gpio pin0 device */
+static struct pmx_mux_reg pmx_timer_1_2_mux[] = {
 	{
-		.ids = 0xffffffff,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
+		.value = PMX_TIMER_1_2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_timer_1_2_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_timer_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_timer_1_2_mux),
 	},
 };
 
@@ -500,15 +637,24 @@ struct pmx_dev pmx_timer_1_2 = {
 	.name = "timer_1_2",
 	.modes = pmx_timer_1_2_modes,
 	.mode_count = ARRAY_SIZE(pmx_timer_1_2_modes),
-	.enb_on_reset = 0,
 };
 
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
 /* plgpios devices */
-struct pmx_dev_mode pmx_plgpio_0_1_modes[] = {
+/* Pad multiplexing for plgpio_0_1 devices */
+static struct pmx_mux_reg pmx_plgpio_0_1_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_0_1_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_0_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_0_1_mux),
 	},
 };
 
@@ -516,13 +662,22 @@ struct pmx_dev pmx_plgpio_0_1 = {
 	.name = "plgpio 0 and 1",
 	.modes = pmx_plgpio_0_1_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_0_1_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_2_3_modes[] = {
+/* Pad multiplexing for plgpio_2_3 devices */
+static struct pmx_mux_reg pmx_plgpio_2_3_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_2_3_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_2_3_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_2_3_mux),
 	},
 };
 
@@ -530,13 +685,22 @@ struct pmx_dev pmx_plgpio_2_3 = {
 	.name = "plgpio 2 and 3",
 	.modes = pmx_plgpio_2_3_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_2_3_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_4_5_modes[] = {
+/* Pad multiplexing for plgpio_4_5 devices */
+static struct pmx_mux_reg pmx_plgpio_4_5_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_4_5_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_4_5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_4_5_mux),
 	},
 };
 
@@ -544,13 +708,22 @@ struct pmx_dev pmx_plgpio_4_5 = {
 	.name = "plgpio 4 and 5",
 	.modes = pmx_plgpio_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_4_5_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_6_9_modes[] = {
+/* Pad multiplexing for plgpio_6_9 devices */
+static struct pmx_mux_reg pmx_plgpio_6_9_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_6_9_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_6_9_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_6_9_mux),
 	},
 };
 
@@ -558,13 +731,22 @@ struct pmx_dev pmx_plgpio_6_9 = {
 	.name = "plgpio 6 to 9",
 	.modes = pmx_plgpio_6_9_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_6_9_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_10_27_modes[] = {
+/* Pad multiplexing for plgpio_10_27 devices */
+static struct pmx_mux_reg pmx_plgpio_10_27_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_10_27_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_10_27_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_10_27_mux),
 	},
 };
 
@@ -572,13 +754,22 @@ struct pmx_dev pmx_plgpio_10_27 = {
 	.name = "plgpio 10 to 27",
 	.modes = pmx_plgpio_10_27_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_10_27_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_28_modes[] = {
+/* Pad multiplexing for plgpio_28 devices */
+static struct pmx_mux_reg pmx_plgpio_28_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_28_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_28_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_28_mux),
 	},
 };
 
@@ -586,13 +777,22 @@ struct pmx_dev pmx_plgpio_28 = {
 	.name = "plgpio 28",
 	.modes = pmx_plgpio_28_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_28_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_29_modes[] = {
+/* Pad multiplexing for plgpio_29 devices */
+static struct pmx_mux_reg pmx_plgpio_29_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_29_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_29_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_29_mux),
 	},
 };
 
@@ -600,13 +800,22 @@ struct pmx_dev pmx_plgpio_29 = {
 	.name = "plgpio 29",
 	.modes = pmx_plgpio_29_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_29_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_30_modes[] = {
+/* Pad multiplexing for plgpio_30 device */
+static struct pmx_mux_reg pmx_plgpio_30_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_30_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_30_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_30_mux),
 	},
 };
 
@@ -614,13 +823,22 @@ struct pmx_dev pmx_plgpio_30 = {
 	.name = "plgpio 30",
 	.modes = pmx_plgpio_30_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_30_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_31_modes[] = {
+/* Pad multiplexing for plgpio_31 device */
+static struct pmx_mux_reg pmx_plgpio_31_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_31_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_31_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_31_mux),
 	},
 };
 
@@ -628,13 +846,22 @@ struct pmx_dev pmx_plgpio_31 = {
 	.name = "plgpio 31",
 	.modes = pmx_plgpio_31_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_31_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_32_modes[] = {
+/* Pad multiplexing for plgpio_32 device */
+static struct pmx_mux_reg pmx_plgpio_32_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_32_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_32_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_32_mux),
 	},
 };
 
@@ -642,13 +869,22 @@ struct pmx_dev pmx_plgpio_32 = {
 	.name = "plgpio 32",
 	.modes = pmx_plgpio_32_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_32_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_33_modes[] = {
+/* Pad multiplexing for plgpio_33 device */
+static struct pmx_mux_reg pmx_plgpio_33_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_33_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_33_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_33_mux),
 	},
 };
 
@@ -656,13 +892,22 @@ struct pmx_dev pmx_plgpio_33 = {
 	.name = "plgpio 33",
 	.modes = pmx_plgpio_33_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_33_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_34_36_modes[] = {
+/* Pad multiplexing for plgpio_34_36 device */
+static struct pmx_mux_reg pmx_plgpio_34_36_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_34_36_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_34_36_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_34_36_mux),
 	},
 };
 
@@ -670,13 +915,22 @@ struct pmx_dev pmx_plgpio_34_36 = {
 	.name = "plgpio 34 to 36",
 	.modes = pmx_plgpio_34_36_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_34_36_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_37_42_modes[] = {
+/* Pad multiplexing for plgpio_37_42 device */
+static struct pmx_mux_reg pmx_plgpio_37_42_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_37_42_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_37_42_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_37_42_mux),
 	},
 };
 
@@ -684,13 +938,22 @@ struct pmx_dev pmx_plgpio_37_42 = {
 	.name = "plgpio 37 to 42",
 	.modes = pmx_plgpio_37_42_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_37_42_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = {
+/* Pad multiplexing for plgpio_43_44_47_48 device */
+static struct pmx_mux_reg pmx_plgpio_43_44_47_48_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_43_44_47_48_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_43_44_47_48_mux),
 	},
 };
 
@@ -698,13 +961,22 @@ struct pmx_dev pmx_plgpio_43_44_47_48 = {
 	.name = "plgpio 43, 44, 47 and 48",
 	.modes = pmx_plgpio_43_44_47_48_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_43_44_47_48_modes),
-	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = {
+/* Pad multiplexing for plgpio_45_46_49_50 device */
+static struct pmx_mux_reg pmx_plgpio_45_46_49_50_mux[] = {
 	{
-		.ids = 0x00,
+		.offset = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = {
+	{
+		.ids = 0xffffffff,
+		.mux_regs = pmx_plgpio_45_46_49_50_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_plgpio_45_46_49_50_mux),
 	},
 };
 
@@ -712,7 +984,6 @@ struct pmx_dev pmx_plgpio_45_46_49_50 = {
 	.name = "plgpio 45, 46, 49 and 50",
 	.modes = pmx_plgpio_45_46_49_50_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
-	.enb_on_reset = 1,
 };
 #endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
 
diff --git a/arch/arm/plat-spear/include/plat/padmux.h b/arch/arm/plat-spear/include/plat/padmux.h
index 877f3ad..1b69ca5 100644
--- a/arch/arm/plat-spear/include/plat/padmux.h
+++ b/arch/arm/plat-spear/include/plat/padmux.h
@@ -28,26 +28,42 @@ struct pmx_reg {
 };
 
 /*
+ * struct pmx_mux_reg: configuration structure every group of modes of a device
+ *
+ * offset: multiplexing register offset
+ * mask: mask for supported mode
+ * value: value to be written
+ */
+struct pmx_mux_reg {
+	u32 offset;
+	u32 mask;
+	u32 value;
+};
+
+/*
  * struct pmx_dev_mode: configuration structure every group of modes of a device
  *
  * ids: all modes for this configuration
- * mask: mask for supported mode
+ * mux_regs: array of mux registers, masks and values to enable the device in
+ *		this group of modes
+ * mux_reg_cnt: count of mux_regs elements
  */
 struct pmx_dev_mode {
 	u32 ids;
-	u32 mask;
+	struct pmx_mux_reg *mux_regs;
+	u8 mux_reg_cnt;
 };
 
 /*
  * struct pmx_mode: mode definition structure
  *
  * name: mode name
- * mask: mode mask
+ * value: mode value
  */
 struct pmx_mode {
 	char *name;
 	u32 id;
-	u32 mask;
+	u32 value;
 };
 
 /*
@@ -57,14 +73,12 @@ struct pmx_mode {
  * modes: device configuration array for different modes supported
  * mode_count: size of modes array
  * is_active: is peripheral active/enabled
- * enb_on_reset: if 1, mask bits to be cleared in reg otherwise to be set in reg
  */
 struct pmx_dev {
 	char *name;
 	struct pmx_dev_mode *modes;
 	u8 mode_count;
 	bool is_active;
-	bool enb_on_reset;
 };
 
 /*
@@ -75,7 +89,6 @@ struct pmx_dev {
  * devs_count: ARRAY_SIZE of devs
  * base: base address of soc config registers
  * mode_reg: structure of mode config register
- * mux_reg: structure of device mux config register
  */
 struct pmx_driver {
 	struct pmx_mode *mode;
@@ -83,7 +96,6 @@ struct pmx_driver {
 	u8 devs_count;
 	u32 *base;
 	struct pmx_reg mode_reg;
-	struct pmx_reg mux_reg;
 };
 
 /* pmx functions */
diff --git a/arch/arm/plat-spear/padmux.c b/arch/arm/plat-spear/padmux.c
index 555eec6..f30f94b 100644
--- a/arch/arm/plat-spear/padmux.c
+++ b/arch/arm/plat-spear/padmux.c
@@ -21,13 +21,11 @@
  *
  * base: base address of configuration registers
  * mode_reg: mode configurations
- * mux_reg: muxing configurations
  * active_mode: pointer to current active mode
  */
 struct pmx {
 	u32 base;
 	struct pmx_reg mode_reg;
-	struct pmx_reg mux_reg;
 	struct pmx_mode *active_mode;
 };
 
@@ -51,7 +49,7 @@ static int pmx_mode_set(struct pmx_mode *mode)
 
 	val = readl(pmx->base + pmx->mode_reg.offset);
 	val &= ~pmx->mode_reg.mask;
-	val |= mode->mask & pmx->mode_reg.mask;
+	val |= mode->value & pmx->mode_reg.mask;
 	writel(val, pmx->base + pmx->mode_reg.offset);
 
 	return 0;
@@ -66,19 +64,18 @@ static int pmx_mode_set(struct pmx_mode *mode)
  * If peripheral is not supported by current mode then request is rejected.
  * Conflicts between peripherals are not handled and peripherals will be
  * enabled in the order they are present in pmx_dev array.
- * In case of conflicts last peripheral enabled will be present.
+ * In case of conflicts last peripheral enabled will remain present.
  * Returns -ve on Err otherwise 0
  */
 static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
 {
-	u32 val, i, mask;
+	u32 val, i;
 
 	if (!count)
 		return -EINVAL;
 
-	val = readl(pmx->base + pmx->mux_reg.offset);
 	for (i = 0; i < count; i++) {
-		u8 j = 0;
+		u8 k, j = 0;
 
 		if (!devs[i]->name || !devs[i]->modes) {
 			printk(KERN_ERR "padmux: dev name or modes is null\n");
@@ -103,15 +100,18 @@ static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
 		}
 
 		/* enable peripheral */
-		mask = devs[i]->modes[j].mask & pmx->mux_reg.mask;
-		if (devs[i]->enb_on_reset)
-			val &= ~mask;
-		else
-			val |= mask;
+		for (k = 0; k < devs[i]->modes[j].mux_reg_cnt; k++) {
+			struct pmx_mux_reg *mux_reg =
+				&devs[i]->modes[j].mux_regs[k];
+
+			val = readl(pmx->base + mux_reg->offset);
+			val &= ~mux_reg->mask;
+			val |= mux_reg->value & mux_reg->mask;
+			writel(val, pmx->base + mux_reg->offset);
+		}
 
 		devs[i]->is_active = true;
 	}
-	writel(val, pmx->base + pmx->mux_reg.offset);
 	kfree(pmx);
 
 	/* this will ensure that multiplexing can't be changed now */
@@ -144,8 +144,6 @@ int pmx_register(struct pmx_driver *driver)
 	pmx->base = (u32)driver->base;
 	pmx->mode_reg.offset = driver->mode_reg.offset;
 	pmx->mode_reg.mask = driver->mode_reg.mask;
-	pmx->mux_reg.offset = driver->mux_reg.offset;
-	pmx->mux_reg.mask = driver->mux_reg.mask;
 
 	/* choose mode to enable */
 	if (driver->mode) {
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:59 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:59 +0530
Subject: [PATCH V2 39/69] ST SPEAr : EMI (Extrenal Memory Interface)
	controller driver
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <027f942df7073593a3b14406be48590f0ad460eb.1285933332.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

2 SPEAr platform SoCs(spear310 and spear320) support an External Memory
Interface controller. This controller is used to interface with
Parallel NOR Flash devices.

This patch adds just the platform code needed for EMI (mainly EMI
initialization). The driver being used is driver/mtd/maps/physmap.c

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/Makefile                |    4 +
 arch/arm/mach-spear3xx/emi.c                   |  101 ++++++++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/emi.h      |   64 +++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    2 +
 arch/arm/mach-spear3xx/include/mach/spear310.h |    9 ++
 arch/arm/mach-spear3xx/include/mach/spear320.h |    6 ++
 arch/arm/mach-spear3xx/spear310.c              |    9 ++
 arch/arm/mach-spear3xx/spear310_evb.c          |   28 +++++++
 arch/arm/mach-spear3xx/spear320.c              |    9 ++
 arch/arm/mach-spear3xx/spear320_evb.c          |   27 ++++++
 10 files changed, 259 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear3xx/emi.c
 create mode 100644 arch/arm/mach-spear3xx/include/mach/emi.h

diff --git a/arch/arm/mach-spear3xx/Makefile b/arch/arm/mach-spear3xx/Makefile
index b248624..d38ae47 100644
--- a/arch/arm/mach-spear3xx/Makefile
+++ b/arch/arm/mach-spear3xx/Makefile
@@ -24,3 +24,7 @@ obj-$(CONFIG_MACH_SPEAR320) += spear320.o
 
 # spear320 boards files
 obj-$(CONFIG_BOARD_SPEAR320_EVB) += spear320_evb.o
+
+# specific files
+obj-$(CONFIG_MACH_SPEAR310) += emi.o
+obj-$(CONFIG_MACH_SPEAR320) += emi.o
diff --git a/arch/arm/mach-spear3xx/emi.c b/arch/arm/mach-spear3xx/emi.c
new file mode 100644
index 0000000..7b62ff0
--- /dev/null
+++ b/arch/arm/mach-spear3xx/emi.c
@@ -0,0 +1,101 @@
+/*
+ * arch/arm/mach-spear3xx/emi.c
+ *
+ * EMI (External Memory Interface) file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar<vipin.kumar at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <mach/emi.h>
+
+int __init emi_init(struct platform_device *pdev, unsigned long base,
+		u32 bank, u32 width)
+{
+	void __iomem *emi_reg_base;
+	struct clk *clk;
+	int ret;
+
+	if (bank > (EMI_MAX_BANKS - 1))
+		return -EINVAL;
+
+	emi_reg_base = ioremap(base, EMI_REG_SIZE);
+	if (!emi_reg_base)
+		return -ENOMEM;
+
+	clk = clk_get(NULL, "emi");
+	if (IS_ERR(clk)) {
+		iounmap(emi_reg_base);
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_enable(clk);
+	if (ret) {
+		iounmap(emi_reg_base);
+		return ret;
+	}
+
+	/*
+	 * Note: These are relaxed NOR device timings. Nor devices on spear
+	 * eval machines are working fine with these timings. Specific board
+	 * files can optimize these timings based on devices found on board.
+	 */
+	writel(0x10, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TAP_REG);
+	writel(0x05, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TSDP_REG);
+	writel(0x0a, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDPW_REG);
+	writel(0x0a, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDPR_REG);
+	writel(0x05, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDCS_REG);
+
+	switch (width) {
+	case EMI_FLASH_WIDTH8:
+		width = EMI_CNTL_WIDTH8;
+		break;
+
+	case EMI_FLASH_WIDTH16:
+		width = EMI_CNTL_WIDTH16;
+		break;
+
+	case EMI_FLASH_WIDTH32:
+		width = EMI_CNTL_WIDTH32;
+		break;
+	default:
+		width = EMI_CNTL_WIDTH8;
+		break;
+	}
+	/* set the data width */
+	writel(width | EMI_CNTL_ENBBYTERW,
+		emi_reg_base + (EMI_BANK_REG_SIZE * bank) + CTRL_REG);
+
+	/* disable all the acks */
+	writel(0x3f, emi_reg_base + ack_reg);
+
+	iounmap(emi_reg_base);
+
+	return 0;
+}
+
+void __init
+emi_init_board_info(struct platform_device *pdev, struct resource *resources,
+		int res_num, struct mtd_partition *partitions,
+		unsigned int nr_partitions, unsigned int width)
+{
+	struct physmap_flash_data *emi_plat_data = dev_get_platdata(&pdev->dev);
+
+	pdev->resource = resources;
+	pdev->num_resources = res_num;
+
+	if (partitions) {
+		emi_plat_data->parts = partitions;
+		emi_plat_data->nr_parts = nr_partitions;
+	}
+
+	emi_plat_data->width = width;
+}
diff --git a/arch/arm/mach-spear3xx/include/mach/emi.h b/arch/arm/mach-spear3xx/include/mach/emi.h
new file mode 100644
index 0000000..b620bf5
--- /dev/null
+++ b/arch/arm/mach-spear3xx/include/mach/emi.h
@@ -0,0 +1,64 @@
+/*
+ * arch/arm/mach-spear3xx/include/mach/emi.h
+ *
+ * EMI macros for SPEAr platform
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar <vipin.kumar at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_EMI_H
+#define __MACH_EMI_H
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#define EMI_FLASH_WIDTH8	1
+#define EMI_FLASH_WIDTH16	2
+#define EMI_FLASH_WIDTH32	4
+
+#define EMI_REG_SIZE		0x100
+#define EMI_BANK_REG_SIZE	0x18
+
+#define TAP_REG			(0x0)
+#define TSDP_REG		(0x4)
+#define TDPW_REG		(0x8)
+#define TDPR_REG		(0xC)
+#define TDCS_REG		(0x10)
+#define CTRL_REG		(0x14)
+
+#if defined(CONFIG_MACH_SPEAR310)
+#define TIMEOUT_REG		(0x90)
+#define ACK_REG			(0x94)
+#define IRQ_REG			(0x98)
+
+#define EMI_MAX_BANKS		6
+
+#elif defined(CONFIG_MACH_SPEAR320)
+#define TIMEOUT_REG		(0x60)
+#define ACK_REG			(0x64)
+#define IRQ_REG			(0x68)
+
+#define EMI_MAX_BANKS		4
+
+#endif
+
+/* Control register definitions */
+#define EMI_CNTL_WIDTH8		(0 << 0)
+#define EMI_CNTL_WIDTH16	(1 << 0)
+#define EMI_CNTL_WIDTH32	(2 << 0)
+#define EMI_CNTL_ENBBYTEW	(1 << 2)
+#define EMI_CNTL_ENBBYTER	(1 << 3)
+#define EMI_CNTL_ENBBYTERW	(EMI_CNTL_ENBBYTER | EMI_CNTL_ENBBYTEW)
+
+extern int __init emi_init(struct platform_device *pdev, unsigned long base,
+		u32 bank, u32 width);
+extern void __init emi_init_board_info(struct platform_device *pdev,
+		struct resource *resources, int res_num, struct mtd_partition
+		*partitions, unsigned int nr_partitions, unsigned int width);
+#endif
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 7b83197..1462944 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -166,6 +166,7 @@ extern struct amba_device uart2_device;
 extern struct amba_device uart3_device;
 extern struct amba_device uart4_device;
 extern struct amba_device uart5_device;
+extern struct platform_device emi_nor_device;
 extern struct platform_device plgpio_device;
 extern struct platform_device nand_device;
 
@@ -191,6 +192,7 @@ extern struct amba_device uart1_device;
 extern struct amba_device uart2_device;
 extern struct platform_device can0_device;
 extern struct platform_device can1_device;
+extern struct platform_device emi_nor_device;
 extern struct platform_device i2c1_device;
 extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index 1e85347..37556b6 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -18,6 +18,15 @@
 
 #define SPEAR310_NAND_BASE		UL(0x40000000)
 #define SPEAR310_FSMC_BASE		UL(0x44000000)
+#define SPEAR310_EMI_REG_BASE		UL(0x4F000000)
+#define SPEAR310_EMI_MEM_0_BASE		UL(0x50000000)
+#define SPEAR310_EMI_MEM_1_BASE		UL(0x60000000)
+#define SPEAR310_EMI_MEM_2_BASE		UL(0x70000000)
+#define SPEAR310_EMI_MEM_3_BASE		UL(0x80000000)
+#define SPEAR310_EMI_MEM_4_BASE		UL(0x90000000)
+#define SPEAR310_EMI_MEM_5_BASE		UL(0xA0000000)
+#define SPEAR310_EMI_MEM_SIZE		UL(0x10000000)
+
 #define SPEAR310_UART1_BASE		UL(0xB2000000)
 #define SPEAR310_UART2_BASE		UL(0xB2080000)
 #define SPEAR310_UART3_BASE		UL(0xB2100000)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 940f0d8..4f60073 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -17,6 +17,12 @@
 #define __MACH_SPEAR320_H
 
 #define SPEAR320_EMI_CTRL_BASE		UL(0x40000000)
+#define SPEAR320_EMI_MEM_0_BASE		UL(0x44000000)
+#define SPEAR320_EMI_MEM_1_BASE		UL(0x45000000)
+#define SPEAR320_EMI_MEM_2_BASE		UL(0x46000000)
+#define SPEAR320_EMI_MEM_3_BASE		UL(0x47000000)
+#define SPEAR320_EMI_MEM_SIZE		UL(0x01000000)
+
 #define SPEAR320_FSMC_BASE		UL(0x4C000000)
 #define SPEAR320_NAND_BASE		UL(0x50000000)
 #define SPEAR320_I2S_BASE		UL(0x60000000)
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 25a0e94..0d12ee3 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/physmap.h>
 #include <linux/ptrace.h>
 #include <mtd/fsmc.h>
 #include <asm/irq.h>
@@ -268,6 +269,14 @@ int spear300_o2p(int offset)
 		return offset + 2;
 }
 
+/* emi nor flash device registeration */
+static struct physmap_flash_data emi_norflash_data;
+struct platform_device emi_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.dev.platform_data = &emi_norflash_data,
+};
+
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
 	.irq_base = SPEAR_PLGPIO_INT_BASE,
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index bff90b3..49aca18 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -17,6 +17,7 @@
 #include <asm/mach-types.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
+#include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/gpio.h>
 #include <mach/spear.h>
@@ -24,6 +25,24 @@
 #include <plat/smi.h>
 #include <plat/spi.h>
 
+#define PARTITION(n, off, sz)	{.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+	PARTITION("X-loader", 0, 1 * 0x20000),
+	PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+	PARTITION("Kernel", 0x80000, 24 * 0x20000),
+	PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
+/* emi nor flash resources registeration */
+static struct resource emi_nor_resources[] = {
+	{
+		.start	= SPEAR310_EMI_MEM_0_BASE,
+		.end	= SPEAR310_EMI_MEM_0_BASE + SPEAR310_EMI_MEM_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
@@ -61,6 +80,7 @@ static struct amba_device *amba_devs[] __initdata = {
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&ehci_device,
+	&emi_nor_device,
 	&i2c_device,
 	&nand_device,
 	&ohci0_device,
@@ -129,6 +149,11 @@ static void __init spear310_evb_init(void)
 	/* initialize serial nor related data in smi plat data */
 	smi_init_board_info(&smi_device);
 
+	/* initialize emi related data in emi plat data */
+	emi_init_board_info(&emi_nor_device, emi_nor_resources,
+			ARRAY_SIZE(emi_nor_resources), partition_info,
+			ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH32);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
@@ -136,6 +161,9 @@ static void __init spear310_evb_init(void)
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
 
+	/* Initialize emi regiters */
+	emi_init(&emi_nor_device, SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
+
 	spi_init();
 }
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index a6aa487..ae09245 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/amba/pl022.h>
+#include <linux/mtd/physmap.h>
 #include <linux/ptrace.h>
 #include <linux/types.h>
 #include <linux/mmc/sdhci-spear.h>
@@ -473,6 +474,14 @@ struct amba_device uart2_device = {
 	.irq = {VIRQ_UART2, NO_IRQ},
 };
 
+/* emi nor flash device registeration */
+static struct physmap_flash_data emi_norflash_data;
+struct platform_device emi_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.dev.platform_data = &emi_norflash_data,
+};
+
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 1131f9b..04361fc 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -18,6 +18,7 @@
 #include <linux/spi/flash.h>
 #include <linux/mmc/sdhci-spear.h>
 #include <linux/spi/spi.h>
+#include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/gpio.h>
 #include <mach/spear.h>
@@ -25,6 +26,24 @@
 #include <plat/smi.h>
 #include <plat/spi.h>
 
+#define PARTITION(n, off, sz)	{.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+	PARTITION("X-loader", 0, 1 * 0x20000),
+	PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+	PARTITION("Kernel", 0x80000, 24 * 0x20000),
+	PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
+/* emi nor flash resources registeration */
+static struct resource emi_nor_resources[] = {
+	{
+		.start	= SPEAR310_EMI_MEM_0_BASE,
+		.end	= SPEAR310_EMI_MEM_0_BASE + SPEAR310_EMI_MEM_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
@@ -116,6 +135,11 @@ static void __init spear320_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
+	/* initialize emi related data in emi plat data */
+	emi_init_board_info(&emi_nor_device, emi_nor_resources,
+			ARRAY_SIZE(emi_nor_resources), partition_info,
+			ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH16);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
@@ -123,6 +147,9 @@ static void __init spear320_evb_init(void)
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
 
+	/* Initialize emi regiters */
+	emi_init(&emi_nor_device, SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
+
 	spi_init();
 }
 
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:22 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:22 +0530
Subject: [PATCH V2 62/69] ST SPEAr: Appending spear3** with global structures
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <f4787f6021bf3a8c009595749894332c05e656df.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |  140 ++++++++++++------------
 arch/arm/mach-spear3xx/spear300.c             |   42 ++++----
 arch/arm/mach-spear3xx/spear300_evb.c         |   43 ++++----
 arch/arm/mach-spear3xx/spear310.c             |   16 ++--
 arch/arm/mach-spear3xx/spear310_evb.c         |   37 ++++---
 arch/arm/mach-spear3xx/spear320.c             |   32 +++---
 arch/arm/mach-spear3xx/spear320_evb.c         |   50 +++++----
 arch/arm/mach-spear3xx/spear3xx.c             |   20 ++--
 arch/arm/plat-spear/include/plat/spi.h        |    2 +-
 9 files changed, 193 insertions(+), 189 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 3138137..e0de7c7 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -31,16 +31,16 @@
 #define SPEAR_GPT0_CHAN1_IRQ	SPEAR3XX_IRQ_CPU_GPT1_2
 
 /* Add spear3xx family device structure declarations here */
-extern struct amba_device gpio_device;
-extern struct amba_device ssp0_device;
-extern struct amba_device uart_device;
-extern struct amba_device wdt_device;
-extern struct platform_device ehci_device;
-extern struct platform_device i2c_device;
-extern struct platform_device ohci0_device;
-extern struct platform_device ohci1_device;
-extern struct platform_device rtc_device;
-extern struct platform_device smi_device;
+extern struct amba_device spear3xx_gpio_device;
+extern struct amba_device spear3xx_ssp0_device;
+extern struct amba_device spear3xx_uart_device;
+extern struct amba_device spear3xx_wdt_device;
+extern struct platform_device spear3xx_ehci_device;
+extern struct platform_device spear3xx_i2c_device;
+extern struct platform_device spear3xx_ohci0_device;
+extern struct platform_device spear3xx_ohci1_device;
+extern struct platform_device spear3xx_rtc_device;
+extern struct platform_device spear3xx_smi_device;
 extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
@@ -88,49 +88,49 @@ extern struct pmx_dev spear3xx_pmx_timer_1_2;
 
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
 /* padmux plgpio devices */
-extern struct pmx_dev pmx_plgpio_0_1;
-extern struct pmx_dev pmx_plgpio_2_3;
-extern struct pmx_dev pmx_plgpio_4_5;
-extern struct pmx_dev pmx_plgpio_6_9;
-extern struct pmx_dev pmx_plgpio_10_27;
-extern struct pmx_dev pmx_plgpio_28;
-extern struct pmx_dev pmx_plgpio_29;
-extern struct pmx_dev pmx_plgpio_30;
-extern struct pmx_dev pmx_plgpio_31;
-extern struct pmx_dev pmx_plgpio_32;
-extern struct pmx_dev pmx_plgpio_33;
-extern struct pmx_dev pmx_plgpio_34_36;
-extern struct pmx_dev pmx_plgpio_37_42;
-extern struct pmx_dev pmx_plgpio_43_44_47_48;
-extern struct pmx_dev pmx_plgpio_45_46_49_50;
+extern struct pmx_dev spear3xx_pmx_plgpio_0_1;
+extern struct pmx_dev spear3xx_pmx_plgpio_2_3;
+extern struct pmx_dev spear3xx_pmx_plgpio_4_5;
+extern struct pmx_dev spear3xx_pmx_plgpio_6_9;
+extern struct pmx_dev spear3xx_pmx_plgpio_10_27;
+extern struct pmx_dev spear3xx_pmx_plgpio_28;
+extern struct pmx_dev spear3xx_pmx_plgpio_29;
+extern struct pmx_dev spear3xx_pmx_plgpio_30;
+extern struct pmx_dev spear3xx_pmx_plgpio_31;
+extern struct pmx_dev spear3xx_pmx_plgpio_32;
+extern struct pmx_dev spear3xx_pmx_plgpio_33;
+extern struct pmx_dev spear3xx_pmx_plgpio_34_36;
+extern struct pmx_dev spear3xx_pmx_plgpio_37_42;
+extern struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48;
+extern struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50;
 #endif
 
 /* spear300 declarations */
 #ifdef CONFIG_MACH_SPEAR300
 /* Add spear300 machine device structure declarations here */
-extern struct amba_device clcd_device;
-extern struct amba_device gpio1_device;
-extern struct platform_device kbd_device;
-extern struct platform_device nand0_device;
-extern struct platform_device nand1_device;
-extern struct platform_device nand2_device;
-extern struct platform_device nand3_device;
-extern struct platform_device sdhci_device;
+extern struct amba_device spear300_clcd_device;
+extern struct amba_device spear300_gpio1_device;
+extern struct platform_device spear300_kbd_device;
+extern struct platform_device spear300_nand0_device;
+extern struct platform_device spear300_nand1_device;
+extern struct platform_device spear300_nand2_device;
+extern struct platform_device spear300_nand3_device;
+extern struct platform_device spear300_sdhci_device;
 
 /* pad mux modes */
-extern struct pmx_mode nand_mode;
-extern struct pmx_mode nor_mode;
-extern struct pmx_mode photo_frame_mode;
-extern struct pmx_mode lend_ip_phone_mode;
-extern struct pmx_mode hend_ip_phone_mode;
-extern struct pmx_mode lend_wifi_phone_mode;
-extern struct pmx_mode hend_wifi_phone_mode;
-extern struct pmx_mode ata_pabx_wi2s_mode;
-extern struct pmx_mode ata_pabx_i2s_mode;
-extern struct pmx_mode caml_lcdw_mode;
-extern struct pmx_mode camu_lcd_mode;
-extern struct pmx_mode camu_wlcd_mode;
-extern struct pmx_mode caml_lcd_mode;
+extern struct pmx_mode spear300_nand_mode;
+extern struct pmx_mode spear300_nor_mode;
+extern struct pmx_mode spear300_photo_frame_mode;
+extern struct pmx_mode spear300_lend_ip_phone_mode;
+extern struct pmx_mode spear300_hend_ip_phone_mode;
+extern struct pmx_mode spear300_lend_wifi_phone_mode;
+extern struct pmx_mode spear300_hend_wifi_phone_mode;
+extern struct pmx_mode spear300_ata_pabx_wi2s_mode;
+extern struct pmx_mode spear300_ata_pabx_i2s_mode;
+extern struct pmx_mode spear300_caml_lcdw_mode;
+extern struct pmx_mode spear300_camu_lcd_mode;
+extern struct pmx_mode spear300_camu_wlcd_mode;
+extern struct pmx_mode spear300_caml_lcd_mode;
 
 /* pad mux devices */
 extern struct pmx_dev spear300_pmx_fsmc_2_chips;
@@ -166,14 +166,14 @@ extern struct clcd_board clcd_plat_data;
 /* spear310 declarations */
 #if defined(CONFIG_MACH_SPEAR310)
 /* Add spear310 machine device structure declarations here */
-extern struct amba_device uart1_device;
-extern struct amba_device uart2_device;
-extern struct amba_device uart3_device;
-extern struct amba_device uart4_device;
-extern struct amba_device uart5_device;
-extern struct platform_device emi_nor_device;
-extern struct platform_device plgpio_device;
-extern struct platform_device nand_device;
+extern struct amba_device spear310_uart1_device;
+extern struct amba_device spear310_uart2_device;
+extern struct amba_device spear310_uart3_device;
+extern struct amba_device spear310_uart4_device;
+extern struct amba_device spear310_uart5_device;
+extern struct platform_device spear310_emi_nor_device;
+extern struct platform_device spear310_plgpio_device;
+extern struct platform_device spear310_nand_device;
 
 /* pad mux devices */
 extern struct pmx_dev spear310_pmx_emi_cs_0_1_4_5;
@@ -194,24 +194,24 @@ void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 /* spear320 declarations */
 #if defined(CONFIG_MACH_SPEAR320)
 /* Add spear320 machine device structure declarations here */
-extern struct amba_device clcd_device;
-extern struct amba_device ssp_device[];
-extern struct amba_device uart1_device;
-extern struct amba_device uart2_device;
-extern struct platform_device can0_device;
-extern struct platform_device can1_device;
-extern struct platform_device emi_nor_device;
-extern struct platform_device i2c1_device;
-extern struct platform_device nand_device;
-extern struct platform_device plgpio_device;
-extern struct platform_device pwm_device;
-extern struct platform_device sdhci_device;
+extern struct amba_device spear320_clcd_device;
+extern struct amba_device spear320_ssp_device[];
+extern struct amba_device spear320_uart1_device;
+extern struct amba_device spear320_uart2_device;
+extern struct platform_device spear320_can0_device;
+extern struct platform_device spear320_can1_device;
+extern struct platform_device spear320_emi_nor_device;
+extern struct platform_device spear320_i2c1_device;
+extern struct platform_device spear320_nand_device;
+extern struct platform_device spear320_plgpio_device;
+extern struct platform_device spear320_pwm_device;
+extern struct platform_device spear320_sdhci_device;
 
 /* pad mux modes */
-extern struct pmx_mode auto_net_smii_mode;
-extern struct pmx_mode auto_net_mii_mode;
-extern struct pmx_mode auto_exp_mode;
-extern struct pmx_mode small_printers_mode;
+extern struct pmx_mode spear320_auto_net_smii_mode;
+extern struct pmx_mode spear320_auto_net_mii_mode;
+extern struct pmx_mode spear320_auto_exp_mode;
+extern struct pmx_mode spear320_small_printers_mode;
 
 /* pad mux devices */
 extern struct pmx_dev spear320_pmx_clcd;
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 3c040f0..b661e9a 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -36,79 +36,79 @@
 #define CAML_LCD_MODE			(1 << 12)
 #define ALL_MODES			0x1FFF
 
-struct pmx_mode nand_mode = {
+struct pmx_mode spear300_nand_mode = {
 	.id = NAND_MODE,
 	.name = "nand mode",
 	.value = 0x00,
 };
 
-struct pmx_mode nor_mode = {
+struct pmx_mode spear300_nor_mode = {
 	.id = NOR_MODE,
 	.name = "nor mode",
 	.value = 0x01,
 };
 
-struct pmx_mode photo_frame_mode = {
+struct pmx_mode spear300_photo_frame_mode = {
 	.id = PHOTO_FRAME_MODE,
 	.name = "photo frame mode",
 	.value = 0x02,
 };
 
-struct pmx_mode lend_ip_phone_mode = {
+struct pmx_mode spear300_lend_ip_phone_mode = {
 	.id = LEND_IP_PHONE_MODE,
 	.name = "lend ip phone mode",
 	.value = 0x03,
 };
 
-struct pmx_mode hend_ip_phone_mode = {
+struct pmx_mode spear300_hend_ip_phone_mode = {
 	.id = HEND_IP_PHONE_MODE,
 	.name = "hend ip phone mode",
 	.value = 0x04,
 };
 
-struct pmx_mode lend_wifi_phone_mode = {
+struct pmx_mode spear300_lend_wifi_phone_mode = {
 	.id = LEND_WIFI_PHONE_MODE,
 	.name = "lend wifi phone mode",
 	.value = 0x05,
 };
 
-struct pmx_mode hend_wifi_phone_mode = {
+struct pmx_mode spear300_hend_wifi_phone_mode = {
 	.id = HEND_WIFI_PHONE_MODE,
 	.name = "hend wifi phone mode",
 	.value = 0x06,
 };
 
-struct pmx_mode ata_pabx_wi2s_mode = {
+struct pmx_mode spear300_ata_pabx_wi2s_mode = {
 	.id = ATA_PABX_WI2S_MODE,
 	.name = "ata pabx wi2s mode",
 	.value = 0x07,
 };
 
-struct pmx_mode ata_pabx_i2s_mode = {
+struct pmx_mode spear300_ata_pabx_i2s_mode = {
 	.id = ATA_PABX_I2S_MODE,
 	.name = "ata pabx i2s mode",
 	.value = 0x08,
 };
 
-struct pmx_mode caml_lcdw_mode = {
+struct pmx_mode spear300_caml_lcdw_mode = {
 	.id = CAML_LCDW_MODE,
 	.name = "caml lcdw mode",
 	.value = 0x0C,
 };
 
-struct pmx_mode camu_lcd_mode = {
+struct pmx_mode spear300_camu_lcd_mode = {
 	.id = CAMU_LCD_MODE,
 	.name = "camu lcd mode",
 	.value = 0x0D,
 };
 
-struct pmx_mode camu_wlcd_mode = {
+struct pmx_mode spear300_camu_wlcd_mode = {
 	.id = CAMU_WLCD_MODE,
 	.name = "camu wlcd mode",
 	.value = 0x0E,
 };
 
-struct pmx_mode caml_lcd_mode = {
+struct pmx_mode spear300_caml_lcd_mode = {
 	.id = CAML_LCD_MODE,
 	.name = "caml lcd mode",
 	.value = 0x0F,
@@ -526,7 +526,7 @@ static struct pmx_driver pmx_driver = {
 /* Add spear300 specific devices here */
 
 /* CLCD device registration */
-struct amba_device clcd_device = {
+struct amba_device spear300_clcd_device = {
 	.dev = {
 		.init_name = "clcd",
 		.coherent_dma_mask = ~0,
@@ -547,7 +547,7 @@ static struct pl061_platform_data gpio1_plat_data = {
 	.irq_base	= SPEAR300_GPIO1_INT_BASE,
 };
 
-struct amba_device gpio1_device = {
+struct amba_device spear300_gpio1_device = {
 	.dev = {
 		.init_name = "gpio1",
 		.platform_data = &gpio1_plat_data,
@@ -572,7 +572,7 @@ static struct resource kbd_resources[] = {
 	},
 };
 
-struct platform_device kbd_device = {
+struct platform_device spear300_kbd_device = {
 	.name = "keyboard",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(kbd_resources),
@@ -596,7 +596,7 @@ static struct resource nand0_resources[] = {
 	},
 };
 
-struct platform_device nand0_device = {
+struct platform_device spear300_nand0_device = {
 	.name = "nand",
 	.id = 0,
 	.resource = nand0_resources,
@@ -620,7 +620,7 @@ static struct resource nand1_resources[] = {
 	},
 };
 
-struct platform_device nand1_device = {
+struct platform_device spear300_nand1_device = {
 	.name = "nand",
 	.id = 1,
 	.resource = nand1_resources,
@@ -644,7 +644,7 @@ static struct resource nand2_resources[] = {
 	},
 };
 
-struct platform_device nand2_device = {
+struct platform_device spear300_nand2_device = {
 	.name = "nand",
 	.id = 2,
 	.resource = nand2_resources,
@@ -668,7 +668,7 @@ static struct resource nand3_resources[] = {
 	},
 };
 
-struct platform_device nand3_device = {
+struct platform_device spear300_nand3_device = {
 	.name = "nand",
 	.id = 3,
 	.resource = nand3_resources,
@@ -688,7 +688,7 @@ static struct resource sdhci_resources[] = {
 	}
 };
 
-struct platform_device sdhci_device = {
+struct platform_device spear300_sdhci_device = {
 	.dev = {
 		.coherent_dma_mask = ~0,
 	},
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 0adf9f7..7514115 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -44,29 +44,29 @@ static struct pmx_dev *pmx_devs[] = {
 
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&gpio_device,
-	&ssp0_device,
-	&uart_device,
-	&wdt_device,
+	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
+	&spear3xx_uart_device,
+	&spear3xx_wdt_device,
 
 	/* spear300 specific devices */
-	&clcd_device,
-	&gpio1_device,
+	&spear300_clcd_device,
+	&spear300_gpio1_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&ehci_device,
-	&i2c_device,
-	&nand0_device,
-	&ohci0_device,
-	&ohci1_device,
-	&rtc_device,
-	&smi_device,
+	&spear3xx_ehci_device,
+	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
+	&spear3xx_rtc_device,
+	&spear3xx_smi_device,
 
 	/* spear300 specific devices */
-	&kbd_device,
-	&sdhci_device,
+	&spear300_kbd_device,
+	&spear300_nand0_device,
+	&spear300_sdhci_device,
 };
 
 /* sdhci board specific information */
@@ -114,26 +114,27 @@ static void __init spear300_evb_init(void)
 	unsigned int i;
 
 	/* set keyboard plat data */
-	kbd_set_plat_data(&kbd_device, &kbd_data);
+	kbd_set_plat_data(&spear300_kbd_device, &kbd_data);
 
 	/* set nand0 device's plat data */
-	fsmc_nand_set_plat_data(&nand0_device, NULL, 0, NAND_SKIP_BBTSCAN,
-			FSMC_NAND_BW8);
+	fsmc_nand_set_plat_data(&spear300_nand0_device, NULL, 0,
+			NAND_SKIP_BBTSCAN, FSMC_NAND_BW8);
 
 	/* set sdhci device platform data */
-	sdhci_set_plat_data(&sdhci_device, &sdhci_plat_data);
+	sdhci_set_plat_data(&spear300_sdhci_device, &sdhci_plat_data);
 
 	/* Enable sdhci memory */
 	sdhci_i2s_mem_enable(SDHCI_MEM_ENB);
 
 	/* call spear300 machine init function */
-	spear300_init(&photo_frame_mode, pmx_devs, ARRAY_SIZE(pmx_devs));
+	spear300_init(&spear300_photo_frame_mode, pmx_devs,
+			ARRAY_SIZE(pmx_devs));
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
 	/* initialize serial nor related data in smi plat data */
-	smi_init_board_info(&smi_device);
+	smi_init_board_info(&spear3xx_smi_device);
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index f25d2b4..4737182 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -196,7 +196,7 @@ static struct pmx_driver pmx_driver;
 
 /* Add spear310 specific devices here */
 /* uart1 device registeration */
-struct amba_device uart1_device = {
+struct amba_device spear310_uart1_device = {
 	.dev = {
 		.init_name = "uart1",
 	},
@@ -209,7 +209,7 @@ struct amba_device uart1_device = {
 };
 
 /* uart2 device registeration */
-struct amba_device uart2_device = {
+struct amba_device spear310_uart2_device = {
 	.dev = {
 		.init_name = "uart2",
 	},
@@ -222,7 +222,7 @@ struct amba_device uart2_device = {
 };
 
 /* uart3 device registeration */
-struct amba_device uart3_device = {
+struct amba_device spear310_uart3_device = {
 	.dev = {
 		.init_name = "uart3",
 	},
@@ -235,7 +235,7 @@ struct amba_device uart3_device = {
 };
 
 /* uart4 device registeration */
-struct amba_device uart4_device = {
+struct amba_device spear310_uart4_device = {
 	.dev = {
 		.init_name = "uart4",
 	},
@@ -248,7 +248,7 @@ struct amba_device uart4_device = {
 };
 
 /* uart5 device registeration */
-struct amba_device uart5_device = {
+struct amba_device spear310_uart5_device = {
 	.dev = {
 		.init_name = "uart5",
 	},
@@ -277,7 +277,7 @@ static struct resource nand_resources[] = {
 	},
 };
 
-struct platform_device nand_device = {
+struct platform_device spear310_nand_device = {
 	.name = "nand",
 	.id = -1,
 	.resource = nand_resources,
@@ -323,7 +323,7 @@ int spear300_o2p(int offset)
 
 /* emi nor flash device registeration */
 static struct physmap_flash_data emi_norflash_data;
-struct platform_device emi_nor_device = {
+struct platform_device spear310_emi_nor_device = {
 	.name	= "physmap-flash",
 	.id	= -1,
 	.dev.platform_data = &emi_norflash_data,
@@ -351,7 +351,7 @@ static struct resource plgpio_resources[] = {
 	},
 };
 
-struct platform_device plgpio_device = {
+struct platform_device spear310_plgpio_device = {
 	.name = "plgpio",
 	.id = -1,
 	.dev = {
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 953a9ea..2c1044d 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -69,27 +69,27 @@ static struct pmx_dev *pmx_devs[] = {
 
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&gpio_device,
-	&ssp0_device,
-	&uart_device,
-	&wdt_device,
+	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
+	&spear3xx_uart_device,
+	&spear3xx_wdt_device,
 
 	/* spear310 specific devices */
 };
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&ehci_device,
-	&emi_nor_device,
-	&i2c_device,
-	&nand_device,
-	&ohci0_device,
-	&ohci1_device,
-	&rtc_device,
-	&smi_device,
+	&spear3xx_ehci_device,
+	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
+	&spear3xx_rtc_device,
+	&spear3xx_smi_device,
 
 	/* spear310 specific devices */
-	&plgpio_device,
+	&spear310_emi_nor_device,
+	&spear310_nand_device,
+	&spear310_plgpio_device,
 };
 
 /* spi board information */
@@ -132,8 +132,8 @@ static void __init spear310_evb_init(void)
 	unsigned int i;
 
 	/* set nand device's plat data */
-	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
-			FSMC_NAND_BW8);
+	fsmc_nand_set_plat_data(&spear310_nand_device, NULL, 0,
+			NAND_SKIP_BBTSCAN, FSMC_NAND_BW8);
 
 	/* call spear310 machine init function */
 	spear310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
@@ -142,10 +142,10 @@ static void __init spear310_evb_init(void)
 	i2c_register_board_devices();
 
 	/* initialize serial nor related data in smi plat data */
-	smi_init_board_info(&smi_device);
+	smi_init_board_info(&spear3xx_smi_device);
 
 	/* initialize emi related data in emi plat data */
-	emi_init_board_info(&emi_nor_device, emi_nor_resources,
+	emi_init_board_info(&spear310_emi_nor_device, emi_nor_resources,
 			ARRAY_SIZE(emi_nor_resources), partition_info,
 			ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH32);
 
@@ -157,7 +157,8 @@ static void __init spear310_evb_init(void)
 		amba_device_register(amba_devs[i], &iomem_resource);
 
 	/* Initialize emi regiters */
-	emi_init(&emi_nor_device, SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
+	emi_init(&spear310_emi_nor_device, SPEAR310_EMI_REG_BASE, 0,
+			EMI_FLASH_WIDTH32);
 
 	spi_init();
 }
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index bcd76e4..73b8b10 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -30,25 +30,25 @@
 #define SMALL_PRINTERS_MODE	(1 << 3)
 #define ALL_MODES		0xF
 
-struct pmx_mode auto_net_smii_mode = {
+struct pmx_mode spear320_auto_net_smii_mode = {
 	.id = AUTO_NET_SMII_MODE,
 	.name = "Automation Networking SMII Mode",
 	.value = 0x00,
 };
 
-struct pmx_mode auto_net_mii_mode = {
+struct pmx_mode spear320_auto_net_mii_mode = {
 	.id = AUTO_NET_MII_MODE,
 	.name = "Automation Networking MII Mode",
 	.value = 0x01,
 };
 
-struct pmx_mode auto_exp_mode = {
+struct pmx_mode spear320_auto_exp_mode = {
 	.id = AUTO_EXP_MODE,
 	.name = "Automation Expanded Mode",
 	.value = 0x02,
 };
 
-struct pmx_mode small_printers_mode = {
+struct pmx_mode spear320_small_printers_mode = {
 	.id = SMALL_PRINTERS_MODE,
 	.name = "Small Printers Mode",
 	.value = 0x03,
@@ -594,7 +594,7 @@ static struct pmx_driver pmx_driver = {
 
 /* Add spear320 specific devices here */
 /* CLCD device registration */
-struct amba_device clcd_device = {
+struct amba_device spear320_clcd_device = {
 	.dev = {
 		.init_name = "clcd",
 		.coherent_dma_mask = ~0,
@@ -622,7 +622,7 @@ static struct pl022_ssp_controller ssp_platform_data[] = {
 	}
 };
 
-struct amba_device ssp_device[] = {
+struct amba_device spear320_ssp_device[] = {
 	{
 		.dev = {
 			.coherent_dma_mask = ~0,
@@ -651,7 +651,7 @@ struct amba_device ssp_device[] = {
 };
 
 /* uart1 device registeration */
-struct amba_device uart1_device = {
+struct amba_device spear320_uart1_device = {
 	.dev = {
 		.init_name = "uart1",
 	},
@@ -664,7 +664,7 @@ struct amba_device uart1_device = {
 };
 
 /* uart2 device registeration */
-struct amba_device uart2_device = {
+struct amba_device spear320_uart2_device = {
 	.dev = {
 		.init_name = "uart2",
 	},
@@ -678,7 +678,7 @@ struct amba_device uart2_device = {
 
 /* emi nor flash device registeration */
 static struct physmap_flash_data emi_norflash_data;
-struct platform_device emi_nor_device = {
+struct platform_device spear320_emi_nor_device = {
 	.name	= "physmap-flash",
 	.id	= -1,
 	.dev.platform_data = &emi_norflash_data,
@@ -703,7 +703,7 @@ static struct resource can0_resources[] = {
 	},
 };
 
-struct platform_device can0_device = {
+struct platform_device spear320_can0_device = {
 	.name = "spear_can",
 	.id = 0,
 	.num_resources = ARRAY_SIZE(can0_resources),
@@ -721,7 +721,7 @@ static struct resource can1_resources[] = {
 	},
 };
 
-struct platform_device can1_device = {
+struct platform_device spear320_can1_device = {
 	.name = "spear_can",
 	.id = 1,
 	.num_resources = ARRAY_SIZE(can1_resources),
@@ -740,7 +740,7 @@ static struct resource i2c1_resources[] = {
 	},
 };
 
-struct platform_device i2c1_device = {
+struct platform_device spear320_i2c1_device = {
 	.name = "i2c_designware",
 	.id = 1,
 	.dev = {
@@ -767,7 +767,7 @@ static struct resource nand_resources[] = {
 	},
 };
 
-struct platform_device nand_device = {
+struct platform_device spear320_nand_device = {
 	.name = "nand",
 	.id = -1,
 	.resource = nand_resources,
@@ -786,7 +786,7 @@ static struct resource plgpio_resources[] = {
 	},
 };
 
-struct platform_device plgpio_device = {
+struct platform_device spear320_plgpio_device = {
 	.name = "plgpio",
 	.id = -1,
 	.dev = {
@@ -805,7 +805,7 @@ static struct resource pwm_resources[] = {
 	},
 };
 
-struct platform_device pwm_device = {
+struct platform_device spear320_pwm_device = {
 	.name = "pwm",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(pwm_resources),
@@ -824,7 +824,7 @@ static struct resource sdhci_resources[] = {
 	}
 };
 
-struct platform_device sdhci_device = {
+struct platform_device spear320_sdhci_device = {
 	.dev = {
 		.coherent_dma_mask = ~0,
 	},
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index eff4fb3..116dd1b 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -67,31 +67,31 @@ static struct pmx_dev *pmx_devs[] = {
 
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&gpio_device,
-	&uart_device,
-	&wdt_device,
+	&spear3xx_gpio_device,
+	&spear3xx_uart_device,
+	&spear3xx_wdt_device,
 
 	/* spear320 specific devices */
-	&clcd_device,
+	&spear320_clcd_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
-	&ehci_device,
-	&i2c_device,
-	&nand_device,
-	&ohci0_device,
-	&ohci1_device,
-	&rtc_device,
-	&smi_device,
+	&spear3xx_ehci_device,
+	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
+	&spear3xx_rtc_device,
+	&spear3xx_smi_device,
 
 	/* spear320 specific devices */
-	&can0_device,
-	&can1_device,
-	&i2c1_device,
-	&plgpio_device,
-	&pwm_device,
-	&sdhci_device,
+	&spear320_can0_device,
+	&spear320_can1_device,
+	&spear320_i2c1_device,
+	&spear320_nand_device,
+	&spear320_plgpio_device,
+	&spear320_pwm_device,
+	&spear320_sdhci_device,
 };
 
 /* sdhci board specific information */
@@ -115,23 +115,24 @@ static void __init spear320_evb_init(void)
 	unsigned int i;
 
 	/* set sdhci device platform data */
-	sdhci_set_plat_data(&sdhci_device, &sdhci_plat_data);
+	sdhci_set_plat_data(&spear320_sdhci_device, &sdhci_plat_data);
 
 	/* set nand device's plat data */
-	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
-			FSMC_NAND_BW8);
+	fsmc_nand_set_plat_data(&spear320_nand_device, NULL, 0,
+			NAND_SKIP_BBTSCAN, FSMC_NAND_BW8);
 
 	/* call spear320 machine init function */
-	spear320_init(&auto_net_mii_mode, pmx_devs, ARRAY_SIZE(pmx_devs));
+	spear320_init(&spear320_auto_net_mii_mode, pmx_devs,
+			ARRAY_SIZE(pmx_devs));
 
 	/* initialize serial nor related data in smi plat data */
-	smi_init_board_info(&smi_device);
+	smi_init_board_info(&spear3xx_smi_device);
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
 	/* initialize emi related data in emi plat data */
-	emi_init_board_info(&emi_nor_device, emi_nor_resources,
+	emi_init_board_info(&spear320_emi_nor_device, emi_nor_resources,
 			ARRAY_SIZE(emi_nor_resources), partition_info,
 			ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH16);
 
@@ -143,7 +144,8 @@ static void __init spear320_evb_init(void)
 		amba_device_register(amba_devs[i], &iomem_resource);
 
 	/* Initialize emi regiters */
-	emi_init(&emi_nor_device, SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
+	emi_init(&spear320_emi_nor_device, SPEAR320_EMI_CTRL_BASE, 0,
+			EMI_FLASH_WIDTH16);
 
 	spi_init();
 }
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 8c00c2b..15dea9e 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -32,7 +32,7 @@ static struct pl061_platform_data gpio_plat_data = {
 	.irq_base	= SPEAR3XX_GPIO_INT_BASE,
 };
 
-struct amba_device gpio_device = {
+struct amba_device spear3xx_gpio_device = {
 	.dev = {
 		.init_name = "gpio",
 		.platform_data = &gpio_plat_data,
@@ -61,7 +61,7 @@ static struct pl022_ssp_controller ssp_platform_data = {
 	.num_chipselect = 2,
 };
 
-struct amba_device ssp0_device = {
+struct amba_device spear3xx_ssp0_device = {
 	.dev = {
 		.coherent_dma_mask = ~0,
 		.init_name = "ssp-pl022.0",
@@ -76,7 +76,7 @@ struct amba_device ssp0_device = {
 };
 
 /* uart device registeration */
-struct amba_device uart_device = {
+struct amba_device spear3xx_uart_device = {
 	.dev = {
 		.init_name = "uart",
 	},
@@ -89,7 +89,7 @@ struct amba_device uart_device = {
 };
 
 /* watchdog device registeration */
-struct amba_device wdt_device = {
+struct amba_device spear3xx_wdt_device = {
 	.dev = {
 		.init_name = "wdt",
 	},
@@ -112,7 +112,7 @@ static struct resource i2c_resources[] = {
 	},
 };
 
-struct platform_device i2c_device = {
+struct platform_device spear3xx_i2c_device = {
 	.name = "i2c_designware",
 	.id = 0,
 	.dev = {
@@ -162,7 +162,7 @@ static struct resource ohci1_resources[] = {
 static u64 ehci_dmamask = ~0;
 static int usbh_id = -1;
 
-struct platform_device ehci_device = {
+struct platform_device spear3xx_ehci_device = {
 	.name = "spear-ehci",
 	.id = -1,
 	.dev = {
@@ -176,7 +176,7 @@ struct platform_device ehci_device = {
 
 static u64 ohci0_dmamask = ~0;
 
-struct platform_device ohci0_device = {
+struct platform_device spear3xx_ohci0_device = {
 	.name = "spear-ohci",
 	.id = 0,
 	.dev = {
@@ -190,7 +190,7 @@ struct platform_device ohci0_device = {
 
 static u64 ohci1_dmamask = ~0;
 
-struct platform_device ohci1_device = {
+struct platform_device spear3xx_ohci1_device = {
 	.name = "spear-ohci",
 	.id = 1,
 	.dev = {
@@ -214,7 +214,7 @@ static struct resource rtc_resources[] = {
 	},
 };
 
-struct platform_device rtc_device = {
+struct platform_device spear3xx_rtc_device = {
 	.name = "rtc-spear",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(rtc_resources),
@@ -233,7 +233,7 @@ static struct resource smi_resources[] = {
 	},
 };
 
-struct platform_device smi_device = {
+struct platform_device spear3xx_smi_device = {
 	.name = "smi",
 	.id = -1,
 	.num_resources = ARRAY_SIZE(smi_resources),
diff --git a/arch/arm/plat-spear/include/plat/spi.h b/arch/arm/plat-spear/include/plat/spi.h
index a2c53f3..c53410a 100644
--- a/arch/arm/plat-spear/include/plat/spi.h
+++ b/arch/arm/plat-spear/include/plat/spi.h
@@ -55,7 +55,7 @@ static void spi##id##_##type##_cs_control(u32 control)	\
 
 /* This will define CHIP_INFO structure for a specific spi slave */
 #define DECLARE_SPI_CHIP_INFO(id, type, chip_select_control)	\
-struct pl022_config_chip spi##id##_##type##_chip_info = {	\
+static struct pl022_config_chip spi##id##_##type##_chip_info = {\
 	.lbm = LOOPBACK_DISABLED,			\
 	.iface = SSP_INTERFACE_MOTOROLA_SPI,		\
 	.hierarchy = SSP_MASTER,			\
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:16 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:16 +0530
Subject: [PATCH V2 56/69] ST SPEAr Clock Framework: Updating for single image
	solution
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <7a39285e2b281bae63cfebb7d3e76b2f91c9d0be.1285933332.git.viresh.kumar@st.com>

This patch creates different clk_lookup arrays for individual machines.
These lookup arrays will be registered only if that specific machine is
current machine.

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/clock.c          |   29 ++++++++++--
 arch/arm/mach-spear3xx/clock.c           |   75 +++++++++++++++++++-----------
 arch/arm/mach-spear6xx/clock.c           |    8 +++-
 arch/arm/plat-spear/clock.c              |    8 +---
 arch/arm/plat-spear/include/plat/clock.h |    2 +-
 5 files changed, 82 insertions(+), 40 deletions(-)

diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 75cd89c..0755e9f 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -1117,13 +1117,17 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.dev_id = "gpio1",		.clk = &gpio1_clk},
 	{.dev_id = "keyboard",		.clk = &kbd_clk},
 	{.dev_id = "wdt",		.clk = &wdt_clk},
+};
 
-	/* spear1300 machine specific clock structures */
+/* array of all spear 1300 clock lookups */
 #ifdef CONFIG_MACH_SPEAR1300
+static struct clk_lookup spear1300_clk_lookups[] = {
+};
 #endif
 
-	/* spear1310 machine specific clock structures */
+/* array of all spear 1310 clock lookups */
 #ifdef CONFIG_MACH_SPEAR1310
+static struct clk_lookup spear1310_clk_lookups[] = {
 	{.dev_id = "spear_can.0",	.clk = &can0_clk},
 	{.dev_id = "spear_can.1",	.clk = &can1_clk},
 	{.dev_id = "stmmaceth.1",	.clk = &gmac_ras1_clk},
@@ -1134,11 +1138,28 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.dev_id = "stmmacphy.2",	.clk = &gmac_phy2_clk},
 	{.dev_id = "stmmacphy.3",	.clk = &gmac_phy3_clk},
 	{.dev_id = "stmmacphy.4",	.clk = &gmac_phy4_clk},
-#endif
 };
+#endif
 
 /* machine clk init */
 void __init spear13xx_clk_init(void)
 {
-	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
+	int i, cnt;
+	struct clk_lookup *lookups;
+
+	if (machine_is_spear1300()) {
+		cnt = ARRAY_SIZE(spear1300_clk_lookups);
+		lookups = spear1300_clk_lookups;
+	} else {
+		cnt = ARRAY_SIZE(spear1310_clk_lookups);
+		lookups = spear1310_clk_lookups;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
+		clk_register(&spear_clk_lookups[i]);
+
+	for (i = 0; i < cnt; i++)
+		clk_register(&lookups[i]);
+
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 814966a..ec34e50 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -13,6 +13,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <asm/mach-types.h>
 #include <mach/misc_regs.h>
 #include <plat/clock.h>
 
@@ -754,52 +755,72 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "adc",		.clk = &adc_clk},
 	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
 	{ .dev_id = "gpio",		.clk = &gpio_clk},
-#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-	{ .dev_id = "emi",		.clk = &emi_clk},
-#endif
-#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
-	defined(CONFIG_MACH_SPEAR320)
-	{ .con_id = "fsmc",		.clk = &fsmc_clk},
-#endif
-
-/* common clocks to spear310 and spear320 */
-#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-	{ .dev_id = "uart1",		.clk = &uart1_clk},
-	{ .dev_id = "uart2",		.clk = &uart2_clk},
-#endif
-
-	/* common clock to spear300 and spear320 */
-#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
-	{ .dev_id = "clcd",		.clk = &clcd_clk},
-	{ .dev_id = "sdhci",		.clk = &sdhci_clk},
-#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+};
 
-	/* spear300 machine specific clock structures */
+/* array of all spear 300 clock lookups */
 #ifdef CONFIG_MACH_SPEAR300
+static struct clk_lookup spear300_clk_lookups[] = {
+	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
 	{ .dev_id = "gpio1",		.clk = &gpio1_clk},
 	{ .dev_id = "keyboard",		.clk = &kbd_clk},
+	{ .dev_id = "sdhci",		.clk = &sdhci_clk},
+};
 #endif
 
-	/* spear310 machine specific clock structures */
+/* array of all spear 310 clock lookups */
 #ifdef CONFIG_MACH_SPEAR310
+static struct clk_lookup spear310_clk_lookups[] = {
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
+	{ .dev_id = "emi",		.clk = &emi_clk},
+	{ .dev_id = "uart1",		.clk = &uart1_clk},
+	{ .dev_id = "uart2",		.clk = &uart2_clk},
 	{ .dev_id = "uart3",		.clk = &uart3_clk},
 	{ .dev_id = "uart4",		.clk = &uart4_clk},
 	{ .dev_id = "uart5",		.clk = &uart5_clk},
-
+};
 #endif
-	/* spear320 machine specific clock structures */
+
+/* array of all spear 320 clock lookups */
 #ifdef CONFIG_MACH_SPEAR320
+static struct clk_lookup spear320_clk_lookups[] = {
+	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
+	{ .dev_id = "i2c_designware.1",	.clk = &i2c1_clk},
+	{ .dev_id = "emi",		.clk = &emi_clk},
+	{ .dev_id = "pwm",		.clk = &pwm_clk},
+	{ .dev_id = "sdhci",		.clk = &sdhci_clk},
 	{ .dev_id = "spear_can.0",	.clk = &can0_clk},
 	{ .dev_id = "spear_can.1",	.clk = &can1_clk},
-	{ .dev_id = "i2c_designware.1",	.clk = &i2c1_clk},
 	{ .dev_id = "ssp-pl022.1",	.clk = &ssp1_clk},
 	{ .dev_id = "ssp-pl022.2",	.clk = &ssp2_clk},
-	{ .dev_id = "pwm",		.clk = &pwm_clk},
-#endif
+	{ .dev_id = "uart1",		.clk = &uart1_clk},
+	{ .dev_id = "uart2",		.clk = &uart2_clk},
 };
+#endif
 
 /* machine clk init */
 void __init spear3xx_clk_init(void)
 {
-	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
+	int i, cnt;
+	struct clk_lookup *lookups;
+
+	if (machine_is_spear300()) {
+		cnt = ARRAY_SIZE(spear300_clk_lookups);
+		lookups = spear300_clk_lookups;
+	} else if (machine_is_spear310()) {
+		cnt = ARRAY_SIZE(spear310_clk_lookups);
+		lookups = spear310_clk_lookups;
+	} else {
+		cnt = ARRAY_SIZE(spear320_clk_lookups);
+		lookups = spear320_clk_lookups;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
+		clk_register(&spear_clk_lookups[i]);
+
+	for (i = 0; i < cnt; i++)
+		clk_register(&lookups[i]);
+
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 63aab69..fefbb1e 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <mach/misc_regs.h>
+#include <asm/mach-types.h>
 #include <plat/clock.h>
 
 /* root clks */
@@ -740,5 +741,10 @@ static struct clk_lookup spear_clk_lookups[] = {
 /* machine clk init */
 void __init spear6xx_clk_init(void)
 {
-	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
+		clk_register(&spear_clk_lookups[i]);
+
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index ee8f82b..2043c34 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -949,14 +949,8 @@ void recalc_root_clocks(void)
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 
-void __init
-clk_init(struct clk_lookup *clk_lookups, u32 count, struct clk *dclk)
+void __init clk_init(struct clk *dclk)
 {
-	int i;
-
-	for (i = 0; i < count; i++)
-		clk_register(&clk_lookups[i]);
-
 	recalc_root_clocks();
 
 	/* Mark all ancestors of DDR with special flag */
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 00d6854..13ad461 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -241,7 +241,7 @@ struct ddr_rate_tbl {
  * Actually before changing rate of DDRs ancestor, we must put ddr in refresh
  * state and then change parent.
  */
-void clk_init(struct clk_lookup *clk_lookups, u32 count, struct clk *dclk);
+void clk_init(struct clk *dclk);
 void clk_register(struct clk_lookup *cl);
 void recalc_root_clocks(void);
 
-- 
1.7.2.2



From viresh.linux at gmail.com  Fri Oct  1 12:21:06 2010
From: viresh.linux at gmail.com (viresh kumar)
Date: Fri, 1 Oct 2010 21:51:06 +0530
Subject: [PATCH V2 62/69] ST SPEAr: Appending spear3** with global
	structures
In-Reply-To: <f4787f6021bf3a8c009595749894332c05e656df.1285933332.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<f4787f6021bf3a8c009595749894332c05e656df.1285933332.git.viresh.kumar@st.com>
Message-ID: <AANLkTi=xNoG2T1Q2JqB7TH+O7AjW++UnSt1Q85VgPbzp@mail.gmail.com>

On Fri, Oct 1, 2010 at 5:26 PM, Viresh KUMAR <viresh.kumar at st.com> wrote:
> Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
> ---
> ?arch/arm/mach-spear3xx/include/mach/generic.h | ?140 ++++++++++++------------
> ?arch/arm/mach-spear3xx/spear300.c ? ? ? ? ? ? | ? 42 ++++----
> ?arch/arm/mach-spear3xx/spear300_evb.c ? ? ? ? | ? 43 ++++----
> ?arch/arm/mach-spear3xx/spear310.c ? ? ? ? ? ? | ? 16 ++--
> ?arch/arm/mach-spear3xx/spear310_evb.c ? ? ? ? | ? 37 ++++---
> ?arch/arm/mach-spear3xx/spear320.c ? ? ? ? ? ? | ? 32 +++---
> ?arch/arm/mach-spear3xx/spear320_evb.c ? ? ? ? | ? 50 +++++----
> ?arch/arm/mach-spear3xx/spear3xx.c ? ? ? ? ? ? | ? 20 ++--
> ?arch/arm/plat-spear/include/plat/spi.h ? ? ? ?| ? ?2 +-
> ?9 files changed, 193 insertions(+), 189 deletions(-)

Hello everybody,

I have used an latest patch on git for sending this patch series. I
think there is some bug
there, due to which all of you have received some mails which are not
intended for all of you.
There was a bugfix in git which enables to send mail to "recipients
mentioned in TO field", of patch
itself.

After creating patches (with git format-patch ---), i have added To
and CC lists in patches.
But when i sent patches the TO field was carried away in later patches
too. So due to this
all patches send after rtc patches have following recipients added:
rtc-linux at googlegroups.com,
a.zummo at towertech.it. Similarly for other patches too.

Once again sorry for this.

--
viresh


From viresh.kumar at st.com  Fri Oct  1 07:56:13 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:13 +0530
Subject: [PATCH V2 53/69] SPEAr13xx : Fixed part devices in SPEAr13xx addded
	to the generic implementation
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <ea6cc9406acfaee026388797df7ab272ec828189.1285933332.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |  164 ++++++++
 arch/arm/mach-spear13xx/include/mach/spear.h   |    3 +
 arch/arm/mach-spear13xx/spear1300.c            |   15 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   25 ++
 arch/arm/mach-spear13xx/spear1310.c            |   15 +
 arch/arm/mach-spear13xx/spear1310_evb.c        |   25 ++
 arch/arm/mach-spear13xx/spear13xx.c            |  528 ++++++++++++++++++++++++
 arch/arm/plat-spear/Makefile                   |    1 +
 8 files changed, 776 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 56ed7a7..8a0dc8c 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -19,6 +19,168 @@
 #include <linux/amba/bus.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <plat/padmux.h>
+
+/*
+ * Function enable (Pad multiplexing register) offsets
+ */
+#define PAD_MUX_CONFIG_REG_0	0x0
+#define PAD_MUX_CONFIG_REG_1	0x4
+#define PAD_MUX_CONFIG_REG_2	0x8
+#define PAD_MUX_CONFIG_REG_3	0xC
+
+/* pad mux declarations */
+#define PMX_I2S1_MASK		(1 << 3)
+#define PMX_I2S2_MASK		(1 << 16)	/* Offset 4 */
+#define PMX_CLCD1_MASK		(1 << 5)
+#define PMX_CLCD2_MASK		(1 << 3)	/* Offset 4 */
+#define PMX_EGPIO00_MASK	(1 << 6)
+#define PMX_EGPIO01_MASK	(1 << 7)
+#define PMX_EGPIO02_MASK	(1 << 8)
+#define PMX_EGPIO03_MASK	(1 << 9)
+#define PMX_EGPIO04_MASK	(1 << 10)
+#define PMX_EGPIO05_MASK	(1 << 11)
+#define PMX_EGPIO06_MASK	(1 << 12)
+#define PMX_EGPIO07_MASK	(1 << 13)
+#define PMX_EGPIO08_MASK	(1 << 14)
+#define PMX_EGPIO09_MASK	(1 << 15)
+#define PMX_EGPIO10_MASK	(1 << 5)	/* Offset 4 */
+#define PMX_EGPIO11_MASK	(1 << 6)	/* Offset 4 */
+#define PMX_EGPIO12_MASK	(1 << 7)	/* Offset 4 */
+#define PMX_EGPIO13_MASK	(1 << 8)	/* Offset 4 */
+#define PMX_EGPIO14_MASK	(1 << 9)	/* Offset 4 */
+#define PMX_EGPIO15_MASK	(1 << 10)	/* Offset 4 */
+#define PMX_EGPIO_0_GRP_MASK	(PMX_EGPIO00_MASK | PMX_EGPIO01_MASK | \
+		PMX_EGPIO02_MASK | PMX_EGPIO03_MASK | PMX_EGPIO04_MASK | \
+		PMX_EGPIO05_MASK | PMX_EGPIO06_MASK | PMX_EGPIO07_MASK | \
+		PMX_EGPIO08_MASK | PMX_EGPIO09_MASK)
+#define PMX_EGPIO_1_GRP_MASK	(PMX_EGPIO10_MASK | PMX_EGPIO11_MASK | \
+		PMX_EGPIO12_MASK | PMX_EGPIO13_MASK | PMX_EGPIO14_MASK | \
+		PMX_EGPIO15_MASK)
+
+#define PMX_SMI_MASK		(1 << 16)
+#define PMX_SMINCS2_MASK	(1 << 1)	/* Offset 4 */
+#define PMX_SMINCS3_MASK	(1 << 2)	/* Offset 4 */
+
+#define PMX_GMIICLK_MASK			(1 << 18)
+#define PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK	(1 << 19)
+#define PMX_RXCLK_RDV_TXEN_D03_MASK		(1 << 20)
+#define PMX_GMIID47_MASK			(1 << 21)
+#define PMX_MDC_MDIO_MASK			(1 << 22)
+
+#define PMX_GMII_MASK		(PMX_GMIICLK_MASK | \
+		PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK | \
+		PMX_RXCLK_RDV_TXEN_D03_MASK | PMX_GMIID47_MASK | \
+		PMX_MDC_MDIO_MASK)
+
+#define PMX_NAND8_MASK		(1 << 17)
+#define PMX_NFAD023_MASK	(1 << 24)
+#define PMX_NFAD24_MASK		(1 << 25)
+#define PMX_NFAD25_MASK		(1 << 26)
+#define PMX_NFWPRT1_MASK	(1 << 24)	/* Offset 4 */
+#define PMX_NFWPRT2_MASK	(1 << 26)	/* Offset 4 */
+#define PMX_NFWPRT3_MASK	(1 << 28)
+#define PMX_NFRSTPWDWN0_MASK	(1 << 29)
+#define PMX_NFRSTPWDWN1_MASK	(1 << 30)
+#define PMX_NFRSTPWDWN2_MASK	(1 << 31)
+#define PMX_NFRSTPWDWN3_MASK	(1 << 0)	/* Offset 4 */
+#define PMX_NFCE1_MASK		(1 << 20)	/* Offset 4 */
+#define PMX_NFCE2_MASK		(1 << 22)	/* Offset 4 */
+#define PMX_NFCE3_MASK		(1 << 27)
+#define PMX_NFIO815_MASK	(1 << 18)	/* Offset 4 */
+
+#define PMX_NAND8BIT_0_MASK	(PMX_NAND8_MASK | PMX_NFAD023_MASK | \
+		PMX_NFAD24_MASK | PMX_NFAD25_MASK | PMX_NFWPRT3_MASK | \
+		PMX_NFRSTPWDWN0_MASK | PMX_NFRSTPWDWN1_MASK | \
+		PMX_NFRSTPWDWN2_MASK | PMX_NFCE3_MASK)
+#define PMX_NAND8BIT_1_MASK	(PMX_NFRSTPWDWN3_MASK)
+
+#define PMX_NAND8BIT4DEV_0_MASK	(PMX_NAND8BIT_0_MASK)
+#define PMX_NAND8BIT4DEV_1_MASK	(PMX_NAND8BIT_1_MASK | PMX_NFCE1_MASK | \
+		PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK)
+
+#define PMX_NAND16BIT_0_MASK	(PMX_NAND8BIT_0_MASK)
+#define PMX_NAND16BIT_1_MASK	(PMX_NAND8BIT_1_MASK | PMX_NFIO815_MASK)
+#define PMX_NAND16BIT4DEV_0_MASK	(PMX_NAND8BIT4DEV_0_MASK)
+#define PMX_NAND16BIT4DEV_1_MASK	(PMX_NAND8BIT4DEV_1_MASK | \
+					PMX_NFIO815_MASK)
+
+#define PMX_KBD_ROW0_MASK	(1 << 25)	/* Offset 4 */
+#define PMX_KBD_ROW1_MASK	(1 << 23)	/* Offset 4 */
+#define PMX_KBD_ROWCOL25_MASK	(1 << 17)	/* Offset 4 */
+#define PMX_KBD_ROWCOL68_MASK	(1 << 4)	/* Offset 4 */
+#define PMX_KBD_COL0_MASK	(1 << 21)	/* Offset 4 */
+#define PMX_KBD_COL1_MASK	(1 << 19)	/* Offset 4 */
+#define PMX_KEYBOARD_MASK	(PMX_KBD_ROW0_MASK | PMX_KBD_ROW1_MASK | \
+		PMX_KBD_ROWCOL25_MASK | PMX_KBD_ROWCOL68_MASK | \
+		PMX_KBD_COL0_MASK | PMX_KBD_COL1_MASK)
+
+#define PMX_UART0_MASK		(1 << 1)
+#define PMX_I2C_MASK		(1 << 2)
+#define PMX_SSP_MASK		(1 << 4)
+#define PMX_UART0_MODEM_MASK	(1 << 11)	/* Offset 4 */
+#define PMX_GPT0_TMR1_MASK	(1 << 12)	/* Offset 4 */
+#define PMX_GPT0_TMR2_MASK	(1 << 13)	/* Offset 4 */
+#define PMX_GPT1_TMR1_MASK	(1 << 14)	/* Offset 4 */
+#define PMX_GPT1_TMR2_MASK	(1 << 15)	/* Offset 4 */
+
+#define PMX_MCIDATA0_MASK	(1 << 27)	/* Offset 4 */
+#define PMX_MCIDATA1_MASK	(1 << 28)	/* Offset 4 */
+#define PMX_MCIDATA2_MASK	(1 << 29)	/* Offset 4 */
+#define PMX_MCIDATA3_MASK	(1 << 30)	/* Offset 4 */
+#define PMX_MCIDATA4_MASK	(1 << 31)	/* Offset 4 */
+#define PMX_MCIDATA5_MASK	(1 << 0)	/* Offset 8 */
+#define PMX_MCIDATA6_MASK	(1 << 1)	/* Offset 8 */
+#define PMX_MCIDATA7_MASK	(1 << 2)	/* Offset 8 */
+#define PMX_MCIDATA1SD_MASK	(1 << 3)	/* Offset 8 */
+#define PMX_MCIDATA2SD_MASK	(1 << 4)	/* Offset 8 */
+#define PMX_MCIDATA3SD_MASK	(1 << 5)	/* Offset 8 */
+#define PMX_MCIADDR0ALE_MASK	(1 << 6)	/* Offset 8 */
+#define PMX_MCIADDR1CLECLK_MASK	(1 << 7)	/* Offset 8 */
+#define PMX_MCIADDR2_MASK	(1 << 8)	/* Offset 8 */
+#define PMX_MCICECF_MASK	(1 << 9)	/* Offset 8 */
+#define PMX_MCICEXD_MASK	(1 << 10)	/* Offset 8 */
+#define PMX_MCICESDMMC_MASK	(1 << 11)	/* Offset 8 */
+#define PMX_MCICDCF1_MASK	(1 << 12)	/* Offset 8 */
+#define PMX_MCICDCF2_MASK	(1 << 13)	/* Offset 8 */
+#define PMX_MCICDXD_MASK	(1 << 14)	/* Offset 8 */
+#define PMX_MCICDSDMMC_MASK	(1 << 15)	/* Offset 8 */
+#define PMX_MCIDATADIR_MASK	(1 << 16)	/* Offset 8 */
+#define PMX_MCIDMARQWP_MASK	(1 << 17)	/* Offset 8 */
+#define PMX_MCIIORDRE_MASK	(1 << 18)	/* Offset 8 */
+#define PMX_MCIIOWRWE_MASK	(1 << 19)	/* Offset 8 */
+#define PMX_MCIRESETCF_MASK	(1 << 20)	/* Offset 8 */
+#define PMX_MCICS0CE_MASK	(1 << 21)	/* Offset 8 */
+#define PMX_MCICFINTR_MASK	(1 << 22)	/* Offset 8 */
+#define PMX_MCIIORDY_MASK	(1 << 23)	/* Offset 8 */
+#define PMX_MCICS1_MASK		(1 << 24)	/* Offset 8 */
+#define PMX_MCIDMAACK_MASK	(1 << 25)	/* Offset 8 */
+#define PMX_MCISDCMD_MASK	(1 << 26)	/* Offset 8 */
+#define PMX_MCILEDS_MASK	(1 << 27)	/* Offset 8 */
+
+#define PMX_MCIFALL_1_MASK	(0xF8000000)
+#define PMX_MCIFALL_2_MASK	(0x0FFFFFFF)
+
+/* pad mux devices */
+extern struct pmx_dev pmx_i2c;
+extern struct pmx_dev pmx_ssp;
+extern struct pmx_dev pmx_i2s2;
+extern struct pmx_dev pmx_clcd1;
+extern struct pmx_dev pmx_clcd2;
+extern struct pmx_dev pmx_egpio_grp;
+extern struct pmx_dev pmx_smi_2_chips;
+extern struct pmx_dev pmx_smi_4_chips;
+extern struct pmx_dev pmx_gmii;
+extern struct pmx_dev pmx_nand_8bit;
+extern struct pmx_dev pmx_nand_16bit;
+extern struct pmx_dev pmx_keyboard;
+extern struct pmx_dev pmx_uart0;
+extern struct pmx_dev pmx_uart0_modem;
+extern struct pmx_dev pmx_gpt_0_1;
+extern struct pmx_dev pmx_gpt_0_2;
+extern struct pmx_dev pmx_gpt_1_1;
+extern struct pmx_dev pmx_gpt_1_2;
+extern struct pmx_dev pmx_mcif;
 
 /*
  * Each GPT has 2 timer channels
@@ -28,6 +190,8 @@
 #define SPEAR_GPT0_CHAN0_IRQ	IRQ_GPT0_TMR0
 #define SPEAR_GPT0_CHAN1_IRQ	IRQ_GPT0_TMR1
 
+extern struct pmx_driver pmx_driver;
+
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
 extern struct amba_device spear13xx_ssp_device;
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index d043280..03f9616 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -88,6 +88,9 @@
 #define SPEAR13XX_MCIF_CF_BASE		UL(0xB2800000)
 #define SPEAR13XX_MCIF_SDHCI_BASE	UL(0xB3000000)
 
+/* Pad multiplexing base */
+#define SPEAR13XX_FUNC_ENB_BASE		UL(0xE0700650)
+
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR13XX_UART_BASE
 #define VA_SPEAR_DBG_UART_BASE		VA_SPEAR13XX_UART_BASE
diff --git a/arch/arm/mach-spear13xx/spear1300.c b/arch/arm/mach-spear13xx/spear1300.c
index c1b82f1..4569cb5 100644
--- a/arch/arm/mach-spear13xx/spear1300.c
+++ b/arch/arm/mach-spear13xx/spear1300.c
@@ -14,10 +14,25 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 
+/* pmx driver structure */
+struct pmx_driver pmx_driver;
+
 /* Add spear1300 specific devices here */
 
 void __init spear1300_init(void)
 {
+	int ret;
+
 	/* call spear13xx family common init function */
 	spear13xx_init();
+
+	/* pmx initialization */
+	pmx_driver.base = ioremap(SPEAR13XX_FUNC_ENB_BASE, SZ_4K);
+	if (pmx_driver.base) {
+		ret = pmx_register(&pmx_driver);
+		if (ret)
+			pr_err("padmux: registeration failed. err no: %d\n",
+					ret);
+		iounmap(pmx_driver.base);
+	}
 }
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 34e2647..e35a496 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -37,6 +37,26 @@ static struct mtd_partition partition_info[] = {
 	PARTITION("Root File System", 0x380000, 84 * 0x20000),
 };
 
+/* padmux devices to enable */
+static struct pmx_dev *pmx_devs[] = {
+	/* spear13xx specific devices */
+	&pmx_i2c,
+	&pmx_i2s1,
+	&pmx_i2s2,
+	&pmx_clcd1,
+	&pmx_clcd2,
+	&pmx_egpio_grp,
+	&pmx_gmii,
+	&pmx_keyboard,
+	&pmx_mcif,
+	&pmx_nand_8bit,
+	&pmx_smi_4_chips,
+	&pmx_ssp,
+	&pmx_uart0,
+
+	/* spear1300 specific devices */
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[0],
 	&spear13xx_gpio_device[1],
@@ -103,6 +123,11 @@ static void __init spear1300_evb_init(void)
 {
 	unsigned int i;
 
+	/* padmux initialization, must be done before spear1300_init */
+	pmx_driver.mode = NULL;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
+
 	/* set keyboard plat data */
 	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
 
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 648dabc..cd0878e 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -16,6 +16,9 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+/* pmx driver structure */
+struct pmx_driver pmx_driver;
+
 /* Add spear1310 specific devices here */
 
 /* CAN device registeration */
@@ -57,6 +60,18 @@ struct platform_device spear1310_can1_device = {
 
 void __init spear1310_init(void)
 {
+	int ret;
+
 	/* call spear13xx family common init function */
 	spear13xx_init();
+
+	/* pmx initialization */
+	pmx_driver.base = ioremap(SPEAR13XX_FUNC_ENB_BASE, SZ_4K);
+	if (pmx_driver.base) {
+		ret = pmx_register(&pmx_driver);
+		if (ret)
+			pr_err("padmux: registeration failed. err no: %d\n",
+					ret);
+		iounmap(pmx_driver.base);
+	}
 }
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index 1af152f..87f27cf 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -36,6 +36,26 @@ static struct mtd_partition partition_info[] = {
 	PARTITION("Root File System", 0x380000, 84 * 0x20000),
 };
 
+/* padmux devices to enable */
+static struct pmx_dev *pmx_devs[] = {
+	/* spear13xx specific devices */
+	&pmx_i2c,
+	&pmx_i2s1,
+	&pmx_i2s2,
+	&pmx_clcd1,
+	&pmx_clcd2,
+	&pmx_egpio_grp,
+	&pmx_gmii,
+	&pmx_keyboard,
+	&pmx_mcif,
+	&pmx_nand_8bit,
+	&pmx_smi_4_chips,
+	&pmx_ssp,
+	&pmx_uart0,
+
+	/* spear1310 specific devices */
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear13xx specific devices */
 	&spear13xx_gpio_device[0],
@@ -108,6 +128,11 @@ static void __init spear1310_evb_init(void)
 {
 	unsigned int i;
 
+	/* padmux initialization, must be done before spear1300_init */
+	pmx_driver.mode = NULL;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
+
 	/* set keyboard plat data */
 	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index d6a6dc0..623dffd 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -637,3 +637,531 @@ static void __init spear13xx_timer_init(void)
 struct sys_timer spear13xx_timer = {
 	.init = spear13xx_timer_init,
 };
+
+/* pad multiplexing support */
+/* devices */
+
+/* Pad multiplexing for i2c device */
+static struct pmx_mux_reg pmx_i2c_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2C_MASK,
+		.value = PMX_I2C_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c_modes[] = {
+	{
+		.mux_regs = pmx_i2c_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c_mux),
+	},
+};
+
+struct pmx_dev pmx_i2c = {
+	.name = "i2c",
+	.modes = pmx_i2c_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2c_modes),
+};
+
+/* Pad multiplexing for ssp device */
+static struct pmx_mux_reg pmx_ssp_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK,
+		.value = PMX_SSP_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp_modes[] = {
+	{
+		.mux_regs = pmx_ssp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp_mux),
+	},
+};
+
+struct pmx_dev pmx_ssp = {
+	.name = "ssp",
+	.modes = pmx_ssp_modes,
+	.mode_count = ARRAY_SIZE(pmx_ssp_modes),
+};
+
+/* Pad multiplexing for i2s1 device */
+static struct pmx_mux_reg pmx_i2s1_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2S1_MASK,
+		.value = PMX_I2S1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2s1_modes[] = {
+	{
+		.mux_regs = pmx_i2s1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s1_mux),
+	},
+};
+
+struct pmx_dev pmx_i2s1 = {
+	.name = "i2s1",
+	.modes = pmx_i2s1_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2s1_modes),
+};
+
+/* Pad multiplexing for i2s2 device */
+static struct pmx_mux_reg pmx_i2s2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_I2S2_MASK,
+		.value = PMX_I2S2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2s2_modes[] = {
+	{
+		.mux_regs = pmx_i2s2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s2_mux),
+	},
+};
+
+struct pmx_dev pmx_i2s2 = {
+	.name = "i2s2",
+	.modes = pmx_i2s2_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2s2_modes),
+};
+
+/* Pad multiplexing for clcd1 device */
+static struct pmx_mux_reg pmx_clcd1_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = PMX_CLCD1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd1_modes[] = {
+	{
+		.mux_regs = pmx_clcd1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd1_mux),
+	},
+};
+
+struct pmx_dev pmx_clcd1 = {
+	.name = "clcd1",
+	.modes = pmx_clcd1_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd1_modes),
+};
+
+/* Pad multiplexing for clcd2 device */
+static struct pmx_mux_reg pmx_clcd2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK,
+		.value = PMX_CLCD2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd2_modes[] = {
+	{
+		.mux_regs = pmx_clcd2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd2_mux),
+	},
+};
+
+struct pmx_dev pmx_clcd2 = {
+	.name = "clcd2",
+	.modes = pmx_clcd2_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd2_modes),
+};
+
+/*
+ * By default, all EGPIOs are enabled.
+ * TBD : Board specific enabling of specific GPIOs only
+ */
+static struct pmx_mux_reg pmx_egpio_grp_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_EGPIO_0_GRP_MASK,
+		.value = PMX_EGPIO_0_GRP_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_EGPIO_1_GRP_MASK,
+		.value = PMX_EGPIO_1_GRP_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_egpio_grp_modes[] = {
+	{
+		.mux_regs = pmx_egpio_grp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_egpio_grp_mux),
+	},
+};
+
+struct pmx_dev pmx_egpio_grp = {
+	.name = "egpios",
+	.modes = pmx_egpio_grp_modes,
+	.mode_count = ARRAY_SIZE(pmx_egpio_grp_modes),
+};
+
+/* Pad multiplexing for smi 2 chips device */
+static struct pmx_mux_reg pmx_smi_2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SMI_MASK,
+		.value = PMX_SMI_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smi_2_modes[] = {
+	{
+		.mux_regs = pmx_smi_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smi_2_mux),
+	},
+};
+
+struct pmx_dev pmx_smi_2_chips = {
+	.name = "smi_2_chips",
+	.modes = pmx_smi_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_smi_2_modes),
+};
+
+/* Pad multiplexing for smi 4 chips device */
+static struct pmx_mux_reg pmx_smi_4_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SMI_MASK,
+		.value = PMX_SMI_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+		.value = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smi_4_modes[] = {
+	{
+		.mux_regs = pmx_smi_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smi_4_mux),
+	},
+};
+
+struct pmx_dev pmx_smi_4_chips = {
+	.name = "smi_4_chips",
+	.modes = pmx_smi_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_smi_4_modes),
+};
+
+/* Pad multiplexing for gmii device */
+static struct pmx_mux_reg pmx_gmii_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = PMX_GMII_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gmii_modes[] = {
+	{
+		.mux_regs = pmx_gmii_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gmii_mux),
+	},
+};
+
+struct pmx_dev pmx_gmii = {
+	.name = "gmii",
+	.modes = pmx_gmii_modes,
+	.mode_count = ARRAY_SIZE(pmx_gmii_modes),
+};
+
+/* Pad multiplexing for nand 8bit (4 chips) */
+static struct pmx_mux_reg pmx_nand8_4_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND8BIT4DEV_0_MASK,
+		.value = PMX_NAND8BIT4DEV_0_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT4DEV_1_MASK,
+		.value = PMX_NAND8BIT4DEV_1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand8_4_modes[] = {
+	{
+		.mux_regs = pmx_nand8_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand8_4_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_8bit_4_chips = {
+	.name = "nand-8bit_4_chips",
+	.modes = pmx_nand8_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand8_4_modes),
+};
+
+/* Pad multiplexing for nand 8bit device */
+static struct pmx_mux_reg pmx_nand8_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND8BIT_0_MASK,
+		.value = PMX_NAND8BIT_0_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT_1_MASK,
+		.value = PMX_NAND8BIT_1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand8_modes[] = {
+	{
+		.mux_regs = pmx_nand8_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand8_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_8bit = {
+	.name = "nand-8bit",
+	.modes = pmx_nand8_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand8_modes),
+};
+
+/*
+ * Pad multiplexing for nand 16bit device
+ * Note : Enabling pmx_nand_16bit means that all the required pads for
+ *   16bit nand device operations are enabled. These also include pads
+ *   for 8bit devices
+ */
+static struct pmx_mux_reg pmx_nand16_4_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT4DEV_0_MASK,
+		.value = PMX_NAND16BIT4DEV_0_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT4DEV_1_MASK,
+		.value = PMX_NAND16BIT4DEV_1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand16_4_modes[] = {
+	{
+		.mux_regs = pmx_nand16_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand16_4_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_16bit_4_chips = {
+	.name = "nand-16bit_4_chips",
+	.modes = pmx_nand16_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand16_4_modes),
+};
+
+/* Pad multiplexing for nand 16bit device */
+static struct pmx_mux_reg pmx_nand16_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT_0_MASK,
+		.value = PMX_NAND16BIT_0_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT_1_MASK,
+		.value = PMX_NAND16BIT_1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand16_modes[] = {
+	{
+		.mux_regs = pmx_nand16_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand16_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_16bit = {
+	.name = "nand-16bit",
+	.modes = pmx_nand16_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand16_modes),
+};
+
+/* Pad multiplexing for keyboard device */
+static struct pmx_mux_reg pmx_keyboard_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_MASK,
+		.value = PMX_KEYBOARD_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NFIO815_MASK | PMX_NFCE1_MASK | \
+			PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_keyboard_modes[] = {
+	{
+		.mux_regs = pmx_keyboard_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_mux),
+	},
+};
+
+struct pmx_dev pmx_keyboard = {
+	.name = "keyboard",
+	.modes = pmx_keyboard_modes,
+	.mode_count = ARRAY_SIZE(pmx_keyboard_modes),
+};
+
+/* Pad multiplexing for uart0 device */
+static struct pmx_mux_reg pmx_uart0_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_UART0_MASK,
+		.value = PMX_UART0_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modes[] = {
+	{
+		.mux_regs = pmx_uart0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_mux),
+	},
+};
+
+struct pmx_dev pmx_uart0 = {
+	.name = "uart0",
+	.modes = pmx_uart0_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart0_modes),
+};
+
+/* Pad multiplexing for uart0_modem device */
+static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_UART0_MODEM_MASK,
+		.value = PMX_UART0_MODEM_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
+	{
+		.mux_regs = pmx_uart0_modem_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_modem_mux),
+	},
+};
+
+struct pmx_dev pmx_uart0_modem = {
+	.name = "uart0_modem",
+	.modes = pmx_uart0_modem_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
+};
+
+/* Pad multiplexing for gpt_0_1 device */
+static struct pmx_mux_reg pmx_gpt_0_1_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT0_TMR1_MASK,
+		.value = PMX_GPT0_TMR1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_0_1_modes[] = {
+	{
+		.mux_regs = pmx_gpt_0_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_0_1_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_0_1 = {
+	.name = "gpt_0_1",
+	.modes = pmx_gpt_0_1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_0_1_modes),
+};
+
+/* Pad multiplexing for gpt_0_2 device */
+static struct pmx_mux_reg pmx_gpt_0_2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT0_TMR2_MASK,
+		.value = PMX_GPT0_TMR2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_0_2_modes[] = {
+	{
+		.mux_regs = pmx_gpt_0_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_0_2_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_0_2 = {
+	.name = "gpt_0_2",
+	.modes = pmx_gpt_0_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_0_2_modes),
+};
+
+/* Pad multiplexing for gpt_1_1 device */
+static struct pmx_mux_reg pmx_gpt_1_1_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT1_TMR1_MASK,
+		.value = PMX_GPT1_TMR1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_1_1_modes[] = {
+	{
+		.mux_regs = pmx_gpt_1_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_1_1_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_1_1 = {
+	.name = "gpt_1_1",
+	.modes = pmx_gpt_1_1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_1_1_modes),
+};
+
+/* Pad multiplexing for gpt_1_2 device */
+static struct pmx_mux_reg pmx_gpt_1_2_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT1_TMR2_MASK,
+		.value = PMX_GPT1_TMR2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_1_2_modes[] = {
+	{
+		.mux_regs = pmx_gpt_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_1_2 = {
+	.name = "gpt_1_2",
+	.modes = pmx_gpt_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_1_2_modes),
+};
+
+/* Pad multiplexing for mcif device */
+static struct pmx_mux_reg pmx_mcif_mux[] = {
+	{
+		.offset = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_MCIFALL_1_MASK,
+		.value = PMX_MCIFALL_1_MASK,
+	}, {
+		.offset = PAD_MUX_CONFIG_REG_2,
+		.mask = PMX_MCIFALL_2_MASK,
+		.value = PMX_MCIFALL_2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_mcif_modes[] = {
+	{
+		.mux_regs = pmx_mcif_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_mcif_mux),
+	},
+};
+
+struct pmx_dev pmx_mcif = {
+	.name = "mcif",
+	.modes = pmx_mcif_modes,
+	.mode_count = ARRAY_SIZE(pmx_mcif_modes),
+};
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index c25e5b8..79503dd 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -5,6 +5,7 @@
 # Common support
 obj-y	:= clcd.o clock.o pll_clk.o smi.o time.o
 
+obj-$(CONFIG_ARCH_SPEAR13XX)	+= padmux.o
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:51 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:51 +0530
Subject: [PATCH V2 31/69] ST SPEAr: Adding support for SSP PL022
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <bc7b13eec3a7c657da55f6699695b609cc371594.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   15 +++++
 arch/arm/mach-spear13xx/spear13xx.c            |   31 ++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    2 +
 arch/arm/mach-spear3xx/spear300_evb.c          |   30 +++++++++
 arch/arm/mach-spear3xx/spear310_evb.c          |   42 +++++++++++++
 arch/arm/mach-spear3xx/spear320.c              |   42 +++++++++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |   14 ++++
 arch/arm/mach-spear3xx/spear3xx.c              |   31 ++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear6xx/include/mach/spear.h    |    4 +-
 arch/arm/mach-spear6xx/spear600_evb.c          |   18 ++++++
 arch/arm/mach-spear6xx/spear6xx.c              |   68 +++++++++++++++++++++
 arch/arm/plat-spear/include/plat/spi.h         |   77 ++++++++++++++++++++++++
 14 files changed, 374 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/plat-spear/include/plat/spi.h

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 745dd99..7419e0b 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -30,6 +30,7 @@
 
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
+extern struct amba_device spear13xx_ssp_device;
 extern struct amba_device spear13xx_uart_device;
 extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index d8698e0..ba46f61 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -12,7 +12,10 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -22,10 +25,12 @@
 #include <plat/keyboard.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
+#include <plat/spi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[0],
 	&spear13xx_gpio_device[1],
+	&spear13xx_ssp_device,
 	&spear13xx_uart_device,
 };
 
@@ -50,6 +55,14 @@ static struct kbd_platform_data kbd_data = {
 	.rep = 1,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
 #ifdef CONFIG_PCIEPORTBUS
 /* this function is needed for PCIE host and device driver. Same
  * controller can not be programmed as host as well as device. So host
@@ -107,6 +120,8 @@ static void __init spear1300_evb_init(void)
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
 }
 
 MACHINE_START(SPEAR1300, "ST-SPEAR1300-EVB")
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 25a1964..6455ebb 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -64,6 +65,36 @@ struct amba_device spear13xx_gpio_device[] = {
 	}
 };
 
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data = {
+	.bus_id = 0,
+	.enable_dma = 0,
+	/*
+	 * This is number of spi devices that can be connected to spi. There are
+	 * two type of chipselects on which slave devices can work. One is chip
+	 * select provided by spi masters other is controlled through external
+	 * gpio's. We can't use chipselect provided from spi master (because as
+	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+	 * this number now depends on number of gpios available for spi. each
+	 * slave on each master requires a separate gpio pin.
+	 */
+	.num_chipselect = 2,
+};
+
+struct amba_device spear13xx_ssp_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.init_name = "ssp-pl022",
+		.platform_data = &ssp_platform_data,
+	},
+	.res = {
+		.start = SPEAR13XX_SSP_BASE,
+		.end = SPEAR13XX_SSP_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_SSP, NO_IRQ},
+};
+
 /* uart device registeration */
 struct amba_device spear13xx_uart_device = {
 	.dev = {
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 6aac229..04ce8700 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -32,6 +32,7 @@
 
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device gpio_device;
+extern struct amba_device ssp0_device;
 extern struct amba_device uart_device;
 extern struct amba_device wdt_device;
 extern struct platform_device ehci_device;
@@ -176,6 +177,7 @@ void __init spear310_init(void);
 #elif defined(CONFIG_MACH_SPEAR320)
 /* Add spear320 machine device structure declarations here */
 extern struct amba_device clcd_device;
+extern struct amba_device ssp_device[];
 extern struct platform_device i2c1_device;
 extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 41ad013..c702cc3 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -15,11 +15,15 @@
 #include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <mach/generic.h>
+#include <mach/gpio.h>
 #include <mach/spear.h>
 #include <plat/fsmc.h>
 #include <plat/keyboard.h>
 #include <plat/smi.h>
+#include <plat/spi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -40,6 +44,7 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&gpio_device,
+	&ssp0_device,
 	&uart_device,
 	&wdt_device,
 
@@ -71,6 +76,29 @@ static struct kbd_platform_data kbd_data = {
 	.rep = 1,
 };
 
+/* spi board information */
+/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, flash, RAS_GPIO_3);
+/* spi0 flash Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control);
+
+static struct spi_board_info __initdata spi_board_info[] = {
+	/* spi0 board info */
+	{
+		.modalias = "m25p80",
+		.controller_data = &spi0_flash_chip_info,
+		.max_speed_hz = 400000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = 0,
+	}
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
 static void __init spear300_evb_init(void)
 {
 	unsigned int i;
@@ -102,6 +130,8 @@ static void __init spear300_evb_init(void)
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
 }
 
 MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 857afae..bff90b3 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -15,10 +15,14 @@
 #include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <mach/generic.h>
+#include <mach/gpio.h>
 #include <mach/spear.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
+#include <plat/spi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -47,6 +51,7 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&gpio_device,
+	&ssp0_device,
 	&uart_device,
 	&wdt_device,
 
@@ -67,6 +72,41 @@ static struct platform_device *plat_devs[] __initdata = {
 	&plgpio_device,
 };
 
+/* spi board information */
+/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, flash, BASIC_GPIO_3);
+/* spi0 flash Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control);
+
+/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, dev, BASIC_GPIO_4);
+/* spi0 spidev Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control);
+
+static struct spi_board_info __initdata spi_board_info[] = {
+	/* spi0 board info */
+	{
+		.modalias = "spidev",
+		.controller_data = &spi0_dev_chip_info,
+		.max_speed_hz = 10000000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.mode = 0,
+	}, {
+		.modalias = "m25p80",
+		.controller_data = &spi0_flash_chip_info,
+		.max_speed_hz = 400000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = 0,
+	}
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
 static void __init spear310_evb_init(void)
 {
 	unsigned int i;
@@ -95,6 +135,8 @@ static void __init spear310_evb_init(void)
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
 }
 
 MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 3def755..f87cc97 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/amba/pl022.h>
 #include <linux/ptrace.h>
 #include <mtd/fsmc.h>
 #include <asm/irq.h>
@@ -403,6 +404,47 @@ struct amba_device clcd_device = {
 	.irq = {VIRQ_CLCD, NO_IRQ},
 };
 
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data[] = {
+	{
+		.bus_id = 1,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 2,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}
+};
+
+struct amba_device ssp_device[] = {
+	{
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.1",
+			.platform_data = &ssp_platform_data[0],
+		},
+		.res = {
+			.start = SPEAR320_SSP0_BASE,
+			.end = SPEAR320_SSP0_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {VIRQ_SSP1, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.2",
+			.platform_data = &ssp_platform_data[1],
+		},
+		.res = {
+			.start = SPEAR320_SSP1_BASE,
+			.end = SPEAR320_SSP1_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {VIRQ_SSP2, NO_IRQ},
+	}
+};
+
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 3a066bb..dcca84e 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -15,10 +15,14 @@
 #include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <mach/generic.h>
+#include <mach/gpio.h>
 #include <mach/spear.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
+#include <plat/spi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -67,6 +71,14 @@ static struct platform_device *plat_devs[] __initdata = {
 	&pwm_device,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
 static void __init spear320_evb_init(void)
 {
 	unsigned int i;
@@ -95,6 +107,8 @@ static void __init spear320_evb_init(void)
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
 }
 
 MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 88a6bd4..b4c3ad7 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -41,6 +42,36 @@ struct amba_device gpio_device = {
 	.irq = {IRQ_BASIC_GPIO, NO_IRQ},
 };
 
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data = {
+	.bus_id = 0,
+	.enable_dma = 0,
+	/*
+	 * This is number of spi devices that can be connected to spi. There are
+	 * two type of chipselects on which slave devices can work. One is chip
+	 * select provided by spi masters other is controlled through external
+	 * gpio's. We can't use chipselect provided from spi master (because as
+	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+	 * this number now depends on number of gpios available for spi. each
+	 * slave on each master requires a separate gpio pin.
+	 */
+	.num_chipselect = 2,
+};
+
+struct amba_device ssp0_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.init_name = "ssp-pl022.0",
+		.platform_data = &ssp_platform_data,
+	},
+	.res = {
+		.start = SPEAR3XX_ICM1_SSP_BASE,
+		.end = SPEAR3XX_ICM1_SSP_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_SSP, NO_IRQ},
+};
+
 /* uart device registeration */
 struct amba_device uart_device = {
 	.dev = {
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index ff90419..dd29298 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -31,6 +31,7 @@
 /* Add spear6xx family device structure declarations here */
 extern struct amba_device clcd_device;
 extern struct amba_device gpio_device[];
+extern struct amba_device ssp_device[];
 extern struct amba_device uart_device[];
 extern struct amba_device wdt_device;
 extern struct platform_device ehci0_device;
diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h
index a835f5b..31486e5 100644
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ b/arch/arm/mach-spear6xx/include/mach/spear.h
@@ -68,8 +68,8 @@
 #define SPEAR6XX_ICM2_GPIO_BASE		0xD8100000
 #define SPEAR6XX_ICM2_GPIO_SIZE		0x00080000
 
-#define SPEAR6XX_ICM2_SPI2_BASE		0xD8180000
-#define SPEAR6XX_ICM2_SPI2_SIZE		0x00080000
+#define SPEAR6XX_ICM2_SSP2_BASE		0xD8180000
+#define SPEAR6XX_ICM2_SSP2_SIZE		0x00080000
 
 #define SPEAR6XX_ICM2_ADC_BASE		0xD8200000
 #define SPEAR6XX_ICM2_ADC_SIZE		0x00080000
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index f3b1fb4..a98d7d6 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -15,16 +15,24 @@
 #include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <linux/gpio.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <mach/generic.h>
+#include <mach/gpio.h>
 #include <mach/spear.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
+#include <plat/spi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&clcd_device,
 	&gpio_device[0],
 	&gpio_device[1],
 	&gpio_device[2],
+	&ssp_device[0],
+	&ssp_device[1],
+	&ssp_device[2],
 	&uart_device[0],
 	&uart_device[1],
 	&wdt_device,
@@ -41,6 +49,14 @@ static struct platform_device *plat_devs[] __initdata = {
 	&smi_device,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
+static void __init spi_init(void)
+{
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
 static void __init spear600_evb_init(void)
 {
 	unsigned int i;
@@ -64,6 +80,8 @@ static void __init spear600_evb_init(void)
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
+
+	spi_init();
 }
 
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index cc4fd39..82788e1 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -41,6 +42,73 @@ struct amba_device clcd_device = {
 	.irq = {IRQ_BASIC_CLCD, NO_IRQ},
 };
 
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data[] = {
+	{
+		.bus_id = 0,
+		.enable_dma = 0,
+		/*
+		 * This is number of spi devices that can be connected to spi.
+		 * There are two type of chipselects on which slave devices can
+		 * work. One is chip select provided by spi masters other is
+		 * controlled through external gpio's. We can't use chipselect
+		 * provided from spi master (because as soon as FIFO becomes
+		 * empty, CS is disabled and transfer ends). So this number now
+		 * depends on number of gpios available for spi. each slave on
+		 * each master requires a separate gpio pin.
+		 */
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 1,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 2,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}
+};
+
+struct amba_device ssp_device[] = {
+	{
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.0",
+			.platform_data = &ssp_platform_data[0],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM1_SSP0_BASE,
+			.end = SPEAR6XX_ICM1_SSP0_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_SSP_1, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.1",
+			.platform_data = &ssp_platform_data[1],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM1_SSP1_BASE,
+			.end = SPEAR6XX_ICM1_SSP1_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_SSP_2, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.2",
+			.platform_data = &ssp_platform_data[2],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM2_SSP2_BASE,
+			.end = SPEAR6XX_ICM2_SSP2_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_APPL_SSP, NO_IRQ},
+	}
+};
+
 /* uart device registeration */
 struct amba_device uart_device[] = {
 	{
diff --git a/arch/arm/plat-spear/include/plat/spi.h b/arch/arm/plat-spear/include/plat/spi.h
new file mode 100644
index 0000000..a2c53f3
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/spi.h
@@ -0,0 +1,77 @@
+/*
+ * arch/arm/plat-spear/include/plat/spi.h
+ *
+ * SPI board specific definitions common to multiple boards on multiple
+ * machines.
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Viresh Kumar<viresh.kumar at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_SPI_H
+#define __PLAT_SPI_H
+
+#include <linux/amba/pl022.h>
+#include <linux/gpio.h>
+
+/* spi board information */
+static inline int spi_cs_gpio_request(u32 gpio_pin)
+{
+	int ret;
+
+	ret = gpio_request(gpio_pin, "SPI_CS");
+	if (ret < 0) {
+		printk(KERN_ERR "SPI: gpio:%d request fail\n", gpio_pin);
+		return ret;
+	} else {
+		ret = gpio_direction_output(gpio_pin, 1);
+		if (ret) {
+			printk(KERN_ERR "SPI: gpio:%d direction set fail\n",
+					gpio_pin);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+/* This will define cs_control function for a specific spi slave */
+#define DECLARE_SPI_CS_CONTROL(id, type, gpio)		\
+static void spi##id##_##type##_cs_control(u32 control)	\
+{							\
+	static int count, ret;				\
+							\
+	if (unlikely(!count)) {				\
+		count++;				\
+		ret = spi_cs_gpio_request(gpio);	\
+	}						\
+							\
+	if (!ret)					\
+		gpio_set_value(gpio, control);		\
+}
+
+/* This will define CHIP_INFO structure for a specific spi slave */
+#define DECLARE_SPI_CHIP_INFO(id, type, chip_select_control)	\
+struct pl022_config_chip spi##id##_##type##_chip_info = {	\
+	.lbm = LOOPBACK_DISABLED,			\
+	.iface = SSP_INTERFACE_MOTOROLA_SPI,		\
+	.hierarchy = SSP_MASTER,			\
+	.slave_tx_disable = 0,				\
+	.endian_tx = SSP_TX_LSB,			\
+	.endian_rx = SSP_RX_LSB,			\
+	.data_size = SSP_DATA_BITS_8,			\
+	.com_mode = INTERRUPT_TRANSFER,			\
+	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,		\
+	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,	\
+	.clk_phase = SSP_CLK_SECOND_EDGE,		\
+	.clk_pol = SSP_CLK_POL_IDLE_LOW,		\
+	.cs_control = chip_select_control,		\
+};
+
+#define DECLARE_SPI_CHIP_INFO_NULL_ID(chip_select_control)	\
+DECLARE_SPI_CHIP_INFO(, chip_select_control)
+
+#endif /* __PLAT_SPI_H */
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:29 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:29 +0530
Subject: [PATCH V2 69/69] ST SPEAr: Updating defconfigs
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <68d391813bcedde825ee7b207b533abfbe20c585.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
---
 arch/arm/configs/spear13xx_defconfig |   78 ++++++++++++++++++++++++++++++---
 arch/arm/configs/spear3xx_defconfig  |   80 +++++++++++++++++++++++++++++++---
 arch/arm/configs/spear6xx_defconfig  |   72 ++++++++++++++++++++++++++++---
 3 files changed, 211 insertions(+), 19 deletions(-)

diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 9f3baf8..d764fee 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -10,31 +10,94 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_BOARD_SPEAR1300_EVB=y
 CONFIG_BOARD_SPEAR1310_EVB=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEAER is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=y
+CONFIG_ARPD=y
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_SPEAR=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
@@ -42,16 +105,18 @@ CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
@@ -59,3 +124,4 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig
index fea7e1f..5a210ce 100644
--- a/arch/arm/configs/spear3xx_defconfig
+++ b/arch/arm/configs/spear3xx_defconfig
@@ -10,13 +10,54 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_BOARD_SPEAR300_EVB=y
 CONFIG_BOARD_SPEAR310_EVB=y
 CONFIG_BOARD_SPEAR320_EVB=y
+CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_ARPD=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_SPEAR=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -24,30 +65,55 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SAMSUNG_LMS700=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig
index cef2e83..5217396 100644
--- a/arch/arm/configs/spear6xx_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -9,10 +9,48 @@ CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR6XX=y
 CONFIG_BOARD_SPEAR600_EVB=y
+CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_ARPD=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_SERIAL_AMBA_PL011=y
@@ -20,30 +58,52 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SAMSUNG_LMS700=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
+# CONFIG_ARM_UNWIND is not set
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:48 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:48 +0530
Subject: [PATCH V2 28/69] ST SPEAr: Adding machine support for nand
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <1076320a0194c19ef0b4beefdf3c43a44e200439.1285933331.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h   |    2 +
 arch/arm/mach-spear13xx/include/mach/misc_regs.h |   10 ++
 arch/arm/mach-spear13xx/spear1300_evb.c          |    9 ++
 arch/arm/mach-spear13xx/spear13xx.c              |   58 +++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h    |   15 ++--
 arch/arm/mach-spear3xx/include/mach/spear320.h   |    3 +
 arch/arm/mach-spear3xx/spear300.c                |   98 ++++++++++++++++++++++
 arch/arm/mach-spear3xx/spear300_evb.c            |    8 ++
 arch/arm/mach-spear3xx/spear310.c                |   26 ++++++
 arch/arm/mach-spear3xx/spear310_evb.c            |    8 ++
 arch/arm/mach-spear3xx/spear320.c                |   26 ++++++
 arch/arm/mach-spear3xx/spear320_evb.c            |    8 ++
 arch/arm/mach-spear6xx/include/mach/generic.h    |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c            |    8 ++
 arch/arm/mach-spear6xx/spear6xx.c                |   26 ++++++
 arch/arm/plat-spear/include/plat/fsmc.h          |   36 ++++++++
 16 files changed, 336 insertions(+), 6 deletions(-)
 create mode 100644 arch/arm/plat-spear/include/plat/fsmc.h

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 960ff06..745dd99 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -35,6 +35,7 @@ extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
 extern struct platform_device spear13xx_i2c_device;
 extern struct platform_device spear13xx_kbd_device;
+extern struct platform_device spear13xx_nand_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
@@ -51,6 +52,7 @@ void __init spear1300_init(void);
 void __init spear13xx_map_io(void);
 void __init spear13xx_init_irq(void);
 void __init spear13xx_init(void);
+void __init nand_mach_init(u32 busw);
 void spear13xx_secondary_startup(void);
 
 #endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/misc_regs.h b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
index a8a1119..e6823db 100644
--- a/arch/arm/mach-spear13xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
@@ -210,6 +210,16 @@
 	#define CF_MMC_ACTIVE	0x2
 	#define XD_MMC_ACTIVE	0x3
 #define FSMC_CFG		((unsigned int *)(MISC_BASE + 0x330))
+	/* FSMC_CFG register masks */
+	#define FSMC_MEMSEL_MASK	0x3
+	#define FSMC_MEMSEL_SHIFT	0
+	#define FSMC_MEM_NOR		0
+	#define FSMC_MEM_NAND		1
+	#define FSMC_MEM_SRAM		2
+	#define NAND_BANK_MASK		0x3
+	#define NAND_BANK_SHIFT		2
+	#define NAND_DEV_WIDTH16	4
+
 #define MPMC_CTR_STS		((unsigned int *)(MISC_BASE + 0x334))
 
 /* Inter-Processor Communication Registers */
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 1e637fa..56a4294 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -12,11 +12,14 @@
  */
 
 #include <linux/types.h>
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
 #include <plat/keyboard.h>
+#include <plat/fsmc.h>
 #include <plat/smi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -30,6 +33,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
 	&spear13xx_kbd_device,
+	&spear13xx_nand_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
@@ -52,6 +56,11 @@ static void __init spear1300_evb_init(void)
 	/* set keyboard plat data */
 	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
 
+	/* set nand device's plat data */
+	fsmc_nand_set_plat_data(&spear13xx_nand_device, NULL, 0,
+			NAND_SKIP_BBTSCAN, FSMC_NAND_BW8);
+	nand_mach_init(FSMC_NAND_BW8);
+
 	/* call spear1300 machine init function */
 	spear1300_init();
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index f7d30a9..55d654f 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -15,6 +15,7 @@
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
+#include <mtd/fsmc.h>
 #include <asm/hardware/gic.h>
 #include <asm/irq.h>
 #include <asm/localtimer.h>
@@ -23,6 +24,7 @@
 #include <mach/irqs.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
+#include <mach/misc_regs.h>
 
 /* Add spear13xx machines common devices here */
 /* gpio device registeration */
@@ -97,6 +99,62 @@ struct platform_device spear13xx_i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* nand device registeration */
+void __init nand_mach_init(u32 busw)
+{
+	u32 fsmc_cfg = readl(FSMC_CFG);
+	fsmc_cfg &= ~(FSMC_MEMSEL_MASK << FSMC_MEMSEL_SHIFT);
+	fsmc_cfg |= (FSMC_MEM_NAND << FSMC_MEMSEL_SHIFT);
+
+	if (busw == FSMC_NAND_BW16)
+		fsmc_cfg |= 1 << NAND_DEV_WIDTH16;
+	else
+		fsmc_cfg &= ~(1 << NAND_DEV_WIDTH16);
+
+	writel(fsmc_cfg, FSMC_CFG);
+}
+
+static void nand_select_bank(u32 bank, u32 busw)
+{
+	u32 fsmc_cfg = readl(FSMC_CFG);
+
+	fsmc_cfg &= ~(NAND_BANK_MASK << NAND_BANK_SHIFT);
+	fsmc_cfg |= (bank << NAND_BANK_SHIFT);
+
+	if (busw)
+		fsmc_cfg |= 1 << NAND_DEV_WIDTH16;
+	else
+		fsmc_cfg &= ~(1 << NAND_DEV_WIDTH16);
+
+	writel(fsmc_cfg, FSMC_CFG);
+}
+
+static struct fsmc_nand_platform_data nand_platform_data = {
+	.select_bank = nand_select_bank,
+};
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR13XX_FSMC_MEM_BASE,
+		.end = SPEAR13XX_FSMC_MEM_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR13XX_FSMC_BASE,
+		.end = SPEAR13XX_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear13xx_nand_device = {
+	.name = "nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+	.dev.platform_data = &nand_platform_data,
+};
+
 /* usb host device registeration */
 static struct resource ehci0_resources[] = {
 	[0] = {
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 91c0c09..6aac229 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -111,6 +111,10 @@ extern struct pmx_driver pmx_driver;
 extern struct amba_device clcd_device;
 extern struct amba_device gpio1_device;
 extern struct platform_device kbd_device;
+extern struct platform_device nand0_device;
+extern struct platform_device nand1_device;
+extern struct platform_device nand2_device;
+extern struct platform_device nand3_device;
 
 /* pad mux modes */
 extern struct pmx_mode nand_mode;
@@ -148,12 +152,12 @@ void __init spear300_init(void);
 
 /* Add misc structure declarations here */
 extern struct clcd_board clcd_plat_data;
-#endif /* CONFIG_MACH_SPEAR300 */
 
 /* spear310 declarations */
-#ifdef CONFIG_MACH_SPEAR310
+#elif defined(CONFIG_MACH_SPEAR310)
 /* Add spear310 machine device structure declarations here */
 extern struct platform_device plgpio_device;
+extern struct platform_device nand_device;
 
 /* pad mux devices */
 extern struct pmx_dev pmx_emi_cs_0_1_4_5;
@@ -168,13 +172,12 @@ extern struct pmx_dev pmx_tdm0;
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
 
-#endif /* CONFIG_MACH_SPEAR310 */
-
 /* spear320 declarations */
-#ifdef CONFIG_MACH_SPEAR320
+#elif defined(CONFIG_MACH_SPEAR320)
 /* Add spear320 machine device structure declarations here */
 extern struct amba_device clcd_device;
 extern struct platform_device i2c1_device;
+extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
 extern struct platform_device pwm_device;
 
@@ -213,6 +216,6 @@ void __init spear320_init(void);
 
 /* Add misc structure declarations here */
 extern struct clcd_board clcd_plat_data;
-#endif /* CONFIG_MACH_SPEAR320 */
+#endif
 
 #endif /* __MACH_GENERIC_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 53677e4..aa6727c 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -22,6 +22,9 @@
 #define SPEAR320_FSMC_BASE		0x4C000000
 #define SPEAR320_FSMC_SIZE		0x01000000
 
+#define SPEAR320_NAND_BASE		0x50000000
+#define SPEAR320_NAND_SIZE		0x04000000
+
 #define SPEAR320_I2S_BASE		0x60000000
 #define SPEAR320_I2S_SIZE		0x10000000
 
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index c80d4e1..c213614 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
+#include <mtd/fsmc.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -426,6 +427,103 @@ struct platform_device kbd_device = {
 	.resource = kbd_resources,
 };
 
+/* nand device registeration */
+static struct fsmc_nand_platform_data nand0_platform_data;
+
+static struct resource nand0_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_0_BASE,
+		.end = SPEAR300_NAND_0_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand0_device = {
+	.name = "nand",
+	.id = 0,
+	.resource = nand0_resources,
+	.num_resources = ARRAY_SIZE(nand0_resources),
+	.dev.platform_data = &nand0_platform_data,
+};
+
+static struct fsmc_nand_platform_data nand1_platform_data;
+
+static struct resource nand1_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_1_BASE,
+		.end = SPEAR300_NAND_1_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand1_device = {
+	.name = "nand",
+	.id = 1,
+	.resource = nand1_resources,
+	.num_resources = ARRAY_SIZE(nand1_resources),
+	.dev.platform_data = &nand1_platform_data,
+};
+
+static struct fsmc_nand_platform_data nand2_platform_data;
+
+static struct resource nand2_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_2_BASE,
+		.end = SPEAR300_NAND_2_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand2_device = {
+	.name = "nand",
+	.id = 2,
+	.resource = nand2_resources,
+	.num_resources = ARRAY_SIZE(nand2_resources),
+	.dev.platform_data = &nand2_platform_data,
+};
+
+static struct fsmc_nand_platform_data nand3_platform_data;
+
+static struct resource nand3_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_3_BASE,
+		.end = SPEAR300_NAND_3_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand3_device = {
+	.name = "nand",
+	.id = 3,
+	.resource = nand3_resources,
+	.num_resources = ARRAY_SIZE(nand3_resources),
+	.dev.platform_data = &nand3_platform_data,
+};
+
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 7bd8963..41ad013 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -11,10 +11,13 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/fsmc.h>
 #include <plat/keyboard.h>
 #include <plat/smi.h>
 
@@ -49,6 +52,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&ehci_device,
 	&i2c_device,
+	&nand0_device,
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
@@ -79,6 +83,10 @@ static void __init spear300_evb_init(void)
 	/* set keyboard plat data */
 	kbd_set_plat_data(&kbd_device, &kbd_data);
 
+	/* set nand0 device's plat data */
+	fsmc_nand_set_plat_data(&nand0_device, NULL, 0, NAND_SKIP_BBTSCAN,
+			FSMC_NAND_BW8);
+
 	/* call spear300 machine init function */
 	spear300_init();
 
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 88b55b5..1c84303 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/ptrace.h>
+#include <mtd/fsmc.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -177,6 +178,31 @@ int spear300_o2p(int offset)
 		return offset + 2;
 }
 
+/* nand device registeration */
+static struct fsmc_nand_platform_data nand_platform_data;
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR310_NAND_BASE,
+		.end = SPEAR310_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR310_FSMC_BASE,
+		.end = SPEAR310_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand_device = {
+	.name = "nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+	.dev.platform_data = &nand_platform_data,
+};
+
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
 	.irq_base = SPEAR_PLGPIO_INT_BASE,
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index cd076c9..857afae 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -11,10 +11,13 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/fsmc.h>
 #include <plat/smi.h>
 
 /* padmux devices to enable */
@@ -54,6 +57,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&ehci_device,
 	&i2c_device,
+	&nand_device,
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
@@ -72,6 +76,10 @@ static void __init spear310_evb_init(void)
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
 
+	/* set nand device's plat data */
+	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
+			FSMC_NAND_BW8);
+
 	/* call spear310 machine init function */
 	spear310_init();
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 75e7890..3def755 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/ptrace.h>
+#include <mtd/fsmc.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -431,6 +432,31 @@ struct platform_device i2c1_device = {
 	.resource = i2c1_resources,
 };
 
+/* nand device registeration */
+static struct fsmc_nand_platform_data nand_platform_data;
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR320_NAND_BASE,
+		.end = SPEAR320_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR320_FSMC_BASE,
+		.end = SPEAR320_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand_device = {
+	.name = "nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+	.dev.platform_data = &nand_platform_data,
+};
+
 static struct resource plgpio_resources[] = {
 	{
 		.start = SPEAR320_SOC_CONFIG_BASE,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 7f7b5dd..3a066bb 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -11,10 +11,13 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/fsmc.h>
 #include <plat/smi.h>
 
 /* padmux devices to enable */
@@ -52,6 +55,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&ehci_device,
 	&i2c_device,
+	&nand_device,
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
@@ -72,6 +76,10 @@ static void __init spear320_evb_init(void)
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
 
+	/* set nand device's plat data */
+	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
+			FSMC_NAND_BW8);
+
 	/* call spear320 machine init function */
 	spear320_init();
 
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index f885898..ff90419 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -36,6 +36,7 @@ extern struct amba_device wdt_device;
 extern struct platform_device ehci0_device;
 extern struct platform_device ehci1_device;
 extern struct platform_device i2c_device;
+extern struct platform_device nand_device;
 extern struct platform_device ohci0_device;
 extern struct platform_device ohci1_device;
 extern struct platform_device rtc_device;
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index 0eb5f50..f3b1fb4 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -11,10 +11,13 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/fsmc.h>
 #include <plat/smi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -33,6 +36,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&i2c_device,
 	&ohci0_device,
 	&ohci1_device,
+	&nand_device,
 	&rtc_device,
 	&smi_device,
 };
@@ -41,6 +45,10 @@ static void __init spear600_evb_init(void)
 {
 	unsigned int i;
 
+	/* set nand device's plat data */
+	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
+			FSMC_NAND_BW8);
+
 	/* call spear600 machine init function */
 	spear600_init();
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 2eec8ac..cc4fd39 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -15,6 +15,7 @@
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
+#include <mtd/fsmc.h>
 #include <asm/hardware/vic.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
@@ -152,6 +153,31 @@ struct platform_device i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* nand device registeration */
+static struct fsmc_nand_platform_data nand_platform_data;
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR6XX_ICM1_NAND_BASE,
+		.end = SPEAR6XX_ICM1_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR6XX_ICM1_FSMC_BASE,
+		.end = SPEAR6XX_ICM1_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand_device = {
+	.name = "nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+	.dev.platform_data = &nand_platform_data,
+};
+
 /* usb host device registeration */
 static struct resource ehci0_resources[] = {
 	[0] = {
diff --git a/arch/arm/plat-spear/include/plat/fsmc.h b/arch/arm/plat-spear/include/plat/fsmc.h
new file mode 100644
index 0000000..bb161fb
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/fsmc.h
@@ -0,0 +1,36 @@
+/*
+ * arch/arm/plat-spear/include/plat/fsmc.h
+ *
+ * FSMC definitions for SPEAr platform
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar <vipin.kumar at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_FSMC_H
+#define __PLAT_FSMC_H
+
+#include <mtd/fsmc.h>
+
+/* This function is used to set platform data field of pdev->dev */
+static inline void fsmc_nand_set_plat_data(struct platform_device *pdev,
+		struct mtd_partition *partitions, unsigned int nr_partitions,
+		unsigned int options, unsigned int width)
+{
+	struct fsmc_nand_platform_data *plat_data;
+	plat_data = dev_get_platdata(&pdev->dev);
+
+	if (partitions) {
+		plat_data->partitions = partitions;
+		plat_data->nr_partitions = nr_partitions;
+	}
+
+	plat_data->options = options;
+	plat_data->width = width;
+}
+
+#endif /* __PLAT_FSMC_H */
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:01 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:01 +0530
Subject: [PATCH V2 41/69] SPEAr Clock Framework: Adding support for PLL
	frequency change
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <e9532ec2012f0e96068ecb2f57088e550a80aa00.1285933332.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri at st.com>

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/spear3xx.c        |    5 +
 arch/arm/mach-spear6xx/spear6xx.c        |    5 +
 arch/arm/plat-spear/Makefile             |    2 +-
 arch/arm/plat-spear/clock.c              |    6 +-
 arch/arm/plat-spear/include/plat/clock.h |    1 +
 arch/arm/plat-spear/pll_clk.S            |  187 ++++++++++++++++++++++++++++++
 6 files changed, 201 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/plat-spear/pll_clk.S

diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index dcbe020..c9727ac 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -271,6 +271,11 @@ struct map_desc spear3xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR3XX_ICM3_SDRAM_CTRL_BASE),
+		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SDRAM_CTRL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
 	},
 };
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index cd2153c..cc2692e 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -430,6 +430,11 @@ static struct map_desc spear6xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR6XX_ICM3_SDRAM_CTRL_BASE),
+		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SDRAM_CTRL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
 	},
 };
 
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 50c680c..0e2cf75 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y	:= clcd.o clock.o time.o smi.o
+obj-y	:= clcd.o clock.o pll_clk.o smi.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index fb1c87b..ee8f82b 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -586,11 +586,10 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 			 * call routine to put ddr in refresh mode, and
 			 * configure pll.
 			 */
-			/* TBD */
+			pll_set_rate(tbls[i].m, tbls[i].p, tbls[i].n);
 			clk->rate = rate;
 		}
-
-		return ret;
+		return 0;
 	}
 
 	val = readl(config->mode_reg) &
@@ -616,7 +615,6 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 			config->masks->norm_fdbk_m_shift;
 
 	writel(val, config->cfg_reg);
-
 	clk->rate = rate;
 
 	return 0;
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 6ddcf93..00d6854 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -264,5 +264,6 @@ int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long clcd_calc_rate(struct clk *clk, int index);
 int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+void pll_set_rate(u16 pdiv, u8 nmul, u8 hclkdiv);
 
 #endif /* __PLAT_CLOCK_H */
diff --git a/arch/arm/plat-spear/pll_clk.S b/arch/arm/plat-spear/pll_clk.S
new file mode 100644
index 0000000..d0687b4
--- /dev/null
+++ b/arch/arm/plat-spear/pll_clk.S
@@ -0,0 +1,187 @@
+/*
+ * arch/arm/plat-spear/pll_clk.S
+ *
+ * SPEAR3xx and SPEAR6xx specific functions that will run in
+ * cache. These funstions intend to configure the PLL.
+ *
+ * Copyright (ST) 2010 Deepak Sikri <deepak.sikri at .com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+#if defined(CONFIG_ARCH_SPEAR3XX) || defined(CONFIG_ARCH_SPEAR6XX)
+.text
+ENTRY(pll_set_rate)
+	stmfd	sp!, {r0-r12, lr}
+
+	/* Lock down the TLB entry to the current victim */
+	mrc	p15, 0, r3, c10, c0, 0	/* read the lockdown register */
+	orr	r3, r3, #1		/* set the preserved bit */
+	mcr	p15, 0, r3, c10, c0, 0	/* write to the lockdown register */
+
+	/*
+	 * set r4 to the value of the address to be locked down.
+	 * Invalidate the TLB single entry in TLB to ensure that
+	 * the locked address is not already in TLB.
+	 * MPMC, System Controller & Miscellaneous register address
+	 * are locked down below.
+	 */
+
+	ldr	r4, MPMC_BASE_VA
+	/* Invalidate the MPMC virtual address in TLB. */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	ldr	r4, SYS_CTRL_BASE_VA
+	/* Invalidate the System controller virtual address in TLB */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	ldr	r4, MISC_BASE_VA
+	/* Invalidate the Miscellaneous registers virtual address in TLB */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	/* clear preserve bit */
+	bic	r3, r3, #1
+	/* write to the lockdown register */
+	mcr	p15, 0, r3, c10, c0, 0
+
+	ldr	r7, MPMC_BASE_VA
+	ldr	r8, SYS_CTRL_BASE_VA
+	ldr	r6, MISC_BASE_VA
+	/* Prefetch certain instructions in the cache. */
+	adr	r4, cache_prefetch_start1
+	adr	r5, cache_prefetch_end1
+	mvn	r3, #0x1F
+	ands	r4, r3, r4
+	/* Lock Instructions in i-cache */
+fetch_loop:
+	/*
+	 * copy a cache-line-sized block of main memory to a cache
+	 * line in the I-cache.
+	 */
+	mcr	p15, 0, r4, c7, c13, 1
+	cmp	r4, r5
+	addls	r4, r4, #0x20
+	bls	fetch_loop
+cache_prefetch_start1:
+	/* Put SDRAM in self-refresh mode */
+	ldr	r3, [r7, #0x1c]
+	/* Clear START bit(24) of MEMCTL_GP_03 register in MPMC */
+	ldr	r4, =0x1000000
+	bic	r3, r3, r4
+	str	r3, [r7, #0x1c]
+
+	ldr	r3, [r7, #0xe4]
+	ldr	r4, =0xffff0000
+	/* Latch the current self refresh time */
+	mov	r9, r3
+	/* Increase the self refresh exit time */
+	bic	r3, r3, r4
+	ldr	r4, =0xffff
+	/* Program the SDRAM self refresh exit time on read command */
+	orr	r3, r3, r4, LSL #16
+	str	r3, [r7, #0xe4]
+
+	ldr	r3, [r7, #0x1c]
+	/* Set the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	orr	r3, r3, r4
+	str	r3, [r7, #0x1c]
+
+	/* Put the system in slow mode, use system controller */
+	ldr	r3, [r8]
+	bic	r3, r3, #0x7
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r3, r3, #0x2
+	str	r3, [r8]
+
+wait_till_slow_mode:
+	ldr	r3, [r8]
+	and	r3, r3, #0x78	/* Wait for the mode to be updated */
+	cmp	r3, #0x10	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_slow_mode
+
+	/*
+	 * reprogram the m(r0), p(r2), n(r1) values in the PLL
+	 * control registers (PLL_FRQ register in misc space).
+	 */
+	ldr	r3, [r6, #0x0c]
+	bic	r3, r3, #0x00ff
+	/* Program the PLL post divisor: p */
+	orr	r3, r3, r2
+	str	r3, [r6, #0x0c]
+
+	ldr	r3, [r6, #0x0c]
+	ldr	r4, =0xffff0000
+	bic	r3, r3, r4
+	bic	r3, r3, #0x0700
+	/* Program the PLL pre divisor: n */
+	orr	r3, r3, r1, LSL #8
+	/* Program the PLL feedback divisor: m */
+	orr	r3, r3, r0, LSL #24
+	str	r3, [r6, #0x0c]
+
+	/* Move the system in Normal mode, use system controller */
+	ldr	r3, [r8, #0x0]
+	ldr	r4, =0xfffffff8
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	and	r3, r3, r4
+	orr	r3, r3, #0x4
+	str	r3, [r8, #0x0]
+
+wait_till_normal_mode:
+	ldr	r3, [r8, #0x0]
+	and	r3, r3, #0x78
+	cmp	r3, #0x20	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_normal_mode
+
+	/* Exit DDR-SDRAM from self-refresh mode */
+	ldr	r10, MPMC_BASE_VA
+	/* Clear the SREFRESH bit(16) */
+	ldr	r3, [r10, #0x1c]
+	ldr	r4, =0x10000
+	bic	r3, r3, r4
+	str	r3, [r10, #0x1c]
+	/* Restore the SDRAM self refresh exit time on read command */
+	mov	r3, r9
+	str	r3, [r7, #0xe4]
+	/* Begin the command processing in controller */
+	ldr	r4, =0x1000000
+	orr	r3, r3, r4
+	/* Set START bit(24) of MEMCTL_GP_03 register in MPMC*/
+	str	r3, [r10, #0x1c]
+
+	ldmfd	sp!, {r0-r12, pc}
+
+/* This is the end of the code to be copied */
+
+SYS_CTRL_BASE_VA :
+	.word IO_ADDRESS(SYS_CTRL_BASE_PA)
+MPMC_BASE_VA :
+	.word IO_ADDRESS(MPMC_BASE_PA)
+MISC_BASE_VA :
+	.word IO_ADDRESS(MISC_BASE_PA)
+cache_prefetch_end1 :
+
+#elif defined(CONFIG_ARCH_SPEAR13XX)
+.text
+ENTRY(pll_set_rate)
+#endif
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:10 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:10 +0530
Subject: [PATCH V2 50/69] ST SPEAr13xx: Modified static mappings
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <81ee7baeea114d591582d1adf33b67f45af5df12.1285933332.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

The new static io mappings map regions in 0xE...,.... space to
0xF...,.... and those in space 0x6...,.... to 0xE...,.... range.
This is done to accomodate regions of RAS configuration registers to be
used by clock frameowrk and possibly others.

Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/hardware.h |    7 ++++++-
 arch/arm/mach-spear13xx/include/mach/vmalloc.h  |    2 +-
 arch/arm/mach-spear13xx/spear13xx.c             |    8 ++++++++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/hardware.h b/arch/arm/mach-spear13xx/include/mach/hardware.h
index 4abc2c0..44cd0c2 100644
--- a/arch/arm/mach-spear13xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear13xx/include/mach/hardware.h
@@ -17,7 +17,12 @@
 #include <mach/spear.h>
 
 /* Vitual to physical translation of statically mapped space */
-#define IO_ADDRESS(x)		(x | 0xF0000000)
+/*
+ * if phy_addr is 0x8...,.... and above then map it to  0xF...,....
+ * else map it to 0xE...,....
+ */
+
+#define IO_ADDRESS(x)   ((x) | ((((x) >> 31) << 28) | 0xE0000000))
 
 /* typesafe io address */
 #define __io_address(n)		__io(IO_ADDRESS(n))
diff --git a/arch/arm/mach-spear13xx/include/mach/vmalloc.h b/arch/arm/mach-spear13xx/include/mach/vmalloc.h
index 85ad57e..9f329d1 100644
--- a/arch/arm/mach-spear13xx/include/mach/vmalloc.h
+++ b/arch/arm/mach-spear13xx/include/mach/vmalloc.h
@@ -13,6 +13,6 @@
 #ifndef __MACH_VMALLOC_H
 #define __MACH_VMALLOC_H
 
-#include <plat/vmalloc.h>
+#define VMALLOC_END		0xEC800000
 
 #endif /* __MACH_VMALLOC_H */
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 8c8a21d..d6a6dc0 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -582,6 +582,14 @@ struct map_desc spear13xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR13XX_SYSRAM1_BASE),
 		.length		= SZ_1M,
 		.type		= MT_MEMORY_NONCACHED
+#ifdef CONFIG_MACH_SPEAR1310
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR1310_RAS_BASE),
+		.pfn		= __phys_to_pfn(SPEAR1310_RAS_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+
+#endif
 	},
 };
 
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:08 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:08 +0530
Subject: [PATCH V2 48/69] ST SPEAr: replace readl, writel with __raw_readl,
	__raw_writel in uncompress.h
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <10581ee8e7ad68eabb4421cee448b5f7df983adb.1285933332.git.viresh.kumar@st.com>

readl also calls outer cache maintainance operations which are not available
during Linux uncompression. This patch replaces readl, writel with __raw_readl
and __raw_writel.

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/plat-spear/include/plat/uncompress.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h
index 99ba678..963aa5b 100644
--- a/arch/arm/plat-spear/include/plat/uncompress.h
+++ b/arch/arm/plat-spear/include/plat/uncompress.h
@@ -24,10 +24,10 @@ static inline void putc(int c)
 {
 	void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE;
 
-	while (readl(base + UART01x_FR) & UART01x_FR_TXFF)
+	while (__raw_readl(base + UART01x_FR) & UART01x_FR_TXFF)
 		barrier();
 
-	writel(c, base + UART01x_DR);
+	__raw_writel(c, base + UART01x_DR);
 }
 
 static inline void flush(void)
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:19 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:19 +0530
Subject: [PATCH V2 59/69] SPEAr3xx: Rework pmx_dev code to remove conflicts
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <9b53fbce9f64b51d234cf28c03e698f26cd90775.1285933332.git.viresh.kumar@st.com>

From: Ryan Mallon <ryan at bluewatersys.com>

Prefix the pmx_devs to remove naming conflicts between the three
SPEAr3xx platforms. Also make pmx_driver static to each platform and
rework the init code to pass the devices rather than export the
pmx_driver structure.

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |  129 +++++++++++++------------
 arch/arm/mach-spear3xx/spear300.c             |   40 ++++----
 arch/arm/mach-spear3xx/spear300_evb.c         |   25 ++---
 arch/arm/mach-spear3xx/spear310.c             |   28 +++---
 arch/arm/mach-spear3xx/spear310_evb.c         |   41 ++++-----
 arch/arm/mach-spear3xx/spear320.c             |   56 ++++++-----
 arch/arm/mach-spear3xx/spear320_evb.c         |   35 +++----
 arch/arm/mach-spear3xx/spear3xx.c             |   60 ++++++------
 8 files changed, 206 insertions(+), 208 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 328f8f5..cef82e8 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -70,21 +70,21 @@ void spear3xx_pmx_init_addr(struct pmx_driver *driver, unsigned int addr);
 #define PMX_TIMER_1_2_MASK	(1 << 0)
 
 /* pad mux devices */
-extern struct pmx_dev pmx_firda;
-extern struct pmx_dev pmx_i2c;
-extern struct pmx_dev pmx_ssp_cs;
-extern struct pmx_dev pmx_ssp;
-extern struct pmx_dev pmx_mii;
-extern struct pmx_dev pmx_gpio_pin0;
-extern struct pmx_dev pmx_gpio_pin1;
-extern struct pmx_dev pmx_gpio_pin2;
-extern struct pmx_dev pmx_gpio_pin3;
-extern struct pmx_dev pmx_gpio_pin4;
-extern struct pmx_dev pmx_gpio_pin5;
-extern struct pmx_dev pmx_uart0_modem;
-extern struct pmx_dev pmx_uart0;
-extern struct pmx_dev pmx_timer_3_4;
-extern struct pmx_dev pmx_timer_1_2;
+extern struct pmx_dev spear3xx_pmx_firda;
+extern struct pmx_dev spear3xx_pmx_i2c;
+extern struct pmx_dev spear3xx_pmx_ssp_cs;
+extern struct pmx_dev spear3xx_pmx_ssp;
+extern struct pmx_dev spear3xx_pmx_mii;
+extern struct pmx_dev spear3xx_pmx_gpio_pin0;
+extern struct pmx_dev spear3xx_pmx_gpio_pin1;
+extern struct pmx_dev spear3xx_pmx_gpio_pin2;
+extern struct pmx_dev spear3xx_pmx_gpio_pin3;
+extern struct pmx_dev spear3xx_pmx_gpio_pin4;
+extern struct pmx_dev spear3xx_pmx_gpio_pin5;
+extern struct pmx_dev spear3xx_pmx_uart0_modem;
+extern struct pmx_dev spear3xx_pmx_uart0;
+extern struct pmx_dev spear3xx_pmx_timer_3_4;
+extern struct pmx_dev spear3xx_pmx_timer_1_2;
 
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
 /* padmux plgpio devices */
@@ -105,8 +105,6 @@ extern struct pmx_dev pmx_plgpio_43_44_47_48;
 extern struct pmx_dev pmx_plgpio_45_46_49_50;
 #endif
 
-extern struct pmx_driver pmx_driver;
-
 /* spear300 declarations */
 #ifdef CONFIG_MACH_SPEAR300
 /* Add spear300 machine device structure declarations here */
@@ -135,27 +133,28 @@ extern struct pmx_mode camu_wlcd_mode;
 extern struct pmx_mode caml_lcd_mode;
 
 /* pad mux devices */
-extern struct pmx_dev pmx_fsmc_2_chips;
-extern struct pmx_dev pmx_fsmc_4_chips;
-extern struct pmx_dev pmx_keyboard;
-extern struct pmx_dev pmx_clcd;
-extern struct pmx_dev pmx_telecom_gpio;
-extern struct pmx_dev pmx_telecom_tdm;
-extern struct pmx_dev pmx_telecom_spi_cs_i2c_clk;
-extern struct pmx_dev pmx_telecom_camera;
-extern struct pmx_dev pmx_telecom_dac;
-extern struct pmx_dev pmx_telecom_i2s;
-extern struct pmx_dev pmx_telecom_boot_pins;
-extern struct pmx_dev pmx_telecom_sdhci_4bit;
-extern struct pmx_dev pmx_telecom_sdhci_8bit;
-extern struct pmx_dev pmx_gpio1;
+extern struct pmx_dev spear300_pmx_fsmc_2_chips;
+extern struct pmx_dev spear300_pmx_fsmc_4_chips;
+extern struct pmx_dev spear300_pmx_keyboard;
+extern struct pmx_dev spear300_pmx_clcd;
+extern struct pmx_dev spear300_pmx_telecom_gpio;
+extern struct pmx_dev spear300_pmx_telecom_tdm;
+extern struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk;
+extern struct pmx_dev spear300_pmx_telecom_camera;
+extern struct pmx_dev spear300_pmx_telecom_dac;
+extern struct pmx_dev spear300_pmx_telecom_i2s;
+extern struct pmx_dev spear300_pmx_telecom_boot_pins;
+extern struct pmx_dev spear300_pmx_telecom_sdhci_4bit;
+extern struct pmx_dev spear300_pmx_telecom_sdhci_8bit;
+extern struct pmx_dev spear300_pmx_gpio1;
 
 /* pad multiplexing support */
 #define SPEAR300_PAD_MUX_CONFIG_REG	0x99000000
 #define SPEAR300_MODE_CONFIG_REG	0x99000004
 
 /* Add spear300 machine function declarations here */
-void __init spear300_init(void);
+void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 #define SDHCI_MEM_ENB	0x1
 #define I2S_MEM_ENB	0x2
 void sdhci_i2s_mem_enable(u8 mask);
@@ -176,18 +175,19 @@ extern struct platform_device plgpio_device;
 extern struct platform_device nand_device;
 
 /* pad mux devices */
-extern struct pmx_dev pmx_emi_cs_0_1_4_5;
-extern struct pmx_dev pmx_emi_cs_2_3;
-extern struct pmx_dev pmx_uart1;
-extern struct pmx_dev pmx_uart2;
-extern struct pmx_dev pmx_uart3_4_5;
-extern struct pmx_dev pmx_fsmc;
-extern struct pmx_dev pmx_rs485_0_1;
-extern struct pmx_dev pmx_tdm0;
+extern struct pmx_dev spear310_pmx_emi_cs_0_1_4_5;
+extern struct pmx_dev spear310_pmx_emi_cs_2_3;
+extern struct pmx_dev spear310_pmx_uart1;
+extern struct pmx_dev spear310_pmx_uart2;
+extern struct pmx_dev spear310_pmx_uart3_4_5;
+extern struct pmx_dev spear310_pmx_fsmc;
+extern struct pmx_dev spear310_pmx_rs485_0_1;
+extern struct pmx_dev spear310_pmx_tdm0;
 #define SPEAR310_PAD_MUX_CONFIG_REG	0xB4000008
 
 /* Add spear310 machine function declarations here */
-void __init spear310_init(void);
+void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 
 /* spear320 declarations */
 #elif defined(CONFIG_MACH_SPEAR320)
@@ -212,35 +212,36 @@ extern struct pmx_mode auto_exp_mode;
 extern struct pmx_mode small_printers_mode;
 
 /* pad mux devices */
-extern struct pmx_dev pmx_clcd;
-extern struct pmx_dev pmx_emi;
-extern struct pmx_dev pmx_fsmc;
-extern struct pmx_dev pmx_spp;
-extern struct pmx_dev pmx_sdhci;
-extern struct pmx_dev pmx_i2s;
-extern struct pmx_dev pmx_uart1;
-extern struct pmx_dev pmx_uart1_modem;
-extern struct pmx_dev pmx_uart2;
-extern struct pmx_dev pmx_touchscreen;
-extern struct pmx_dev pmx_can;
-extern struct pmx_dev pmx_sdhci_led;
-extern struct pmx_dev pmx_pwm0;
-extern struct pmx_dev pmx_pwm1;
-extern struct pmx_dev pmx_pwm2;
-extern struct pmx_dev pmx_pwm3;
-extern struct pmx_dev pmx_ssp1;
-extern struct pmx_dev pmx_ssp2;
-extern struct pmx_dev pmx_mii1;
-extern struct pmx_dev pmx_smii0;
-extern struct pmx_dev pmx_smii1;
-extern struct pmx_dev pmx_i2c1;
+extern struct pmx_dev spear320_pmx_clcd;
+extern struct pmx_dev spear320_pmx_emi;
+extern struct pmx_dev spear320_pmx_fsmc;
+extern struct pmx_dev spear320_pmx_spp;
+extern struct pmx_dev spear320_pmx_sdhci;
+extern struct pmx_dev spear320_pmx_i2s;
+extern struct pmx_dev spear320_pmx_uart1;
+extern struct pmx_dev spear320_pmx_uart1_modem;
+extern struct pmx_dev spear320_pmx_uart2;
+extern struct pmx_dev spear320_pmx_touchscreen;
+extern struct pmx_dev spear320_pmx_can;
+extern struct pmx_dev spear320_pmx_sdhci_led;
+extern struct pmx_dev spear320_pmx_pwm0;
+extern struct pmx_dev spear320_pmx_pwm1;
+extern struct pmx_dev spear320_pmx_pwm2;
+extern struct pmx_dev spear320_pmx_pwm3;
+extern struct pmx_dev spear320_pmx_ssp1;
+extern struct pmx_dev spear320_pmx_ssp2;
+extern struct pmx_dev spear320_pmx_mii1;
+extern struct pmx_dev spear320_pmx_smii0;
+extern struct pmx_dev spear320_pmx_smii1;
+extern struct pmx_dev spear320_pmx_i2c1;
 
 /* pad multiplexing support */
 #define SPEAR320_PAD_MUX_CONFIG_REG	0xB300000C
 #define SPEAR320_MODE_CONFIG_REG	0xB3000010
 
 /* Add spear320 machine function declarations here */
-void __init spear320_init(void);
+void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 
 /* Add misc structure declarations here */
 extern struct clcd_board clcd_plat_data;
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index b041427..3c040f0 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -131,7 +131,7 @@ static struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_fsmc_2_chips = {
+struct pmx_dev spear300_pmx_fsmc_2_chips = {
 	.name = "fsmc_2_chips",
 	.modes = pmx_fsmc_2_chips_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_2_chips_modes),
@@ -154,7 +154,7 @@ static struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_fsmc_4_chips = {
+struct pmx_dev spear300_pmx_fsmc_4_chips = {
 	.name = "fsmc_4_chips",
 	.modes = pmx_fsmc_4_chips_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_4_chips_modes),
@@ -179,7 +179,7 @@ static struct pmx_dev_mode pmx_keyboard_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_keyboard = {
+struct pmx_dev spear300_pmx_keyboard = {
 	.name = "keyboard",
 	.modes = pmx_keyboard_modes,
 	.mode_count = ARRAY_SIZE(pmx_keyboard_modes),
@@ -213,7 +213,7 @@ static struct pmx_dev_mode pmx_clcd_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_clcd = {
+struct pmx_dev spear300_pmx_clcd = {
 	.name = "clcd",
 	.modes = pmx_clcd_modes,
 	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
@@ -280,7 +280,7 @@ static struct pmx_dev_mode pmx_telecom_gpio_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_gpio = {
+struct pmx_dev spear300_pmx_telecom_gpio = {
 	.name = "telecom_gpio",
 	.modes = pmx_telecom_gpio_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_gpio_modes),
@@ -306,7 +306,7 @@ static struct pmx_dev_mode pmx_telecom_tdm_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_tdm = {
+struct pmx_dev spear300_pmx_telecom_tdm = {
 	.name = "telecom_tdm",
 	.modes = pmx_telecom_tdm_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_tdm_modes),
@@ -331,7 +331,7 @@ static struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_spi_cs_i2c_clk = {
+struct pmx_dev spear300_pmx_telecom_spi_cs_i2c_clk = {
 	.name = "telecom_spi_cs_i2c_clk",
 	.modes = pmx_telecom_spi_cs_i2c_clk_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_spi_cs_i2c_clk_modes),
@@ -363,7 +363,7 @@ static struct pmx_dev_mode pmx_telecom_camera_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_camera = {
+struct pmx_dev spear300_pmx_telecom_camera = {
 	.name = "telecom_camera",
 	.modes = pmx_telecom_camera_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_camera_modes),
@@ -386,7 +386,7 @@ static struct pmx_dev_mode pmx_telecom_dac_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_dac = {
+struct pmx_dev spear300_pmx_telecom_dac = {
 	.name = "telecom_dac",
 	.modes = pmx_telecom_dac_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_dac_modes),
@@ -411,7 +411,7 @@ static struct pmx_dev_mode pmx_telecom_i2s_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_i2s = {
+struct pmx_dev spear300_pmx_telecom_i2s = {
 	.name = "telecom_i2s",
 	.modes = pmx_telecom_i2s_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_i2s_modes),
@@ -434,7 +434,7 @@ static struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_boot_pins = {
+struct pmx_dev spear300_pmx_telecom_boot_pins = {
 	.name = "telecom_boot_pins",
 	.modes = pmx_telecom_boot_pins_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_boot_pins_modes),
@@ -462,7 +462,7 @@ static struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdhci_4bit = {
+struct pmx_dev spear300_pmx_telecom_sdhci_4bit = {
 	.name = "telecom_sdhci_4bit",
 	.modes = pmx_telecom_sdhci_4bit_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
@@ -489,7 +489,7 @@ static struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdhci_8bit = {
+struct pmx_dev spear300_pmx_telecom_sdhci_8bit = {
 	.name = "telecom_sdhci_8bit",
 	.modes = pmx_telecom_sdhci_8bit_modes,
 	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
@@ -512,14 +512,14 @@ static struct pmx_dev_mode pmx_gpio1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio1 = {
+struct pmx_dev spear300_pmx_gpio1 = {
 	.name = "arm gpio1",
 	.modes = pmx_gpio1_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio1_modes),
 };
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver = {
+static struct pmx_driver pmx_driver = {
 	.mode_reg = {.address = SPEAR300_MODE_CONFIG_REG, .mask = 0x0000000f},
 };
 
@@ -773,7 +773,8 @@ void sdhci_i2s_mem_enable(u8 mask)
 }
 
 /* spear300 routines */
-void __init spear300_init(void)
+void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
 	int ret = 0;
 
@@ -788,10 +789,13 @@ void __init spear300_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ\n");
 	}
 
+	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
 	/* This fixes addresses of all pmx devices for spear300 */
 	spear3xx_pmx_init_addr(&pmx_driver, SPEAR300_PAD_MUX_CONFIG_REG);
-
-	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
 		pr_err("padmux: registeration failed. err no: %d\n", ret);
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 2bcb55f..0adf9f7 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -29,17 +29,17 @@
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
-	&pmx_i2c,
-	&pmx_ssp_cs,
-	&pmx_ssp,
-	&pmx_mii,
-	&pmx_uart0,
+	&spear3xx_pmx_i2c,
+	&spear3xx_pmx_ssp_cs,
+	&spear3xx_pmx_ssp,
+	&spear3xx_pmx_mii,
+	&spear3xx_pmx_uart0,
 
 	/* spear300 specific devices */
-	&pmx_fsmc_2_chips,
-	&pmx_clcd,
-	&pmx_telecom_sdhci_4bit,
-	&pmx_gpio1,
+	&spear300_pmx_fsmc_2_chips,
+	&spear300_pmx_clcd,
+	&spear300_pmx_telecom_sdhci_4bit,
+	&spear300_pmx_gpio1,
 };
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -113,11 +113,6 @@ static void __init spear300_evb_init(void)
 {
 	unsigned int i;
 
-	/* padmux initialization, must be done before spear300_init */
-	pmx_driver.mode = &photo_frame_mode;
-	pmx_driver.devs = pmx_devs;
-	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-
 	/* set keyboard plat data */
 	kbd_set_plat_data(&kbd_device, &kbd_data);
 
@@ -132,7 +127,7 @@ static void __init spear300_evb_init(void)
 	sdhci_i2s_mem_enable(SDHCI_MEM_ENB);
 
 	/* call spear300 machine init function */
-	spear300_init();
+	spear300_init(&photo_frame_mode, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 6fb20c3..f25d2b4 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -38,7 +38,7 @@ static struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_emi_cs_0_1_4_5 = {
+struct pmx_dev spear310_pmx_emi_cs_0_1_4_5 = {
 	.name = "emi_cs_0_1_4_5",
 	.modes = pmx_emi_cs_0_1_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_modes),
@@ -59,7 +59,7 @@ static struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_emi_cs_2_3 = {
+struct pmx_dev spear310_pmx_emi_cs_2_3 = {
 	.name = "emi_cs_2_3",
 	.modes = pmx_emi_cs_2_3_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_cs_2_3_modes),
@@ -80,7 +80,7 @@ static struct pmx_dev_mode pmx_uart1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart1 = {
+struct pmx_dev spear310_pmx_uart1 = {
 	.name = "uart1",
 	.modes = pmx_uart1_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
@@ -101,7 +101,7 @@ static struct pmx_dev_mode pmx_uart2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart2 = {
+struct pmx_dev spear310_pmx_uart2 = {
 	.name = "uart2",
 	.modes = pmx_uart2_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
@@ -122,7 +122,7 @@ static struct pmx_dev_mode pmx_uart3_4_5_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart3_4_5 = {
+struct pmx_dev spear310_pmx_uart3_4_5 = {
 	.name = "uart3_4_5",
 	.modes = pmx_uart3_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart3_4_5_modes),
@@ -143,7 +143,7 @@ static struct pmx_dev_mode pmx_fsmc_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_fsmc = {
+struct pmx_dev spear310_pmx_fsmc = {
 	.name = "fsmc",
 	.modes = pmx_fsmc_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
@@ -164,7 +164,7 @@ static struct pmx_dev_mode pmx_rs485_0_1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_rs485_0_1 = {
+struct pmx_dev spear310_pmx_rs485_0_1 = {
 	.name = "rs485_0_1",
 	.modes = pmx_rs485_0_1_modes,
 	.mode_count = ARRAY_SIZE(pmx_rs485_0_1_modes),
@@ -185,14 +185,14 @@ static struct pmx_dev_mode pmx_tdm0_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_tdm0 = {
+struct pmx_dev spear310_pmx_tdm0 = {
 	.name = "tdm0",
 	.modes = pmx_tdm0_modes,
 	.mode_count = ARRAY_SIZE(pmx_tdm0_modes),
 };
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver;
+static struct pmx_driver pmx_driver;
 
 /* Add spear310 specific devices here */
 /* uart1 device registeration */
@@ -479,7 +479,8 @@ static struct spear_shirq shirq_intrcomm_ras = {
 };
 
 /* spear310 routines */
-void __init spear310_init(void)
+void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
 	void __iomem *base;
 	int ret = 0;
@@ -515,10 +516,13 @@ void __init spear310_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
 
+	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
 	/* This fixes addresses of all pmx devices for spear310 */
 	spear3xx_pmx_init_addr(&pmx_driver, SPEAR310_PAD_MUX_CONFIG_REG);
-
-	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
 		pr_err("padmux: registeration failed. err no: %d\n", ret);
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 49aca18..953a9ea 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -46,25 +46,25 @@ static struct resource emi_nor_resources[] = {
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
-	&pmx_i2c,
-	&pmx_ssp,
-	&pmx_gpio_pin0,
-	&pmx_gpio_pin1,
-	&pmx_gpio_pin2,
-	&pmx_gpio_pin3,
-	&pmx_gpio_pin4,
-	&pmx_gpio_pin5,
-	&pmx_uart0,
+	&spear3xx_pmx_i2c,
+	&spear3xx_pmx_ssp,
+	&spear3xx_pmx_gpio_pin0,
+	&spear3xx_pmx_gpio_pin1,
+	&spear3xx_pmx_gpio_pin2,
+	&spear3xx_pmx_gpio_pin3,
+	&spear3xx_pmx_gpio_pin4,
+	&spear3xx_pmx_gpio_pin5,
+	&spear3xx_pmx_uart0,
 
 	/* spear310 specific devices */
-	&pmx_emi_cs_0_1_4_5,
-	&pmx_emi_cs_2_3,
-	&pmx_uart1,
-	&pmx_uart2,
-	&pmx_uart3_4_5,
-	&pmx_fsmc,
-	&pmx_rs485_0_1,
-	&pmx_tdm0,
+	&spear310_pmx_emi_cs_0_1_4_5,
+	&spear310_pmx_emi_cs_2_3,
+	&spear310_pmx_uart1,
+	&spear310_pmx_uart2,
+	&spear310_pmx_uart3_4_5,
+	&spear310_pmx_fsmc,
+	&spear310_pmx_rs485_0_1,
+	&spear310_pmx_tdm0,
 };
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -131,17 +131,12 @@ static void __init spear310_evb_init(void)
 {
 	unsigned int i;
 
-	/* padmux initialization, must be done before spear310_init */
-	pmx_driver.mode = NULL;
-	pmx_driver.devs = pmx_devs;
-	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-
 	/* set nand device's plat data */
 	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
 			FSMC_NAND_BW8);
 
 	/* call spear310 machine init function */
-	spear310_init();
+	spear310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 03d3486..bcd76e4 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -71,7 +71,7 @@ static struct pmx_dev_mode pmx_clcd_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_clcd = {
+struct pmx_dev spear320_pmx_clcd = {
 	.name = "clcd",
 	.modes = pmx_clcd_modes,
 	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
@@ -93,7 +93,7 @@ static struct pmx_dev_mode pmx_emi_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_emi = {
+struct pmx_dev spear320_pmx_emi = {
 	.name = "emi",
 	.modes = pmx_emi_modes,
 	.mode_count = ARRAY_SIZE(pmx_emi_modes),
@@ -115,7 +115,7 @@ static struct pmx_dev_mode pmx_fsmc_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_fsmc = {
+struct pmx_dev spear320_pmx_fsmc = {
 	.name = "fsmc",
 	.modes = pmx_fsmc_modes,
 	.mode_count = ARRAY_SIZE(pmx_fsmc_modes),
@@ -137,7 +137,7 @@ static struct pmx_dev_mode pmx_spp_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_spp = {
+struct pmx_dev spear320_pmx_spp = {
 	.name = "spp",
 	.modes = pmx_spp_modes,
 	.mode_count = ARRAY_SIZE(pmx_spp_modes),
@@ -160,7 +160,7 @@ static struct pmx_dev_mode pmx_sdhci_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_sdhci = {
+struct pmx_dev spear320_pmx_sdhci = {
 	.name = "sdhci",
 	.modes = pmx_sdhci_modes,
 	.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
@@ -182,7 +182,7 @@ static struct pmx_dev_mode pmx_i2s_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_i2s = {
+struct pmx_dev spear320_pmx_i2s = {
 	.name = "i2s",
 	.modes = pmx_i2s_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2s_modes),
@@ -204,7 +204,7 @@ static struct pmx_dev_mode pmx_uart1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart1 = {
+struct pmx_dev spear320_pmx_uart1 = {
 	.name = "uart1",
 	.modes = pmx_uart1_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
@@ -239,7 +239,7 @@ static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart1_modem = {
+struct pmx_dev spear320_pmx_uart1_modem = {
 	.name = "uart1_modem",
 	.modes = pmx_uart1_modem_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
@@ -261,7 +261,7 @@ static struct pmx_dev_mode pmx_uart2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart2 = {
+struct pmx_dev spear320_pmx_uart2 = {
 	.name = "uart2",
 	.modes = pmx_uart2_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
@@ -283,7 +283,7 @@ static struct pmx_dev_mode pmx_touchscreen_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_touchscreen = {
+struct pmx_dev spear320_pmx_touchscreen = {
 	.name = "touchscreen",
 	.modes = pmx_touchscreen_modes,
 	.mode_count = ARRAY_SIZE(pmx_touchscreen_modes),
@@ -306,7 +306,7 @@ static struct pmx_dev_mode pmx_can_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_can = {
+struct pmx_dev spear320_pmx_can = {
 	.name = "can",
 	.modes = pmx_can_modes,
 	.mode_count = ARRAY_SIZE(pmx_can_modes),
@@ -328,7 +328,7 @@ static struct pmx_dev_mode pmx_sdhci_led_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_sdhci_led = {
+struct pmx_dev spear320_pmx_sdhci_led = {
 	.name = "sdhci_led",
 	.modes = pmx_sdhci_led_modes,
 	.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
@@ -361,7 +361,7 @@ static struct pmx_dev_mode pmx_pwm0_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_pwm0 = {
+struct pmx_dev spear320_pmx_pwm0 = {
 	.name = "pwm0",
 	.modes = pmx_pwm0_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm0_modes),
@@ -394,7 +394,7 @@ static struct pmx_dev_mode pmx_pwm1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_pwm1 = {
+struct pmx_dev spear320_pmx_pwm1 = {
 	.name = "pwm1",
 	.modes = pmx_pwm1_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm1_modes),
@@ -427,7 +427,7 @@ static struct pmx_dev_mode pmx_pwm2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_pwm2 = {
+struct pmx_dev spear320_pmx_pwm2 = {
 	.name = "pwm2",
 	.modes = pmx_pwm2_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm2_modes),
@@ -449,7 +449,7 @@ static struct pmx_dev_mode pmx_pwm3_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_pwm3 = {
+struct pmx_dev spear320_pmx_pwm3 = {
 	.name = "pwm3",
 	.modes = pmx_pwm3_modes,
 	.mode_count = ARRAY_SIZE(pmx_pwm3_modes),
@@ -471,7 +471,7 @@ static struct pmx_dev_mode pmx_ssp1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_ssp1 = {
+struct pmx_dev spear320_pmx_ssp1 = {
 	.name = "ssp1",
 	.modes = pmx_ssp1_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp1_modes),
@@ -493,7 +493,7 @@ static struct pmx_dev_mode pmx_ssp2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_ssp2 = {
+struct pmx_dev spear320_pmx_ssp2 = {
 	.name = "ssp2",
 	.modes = pmx_ssp2_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp2_modes),
@@ -515,7 +515,7 @@ static struct pmx_dev_mode pmx_mii1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_mii1 = {
+struct pmx_dev spear320_pmx_mii1 = {
 	.name = "mii1",
 	.modes = pmx_mii1_modes,
 	.mode_count = ARRAY_SIZE(pmx_mii1_modes),
@@ -537,7 +537,7 @@ static struct pmx_dev_mode pmx_smii0_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_smii0 = {
+struct pmx_dev spear320_pmx_smii0 = {
 	.name = "smii0",
 	.modes = pmx_smii0_modes,
 	.mode_count = ARRAY_SIZE(pmx_smii0_modes),
@@ -559,7 +559,7 @@ static struct pmx_dev_mode pmx_smii1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_smii1 = {
+struct pmx_dev spear320_pmx_smii1 = {
 	.name = "smii1",
 	.modes = pmx_smii1_modes,
 	.mode_count = ARRAY_SIZE(pmx_smii1_modes),
@@ -581,14 +581,14 @@ static struct pmx_dev_mode pmx_i2c1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_i2c1 = {
+struct pmx_dev spear320_pmx_i2c1 = {
 	.name = "i2c1",
 	.modes = pmx_i2c1_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2c1_modes),
 };
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver = {
+static struct pmx_driver pmx_driver = {
 	.mode_reg = {.address = SPEAR320_MODE_CONFIG_REG, .mask = 0x00000007},
 };
 
@@ -959,7 +959,8 @@ static struct spear_shirq shirq_intrcomm_ras = {
 };
 
 /* spear320 routines */
-void __init spear320_init(void)
+void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
 	void __iomem *base;
 	int ret = 0;
@@ -989,10 +990,13 @@ void __init spear320_init(void)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
 
+	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
 	/* This fixes addresses of all pmx devices for spear320 */
 	spear3xx_pmx_init_addr(&pmx_driver, SPEAR320_PAD_MUX_CONFIG_REG);
-
-	/* pmx initialization */
 	ret = pmx_register(&pmx_driver);
 	if (ret)
 		pr_err("padmux: registeration failed. err no: %d\n", ret);
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 04361fc..eff4fb3 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -47,22 +47,22 @@ static struct resource emi_nor_resources[] = {
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
-	&pmx_i2c,
-	&pmx_ssp,
-	&pmx_mii,
-	&pmx_uart0,
+	&spear3xx_pmx_i2c,
+	&spear3xx_pmx_ssp,
+	&spear3xx_pmx_mii,
+	&spear3xx_pmx_uart0,
 
 	/* spear320 specific devices */
-	&pmx_fsmc,
-	&pmx_sdhci,
-	&pmx_i2s,
-	&pmx_uart1,
-	&pmx_uart2,
-	&pmx_can,
-	&pmx_pwm0,
-	&pmx_pwm1,
-	&pmx_pwm2,
-	&pmx_mii1,
+	&spear320_pmx_fsmc,
+	&spear320_pmx_sdhci,
+	&spear320_pmx_i2s,
+	&spear320_pmx_uart1,
+	&spear320_pmx_uart2,
+	&spear320_pmx_can,
+	&spear320_pmx_pwm0,
+	&spear320_pmx_pwm1,
+	&spear320_pmx_pwm2,
+	&spear320_pmx_mii1,
 };
 
 static struct amba_device *amba_devs[] __initdata = {
@@ -117,17 +117,12 @@ static void __init spear320_evb_init(void)
 	/* set sdhci device platform data */
 	sdhci_set_plat_data(&sdhci_device, &sdhci_plat_data);
 
-	/* padmux initialization, must be done before spear320_init */
-	pmx_driver.mode = &auto_net_mii_mode;
-	pmx_driver.devs = pmx_devs;
-	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-
 	/* set nand device's plat data */
 	fsmc_nand_set_plat_data(&nand_device, NULL, 0, NAND_SKIP_BBTSCAN,
 			FSMC_NAND_BW8);
 
 	/* call spear320 machine init function */
-	spear320_init();
+	spear320_init(&auto_net_mii_mode, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* initialize serial nor related data in smi plat data */
 	smi_init_board_info(&smi_device);
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 2765d32..8c00c2b 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -310,7 +310,7 @@ static struct pmx_dev_mode pmx_firda_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_firda = {
+struct pmx_dev spear3xx_pmx_firda = {
 	.name = "firda",
 	.modes = pmx_firda_modes,
 	.mode_count = ARRAY_SIZE(pmx_firda_modes),
@@ -332,7 +332,7 @@ static struct pmx_dev_mode pmx_i2c_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_i2c = {
+struct pmx_dev spear3xx_pmx_i2c = {
 	.name = "i2c",
 	.modes = pmx_i2c_modes,
 	.mode_count = ARRAY_SIZE(pmx_i2c_modes),
@@ -354,7 +354,7 @@ static struct pmx_dev_mode pmx_ssp_cs_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_ssp_cs = {
+struct pmx_dev spear3xx_pmx_ssp_cs = {
 	.name = "ssp_chip_selects",
 	.modes = pmx_ssp_cs_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp_cs_modes),
@@ -376,7 +376,7 @@ static struct pmx_dev_mode pmx_ssp_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_ssp = {
+struct pmx_dev spear3xx_pmx_ssp = {
 	.name = "ssp",
 	.modes = pmx_ssp_modes,
 	.mode_count = ARRAY_SIZE(pmx_ssp_modes),
@@ -398,7 +398,7 @@ static struct pmx_dev_mode pmx_mii_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_mii = {
+struct pmx_dev spear3xx_pmx_mii = {
 	.name = "mii",
 	.modes = pmx_mii_modes,
 	.mode_count = ARRAY_SIZE(pmx_mii_modes),
@@ -420,7 +420,7 @@ static struct pmx_dev_mode pmx_gpio_pin0_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin0 = {
+struct pmx_dev spear3xx_pmx_gpio_pin0 = {
 	.name = "gpio_pin0",
 	.modes = pmx_gpio_pin0_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin0_modes),
@@ -442,7 +442,7 @@ static struct pmx_dev_mode pmx_gpio_pin1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin1 = {
+struct pmx_dev spear3xx_pmx_gpio_pin1 = {
 	.name = "gpio_pin1",
 	.modes = pmx_gpio_pin1_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin1_modes),
@@ -464,7 +464,7 @@ static struct pmx_dev_mode pmx_gpio_pin2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin2 = {
+struct pmx_dev spear3xx_pmx_gpio_pin2 = {
 	.name = "gpio_pin2",
 	.modes = pmx_gpio_pin2_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin2_modes),
@@ -486,7 +486,7 @@ static struct pmx_dev_mode pmx_gpio_pin3_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin3 = {
+struct pmx_dev spear3xx_pmx_gpio_pin3 = {
 	.name = "gpio_pin3",
 	.modes = pmx_gpio_pin3_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin3_modes),
@@ -508,7 +508,7 @@ static struct pmx_dev_mode pmx_gpio_pin4_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin4 = {
+struct pmx_dev spear3xx_pmx_gpio_pin4 = {
 	.name = "gpio_pin4",
 	.modes = pmx_gpio_pin4_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin4_modes),
@@ -530,7 +530,7 @@ static struct pmx_dev_mode pmx_gpio_pin5_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_gpio_pin5 = {
+struct pmx_dev spear3xx_pmx_gpio_pin5 = {
 	.name = "gpio_pin5",
 	.modes = pmx_gpio_pin5_modes,
 	.mode_count = ARRAY_SIZE(pmx_gpio_pin5_modes),
@@ -552,7 +552,7 @@ static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart0_modem = {
+struct pmx_dev spear3xx_pmx_uart0_modem = {
 	.name = "uart0_modem",
 	.modes = pmx_uart0_modem_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
@@ -574,7 +574,7 @@ static struct pmx_dev_mode pmx_uart0_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_uart0 = {
+struct pmx_dev spear3xx_pmx_uart0 = {
 	.name = "uart0",
 	.modes = pmx_uart0_modes,
 	.mode_count = ARRAY_SIZE(pmx_uart0_modes),
@@ -596,7 +596,7 @@ static struct pmx_dev_mode pmx_timer_3_4_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_timer_3_4 = {
+struct pmx_dev spear3xx_pmx_timer_3_4 = {
 	.name = "timer_3_4",
 	.modes = pmx_timer_3_4_modes,
 	.mode_count = ARRAY_SIZE(pmx_timer_3_4_modes),
@@ -618,7 +618,7 @@ static struct pmx_dev_mode pmx_timer_1_2_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_timer_1_2 = {
+struct pmx_dev spear3xx_pmx_timer_1_2 = {
 	.name = "timer_1_2",
 	.modes = pmx_timer_1_2_modes,
 	.mode_count = ARRAY_SIZE(pmx_timer_1_2_modes),
@@ -641,7 +641,7 @@ static struct pmx_dev_mode pmx_plgpio_0_1_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_0_1 = {
+struct pmx_dev spear3xx_pmx_plgpio_0_1 = {
 	.name = "plgpio 0 and 1",
 	.modes = pmx_plgpio_0_1_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_0_1_modes),
@@ -663,7 +663,7 @@ static struct pmx_dev_mode pmx_plgpio_2_3_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_2_3 = {
+struct pmx_dev spear3xx_pmx_plgpio_2_3 = {
 	.name = "plgpio 2 and 3",
 	.modes = pmx_plgpio_2_3_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_2_3_modes),
@@ -685,7 +685,7 @@ static struct pmx_dev_mode pmx_plgpio_4_5_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_4_5 = {
+struct pmx_dev spear3xx_pmx_plgpio_4_5 = {
 	.name = "plgpio 4 and 5",
 	.modes = pmx_plgpio_4_5_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_4_5_modes),
@@ -707,7 +707,7 @@ static struct pmx_dev_mode pmx_plgpio_6_9_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_6_9 = {
+struct pmx_dev spear3xx_pmx_plgpio_6_9 = {
 	.name = "plgpio 6 to 9",
 	.modes = pmx_plgpio_6_9_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_6_9_modes),
@@ -729,7 +729,7 @@ static struct pmx_dev_mode pmx_plgpio_10_27_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_10_27 = {
+struct pmx_dev spear3xx_pmx_plgpio_10_27 = {
 	.name = "plgpio 10 to 27",
 	.modes = pmx_plgpio_10_27_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_10_27_modes),
@@ -751,7 +751,7 @@ static struct pmx_dev_mode pmx_plgpio_28_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_28 = {
+struct pmx_dev spear3xx_pmx_plgpio_28 = {
 	.name = "plgpio 28",
 	.modes = pmx_plgpio_28_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_28_modes),
@@ -773,7 +773,7 @@ static struct pmx_dev_mode pmx_plgpio_29_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_29 = {
+struct pmx_dev spear3xx_pmx_plgpio_29 = {
 	.name = "plgpio 29",
 	.modes = pmx_plgpio_29_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_29_modes),
@@ -795,7 +795,7 @@ static struct pmx_dev_mode pmx_plgpio_30_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_30 = {
+struct pmx_dev spear3xx_pmx_plgpio_30 = {
 	.name = "plgpio 30",
 	.modes = pmx_plgpio_30_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_30_modes),
@@ -817,7 +817,7 @@ static struct pmx_dev_mode pmx_plgpio_31_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_31 = {
+struct pmx_dev spear3xx_pmx_plgpio_31 = {
 	.name = "plgpio 31",
 	.modes = pmx_plgpio_31_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_31_modes),
@@ -839,7 +839,7 @@ static struct pmx_dev_mode pmx_plgpio_32_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_32 = {
+struct pmx_dev spear3xx_pmx_plgpio_32 = {
 	.name = "plgpio 32",
 	.modes = pmx_plgpio_32_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_32_modes),
@@ -861,7 +861,7 @@ static struct pmx_dev_mode pmx_plgpio_33_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_33 = {
+struct pmx_dev spear3xx_pmx_plgpio_33 = {
 	.name = "plgpio 33",
 	.modes = pmx_plgpio_33_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_33_modes),
@@ -883,7 +883,7 @@ static struct pmx_dev_mode pmx_plgpio_34_36_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_34_36 = {
+struct pmx_dev spear3xx_pmx_plgpio_34_36 = {
 	.name = "plgpio 34 to 36",
 	.modes = pmx_plgpio_34_36_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_34_36_modes),
@@ -905,7 +905,7 @@ static struct pmx_dev_mode pmx_plgpio_37_42_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_37_42 = {
+struct pmx_dev spear3xx_pmx_plgpio_37_42 = {
 	.name = "plgpio 37 to 42",
 	.modes = pmx_plgpio_37_42_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_37_42_modes),
@@ -927,7 +927,7 @@ static struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_43_44_47_48 = {
+struct pmx_dev spear3xx_pmx_plgpio_43_44_47_48 = {
 	.name = "plgpio 43, 44, 47 and 48",
 	.modes = pmx_plgpio_43_44_47_48_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_43_44_47_48_modes),
@@ -949,7 +949,7 @@ static struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_plgpio_45_46_49_50 = {
+struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50 = {
 	.name = "plgpio 45, 46, 49 and 50",
 	.modes = pmx_plgpio_45_46_49_50_modes,
 	.mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:21 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:21 +0530
Subject: [PATCH V2 61/69] SPEAr3xx: Replace defconfigs with single unified
	defconfig
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <753e3ba7b912827f53554165d8a7d6e6c3c30610.1285933332.git.viresh.kumar@st.com>

From: Ryan Mallon <ryan at bluewatersys.com>

We only need one defconfig for SPEAr3xx now since we can build all
three boards into one kernel.

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/configs/spear310_defconfig                |   52 --------------------
 arch/arm/configs/spear320_defconfig                |   52 --------------------
 .../{spear300_defconfig => spear3xx_defconfig}     |    4 +-
 3 files changed, 3 insertions(+), 105 deletions(-)
 delete mode 100644 arch/arm/configs/spear310_defconfig
 delete mode 100644 arch/arm/configs/spear320_defconfig
 rename arch/arm/configs/{spear300_defconfig => spear3xx_defconfig} (93%)

diff --git a/arch/arm/configs/spear310_defconfig b/arch/arm/configs/spear310_defconfig
deleted file mode 100644
index 824e444..0000000
--- a/arch/arm/configs/spear310_defconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PLAT_SPEAR=y
-CONFIG_MACH_SPEAR310=y
-CONFIG_BINFMT_MISC=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_INPUT_FF_MEMLESS=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_AMBA_PL011=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=8192
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PL061=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-CONFIG_TMPFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/spear320_defconfig b/arch/arm/configs/spear320_defconfig
deleted file mode 100644
index 842f7f3..0000000
--- a/arch/arm/configs/spear320_defconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_PLAT_SPEAR=y
-CONFIG_MACH_SPEAR320=y
-CONFIG_BINFMT_MISC=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_INPUT_FF_MEMLESS=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_AMBA_PL011=y
-CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=8192
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_PL061=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
-CONFIG_TMPFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/spear300_defconfig b/arch/arm/configs/spear3xx_defconfig
similarity index 93%
rename from arch/arm/configs/spear300_defconfig
rename to arch/arm/configs/spear3xx_defconfig
index cf29f3e..fea7e1f 100644
--- a/arch/arm/configs/spear300_defconfig
+++ b/arch/arm/configs/spear3xx_defconfig
@@ -7,6 +7,9 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
+CONFIG_BOARD_SPEAR300_EVB=y
+CONFIG_BOARD_SPEAR310_EVB=y
+CONFIG_BOARD_SPEAR320_EVB=y
 CONFIG_BINFMT_MISC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
@@ -24,7 +27,6 @@ CONFIG_MAX_RAW_DEVS=8192
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:26 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:26 +0530
Subject: [PATCH V2 66/69] ST SPEAr13xx: Pass default padmux settings as
	parameter to spear13**_init routine
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <8f1014d21b888fac4aea1778c1032e5d02079329.1285933332.git.viresh.kumar@st.com>

This patch makes pmx_driver static to spear1300.c and spear1310.c, also now
default setting of padmux are sent to spear1300_init and spear1310_init routines

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    8 ++++----
 arch/arm/mach-spear13xx/spear1300.c            |    9 +++++++--
 arch/arm/mach-spear13xx/spear1300_evb.c        |    7 +------
 arch/arm/mach-spear13xx/spear1310.c            |    9 +++++++--
 arch/arm/mach-spear13xx/spear1310_evb.c        |    7 +------
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index f619b70..e005936 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -220,8 +220,6 @@ extern struct pmx_dev pmx_uart1_modem;
 #define SPEAR_GPT0_CHAN0_IRQ	IRQ_GPT0_TMR0
 #define SPEAR_GPT0_CHAN1_IRQ	IRQ_GPT0_TMR1
 
-extern struct pmx_driver pmx_driver;
-
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
 extern struct amba_device spear13xx_ssp_device;
@@ -255,7 +253,8 @@ void spear13xx_secondary_startup(void);
 /* spear1300 declarations */
 #ifdef CONFIG_MACH_SPEAR1300
 /* Add spear1300 machine function declarations here */
-void __init spear1300_init(void);
+void __init spear1300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 
 #endif /* CONFIG_MACH_SPEAR1300 */
 
@@ -266,7 +265,8 @@ extern struct platform_device spear1310_can0_device;
 extern struct platform_device spear1310_can1_device;
 
 /* Add spear1310 machine function declarations here */
-void __init spear1310_init(void);
+void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 
 #endif /* CONFIG_MACH_SPEAR1310 */
 
diff --git a/arch/arm/mach-spear13xx/spear1300.c b/arch/arm/mach-spear13xx/spear1300.c
index 28822a3..b10f7a0 100644
--- a/arch/arm/mach-spear13xx/spear1300.c
+++ b/arch/arm/mach-spear13xx/spear1300.c
@@ -15,11 +15,12 @@
 #include <mach/spear.h>
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver;
+static struct pmx_driver pmx_driver;
 
 /* Add spear1300 specific devices here */
 
-void __init spear1300_init(void)
+void __init spear1300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
 	int ret;
 
@@ -27,6 +28,10 @@ void __init spear1300_init(void)
 	spear13xx_init();
 
 	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
 	ret = pmx_register(&pmx_driver);
 	if (ret)
 		pr_err("padmux: registeration failed. err no: %d\n", ret);
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index ceb3bd0..4c8365b 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -122,11 +122,6 @@ static void __init spear1300_evb_init(void)
 {
 	unsigned int i;
 
-	/* padmux initialization, must be done before spear1300_init */
-	pmx_driver.mode = NULL;
-	pmx_driver.devs = pmx_devs;
-	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-
 	/* set keyboard plat data */
 	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
 
@@ -136,7 +131,7 @@ static void __init spear1300_evb_init(void)
 	nand_mach_init(FSMC_NAND_BW8);
 
 	/* call spear1300 machine init function */
-	spear1300_init();
+	spear1300_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 39ea491..375f5b2 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -17,7 +17,7 @@
 #include <mach/hardware.h>
 
 /* pmx driver structure */
-struct pmx_driver pmx_driver;
+static struct pmx_driver pmx_driver;
 
 /* Pad multiplexing for uart1_modem device */
 static struct pmx_mux_reg pmx_uart1_modem_mux[] = {
@@ -393,7 +393,8 @@ struct platform_device spear1310_can1_device = {
 	.resource = can1_resources,
 };
 
-void __init spear1310_init(void)
+void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
 	int ret;
 
@@ -401,6 +402,10 @@ void __init spear1310_init(void)
 	spear13xx_init();
 
 	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
 	ret = pmx_register(&pmx_driver);
 	if (ret)
 		pr_err("padmux: registeration failed. err no: %d\n", ret);
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index c4b83b2..a263b40 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -133,11 +133,6 @@ static void __init spear1310_evb_init(void)
 {
 	unsigned int i;
 
-	/* padmux initialization, must be done before spear1300_init */
-	pmx_driver.mode = NULL;
-	pmx_driver.devs = pmx_devs;
-	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-
 	/* set keyboard plat data */
 	kbd_set_plat_data(&spear13xx_kbd_device, &kbd_data);
 
@@ -147,7 +142,7 @@ static void __init spear1310_evb_init(void)
 	nand_mach_init(FSMC_NAND_BW8);
 
 	/* call spear1310 machine init function */
-	spear1310_init();
+	spear1310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:11 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:11 +0530
Subject: [PATCH V2 51/69] SPEAr: Adding and Updating Clock definitions
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <07df8f5b97e4c0ee24396873df8ec05ba6939cda.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/clock.c                  |  210 ++++++++++++++++++++-
 arch/arm/mach-spear13xx/include/mach/misc_regs.h |   19 ++
 arch/arm/mach-spear3xx/clock.c                   |    6 +-
 arch/arm/mach-spear6xx/clock.c                   |    4 +-
 4 files changed, 224 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 79942a9..75cd89c 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -355,6 +355,7 @@ static struct aux_clk_config uart_synth_config = {
 /* aux rate configuration table, in ascending order of rates */
 struct aux_rate_tbl aux_rtbl[] = {
 	/* For PLL1div2 = 500 MHz */
+	{.xscale = 2, .yscale = 21, .eq = 1}, /* 48 MHz */
 	{.xscale = 1, .yscale = 6, .eq = 1}, /* 83 MHz */
 	{.xscale = 1, .yscale = 4, .eq = 1}, /* 125 MHz */
 	{.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
@@ -369,7 +370,7 @@ static struct clk uart_synth_clk = {
 	.calc_rate = &aux_calc_rate,
 	.recalc = &aux_clk_recalc,
 	.set_rate = &aux_clk_set_rate,
-	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
 	.private_data = &uart_synth_config,
 };
 
@@ -415,7 +416,7 @@ static struct clk sdhci_synth_clk = {
 	.calc_rate = &aux_calc_rate,
 	.recalc = &aux_clk_recalc,
 	.set_rate = &aux_clk_set_rate,
-	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
 	.private_data = &sdhci_synth_config,
 };
 
@@ -441,7 +442,7 @@ static struct clk cfxd_synth_clk = {
 	.calc_rate = &aux_calc_rate,
 	.recalc = &aux_clk_recalc,
 	.set_rate = &aux_clk_set_rate,
-	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
 	.private_data = &cfxd_synth_config,
 };
 
@@ -467,7 +468,7 @@ static struct clk c3_synth_clk = {
 	.calc_rate = &aux_calc_rate,
 	.recalc = &aux_clk_recalc,
 	.set_rate = &aux_clk_set_rate,
-	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 0},
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
 	.private_data = &c3_synth_config,
 };
 
@@ -579,7 +580,7 @@ static struct pclk_sel gmac_phy_pclk_sel = {
 };
 
 /* gmac phy clock */
-static struct clk gmac_phy_clk = {
+static struct clk gmac_phy0_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk_sel = &gmac_phy_pclk_sel,
 	.pclk_sel_shift = GMAC_PHY_CLK_SHIFT,
@@ -697,8 +698,8 @@ static struct clk jpeg_clk = {
 	.recalc = &follow_parent,
 };
 
-/* gmac clock */
-static struct clk gmac_clk = {
+/* gmac clock :Fixed Part*/
+static struct clk gmac0_clk = {
 	.pclk = &ahb_clk,
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = GMAC_CLK_ENB,
@@ -839,6 +840,92 @@ static struct clk kbd_clk = {
 	.recalc = &follow_parent,
 };
 
+/* RAS CLOCKS */
+/* pll3 generated clock */
+static struct clk ras_pll3_clk = {
+	.pclk = &pll3_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = PLL3_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* pll2 generated clock */
+static struct clk ras_pll2_clk = {
+	.pclk = &pll2_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = PLL2_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* 125MHz clock generated on Tx pad */
+static struct clk ras_tx125_clk = {
+	.pclk = &gmii_txclk125_pad,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = C125_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* 30 MHz clock generated by USB PHy Pll */
+static struct clk ras_30Mhz_clk = {
+	.rate = 30000000,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = C30_CLK_ENB,
+};
+
+/* 48 MHz clock generated by USB PHy Pll */
+static struct clk ras_48Mhz_clk = {
+	.pclk = &pll5_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = C48_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* osc3 generated clock */
+static struct clk ras_osc3_clk = {
+	.pclk = &ahb_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = OSC3_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* osc2 generated clock */
+static struct clk ras_osc2_clk = {
+	.pclk = &osc2_32k_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = OSC2_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* osc1 generated clock */
+static struct clk ras_osc1_clk = {
+	.pclk = &osc1_24m_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = OSC1_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* apb generated clock */
+static struct clk ras_pclk_clk = {
+	.pclk = &apb_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = PCLK_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* ahb generated clock */
+static struct clk ras_aclk_clk = {
+	.pclk = &ahb_clk,
+	.en_reg = RAS_CLK_ENB,
+	.en_reg_bit = ACLK_CLK_ENB,
+	.recalc = &follow_parent,
+};
+
+/* External pad 50 MHz clock for phy operation */
+static struct clk ras_tx50_clk = {
+	.flags = ALWAYS_ENABLED,
+	.rate = 50000000,
+};
+
 /* spear1300 machine specific clock structures */
 #ifdef CONFIG_MACH_SPEAR1300
 
@@ -859,10 +946,92 @@ static struct clk can1_clk = {
 	.pclk = &apb_clk,
 	.recalc = &follow_parent,
 };
+
+/* gmac clocks :RAS part*/
+static struct clk gmac_ras1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_aclk_clk,
+	.recalc = &follow_parent,
+};
+
+static struct clk gmac_ras2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_aclk_clk,
+	.recalc = &follow_parent,
+};
+
+static struct clk gmac_ras3_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_aclk_clk,
+	.recalc = &follow_parent,
+};
+
+static struct clk gmac_ras4_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_aclk_clk,
+	.recalc = &follow_parent,
+};
+
+/* phy clock parent select */
+static struct pclk_info phy_pclk_info[] = {
+	{
+		.pclk = &ras_pll2_clk,
+		.pclk_val = 0x8,
+	}, {
+		.pclk = &ras_tx125_clk,
+		.pclk_val = 0x4,
+	}, {
+		.pclk = &ras_tx50_clk,
+		.pclk_val = 0x0,
+	},
+};
+
+static struct pclk_sel phy_pclk_sel = {
+	.pclk_info = phy_pclk_info,
+	.pclk_count = ARRAY_SIZE(phy_pclk_info),
+	.pclk_sel_reg = (unsigned int *)(IO_ADDRESS(SPEAR1310_RAS_CTRL_REG1)),
+	.pclk_sel_mask = SPEAR1310_PHY_CLK_MASK,
+};
+
+/* Phy 1 Clock */
+struct clk gmac_phy1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &phy_pclk_sel,
+	.pclk_sel_shift = SPEAR1310_PHY_CLK_SHIFT,
+	.recalc = &follow_parent,
+};
+
+/* Phy 2 Clock */
+static struct clk gmac_phy2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &phy_pclk_sel,
+	.pclk_sel_shift = SPEAR1310_PHY_CLK_SHIFT,
+	.recalc = &follow_parent,
+};
+
+/* Phy 3 Clock */
+static struct clk gmac_phy3_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &phy_pclk_sel,
+	.pclk_sel_shift = SPEAR1310_PHY_CLK_SHIFT,
+	.recalc = &follow_parent,
+};
+
+/* Phy 4 Clock */
+static struct clk gmac_phy4_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &phy_pclk_sel,
+	.pclk_sel_shift = SPEAR1310_PHY_CLK_SHIFT,
+	.recalc = &follow_parent,
+};
+
 #endif
 
+static struct clk dummy_apb_pclk;
+
 /* array of all spear 13xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{.con_id = "osc1_24m_clk",	.clk = &osc1_24m_clk},
 	{.con_id = "osc2_32k_clk",	.clk = &osc2_32k_clk},
@@ -896,7 +1065,20 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.con_id = "cfxd_synth_clk",		.clk = &cfxd_synth_clk},
 	{.con_id = "gmac_phy_input_clk",	.clk = &gmac_phy_input_clk},
 	{.con_id = "gmac_phy_synth_clk",	.clk = &gmac_phy_synth_clk},
-	{.con_id = "gmac_phy_clk",		.clk = &gmac_phy_clk},
+	{.dev_id = "stmmacphy.0",		.clk = &gmac_phy0_clk},
+
+	/* RAS clocks */
+	{.con_id = "ras_pll3_clk",		.clk = &ras_pll3_clk},
+	{.con_id = "ras_pll2_clk",		.clk = &ras_pll2_clk},
+	{.con_id = "ras_tx125_clk",		.clk = &ras_tx125_clk},
+	{.con_id = "ras_30Mhz_clk",		.clk = &ras_30Mhz_clk},
+	{.con_id = "ras_48Mhz_clk",		.clk = &ras_48Mhz_clk},
+	{.con_id = "ras_osc3_clk",		.clk = &ras_osc3_clk},
+	{.con_id = "ras_osc2_clk",		.clk = &ras_osc2_clk},
+	{.con_id = "ras_osc1_clk",		.clk = &ras_osc1_clk},
+	{.con_id = "ras_pclk_clk",		.clk = &ras_pclk_clk},
+	{.con_id = "ras_aclk_clk",		.clk = &ras_aclk_clk},
+	{.con_id = "ras_tx50_clk",		.clk = &ras_tx50_clk},
 
 	/* clocks having multiple parent source from above clocks */
 	{.dev_id = "clcd",		.clk = &clcd_clk},
@@ -910,12 +1092,12 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.dev_id = "smi",		.clk = &smi_clk},
 	{.con_id = "usbh.0_clk",	.clk = &uhci0_clk},
 	{.con_id = "usbh.1_clk",	.clk = &uhci1_clk},
-	{.dev_id = "usbd",		.clk = &usbd_clk},
+	{.dev_id = "designware_udc",	.clk = &usbd_clk},
 	{.dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{.dev_id = "dma0",		.clk = &dma0_clk},
 	{.dev_id = "dma1",		.clk = &dma1_clk},
 	{.dev_id = "jpeg",		.clk = &jpeg_clk},
-	{.dev_id = "gmac",		.clk = &gmac_clk},
+	{.dev_id = "stmmaceth.0",	.clk = &gmac0_clk},
 	{.dev_id = "c3",		.clk = &c3_clk},
 	{.dev_id = "pcie0",		.clk = &pcie0_clk},
 	{.dev_id = "pcie1",		.clk = &pcie1_clk},
@@ -944,6 +1126,14 @@ static struct clk_lookup spear_clk_lookups[] = {
 #ifdef CONFIG_MACH_SPEAR1310
 	{.dev_id = "spear_can.0",	.clk = &can0_clk},
 	{.dev_id = "spear_can.1",	.clk = &can1_clk},
+	{.dev_id = "stmmaceth.1",	.clk = &gmac_ras1_clk},
+	{.dev_id = "stmmaceth.2",	.clk = &gmac_ras2_clk},
+	{.dev_id = "stmmaceth.3",	.clk = &gmac_ras3_clk},
+	{.dev_id = "stmmaceth.4",	.clk = &gmac_ras4_clk},
+	{.dev_id = "stmmacphy.1",	.clk = &gmac_phy1_clk},
+	{.dev_id = "stmmacphy.2",	.clk = &gmac_phy2_clk},
+	{.dev_id = "stmmacphy.3",	.clk = &gmac_phy3_clk},
+	{.dev_id = "stmmacphy.4",	.clk = &gmac_phy4_clk},
 #endif
 };
 
diff --git a/arch/arm/mach-spear13xx/include/mach/misc_regs.h b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
index 3cfd4fc..ea6096f 100644
--- a/arch/arm/mach-spear13xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
@@ -191,6 +191,25 @@
 	#define JPEG_SOF_RST		28
 #define PERIP2_SW_RST		((unsigned int *)(MISC_BASE + 0x280))
 #define RAS_CLK_ENB		((unsigned int *)(MISC_BASE + 0x284))
+	/* RAS_CLK_ENB register masks */
+	#define ACLK_CLK_ENB		0
+	#define PCLK_CLK_ENB		1
+	#define OSC1_CLK_ENB		2
+	#define OSC2_CLK_ENB		3
+	#define OSC3_CLK_ENB		4
+	#define C48_CLK_ENB		5
+	#define C30_CLK_ENB		6
+	#define C125_CLK_ENB		7
+	#define PLL2_CLK_ENB		8
+	#define PLL3_CLK_ENB		9
+	#define PCLK0_CLK_ENB		10
+	#define PCLK1_CLK_ENB		11
+	#define PCLK2_CLK_ENB		12
+	#define PCLK3_CLK_ENB		13
+	#define SYN0_CLK_ENB		14
+	#define SYN1_CLK_ENB		15
+	#define SYN2_CLK_ENB		16
+	#define SYN3_CLK_ENB		17
 #define RAS_SW_RST		((unsigned int *)(MISC_BASE + 0x288))
 #define PLL1_SYNT		((unsigned int *)(MISC_BASE + 0x28c))
 #define I2S_CLK_CFG		((unsigned int *)(MISC_BASE + 0x290))
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 64d9cdc..814966a 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -713,7 +713,7 @@ static struct clk pwm_clk = {
 
 /* array of all spear 3xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_24m_clk",	.clk = &osc_24m_clk},
@@ -738,8 +738,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "gpt1",		.clk = &gpt1_clk},
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	/* clock derived from pll3 clk */
+	{ .dev_id = "designware_udc",   .clk = &usbd_clk},
 	{ .con_id = "usbh_clk",		.clk = &usbh_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
 	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
@@ -755,7 +755,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
 	{ .dev_id = "gpio",		.clk = &gpio_clk},
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-	{ .dev_id = "physmap-flash",	.clk = &emi_clk},
+	{ .dev_id = "emi",		.clk = &emi_clk},
 #endif
 #if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
 	defined(CONFIG_MACH_SPEAR320)
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index f1429f5..63aab69 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -685,7 +685,7 @@ static struct clk dummy_apb_pclk;
 
 /* array of all spear 6xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_30m_clk",	.clk = &osc_30m_clk},
@@ -714,9 +714,9 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	{ .dev_id = "gpt3",		.clk = &gpt3_clk},
 	/* clock derived from pll3 clk */
+	{ .dev_id = "designware_udc",	.clk = &usbd_clk},
 	{ .con_id = "usbh.0_clk",	.clk = &usbh0_clk},
 	{ .con_id = "usbh.1_clk",	.clk = &usbh1_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
 	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:03 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:03 +0530
Subject: [PATCH V2 43/69] GIC: Added dummy handlers for Power Management
	Suspend Resume
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <fa5bfc17c18f3849a7835d8b952380f17455d71d.1285933332.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri at st.com>

enable_irq_wake() has a callback for interrupt controllers.
But since gic handler did not had this call back associated, it was always
returning -ENXIO, which was breaking the existing drivers. This patch
adds dummy handlers in gic in order to avoid breaking of existing drivers.

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/common/gic.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 7dfa9a8..e816ef1 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -201,6 +201,18 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 	chip->unmask(irq);
 }
 
+#ifdef CONFIG_PM
+
+static int gic_set_wake(unsigned int irq, unsigned int on)
+{
+	return 0;
+}
+
+#else
+
+#define gic_set_wake NULL
+#endif
+
 static struct irq_chip gic_chip = {
 	.name		= "GIC",
 	.ack		= gic_ack_irq,
@@ -210,6 +222,7 @@ static struct irq_chip gic_chip = {
 #ifdef CONFIG_SMP
 	.set_affinity	= gic_set_cpu,
 #endif
+	.set_wake	= gic_set_wake,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:18 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:18 +0530
Subject: [PATCH V2 58/69] SPEAR3xx: Rename register/irq defines to remove
	naming conflicts
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <87945784c19f72c45f7fc5e70046697c2101a2b0.1285933332.git.viresh.kumar@st.com>

From: Ryan Mallon <ryan at bluewatersys.com>

Prefix register and irq defintions to remove naming conflicts between
the three SPEAr3xx platforms.

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h  |    4 +-
 arch/arm/mach-spear3xx/include/mach/gpio.h     |    3 +-
 arch/arm/mach-spear3xx/include/mach/irqs.h     |  207 ++++++++++++------------
 arch/arm/mach-spear3xx/include/mach/spear300.h |   26 ++--
 arch/arm/mach-spear3xx/include/mach/spear310.h |   44 +++---
 arch/arm/mach-spear3xx/include/mach/spear320.h |   48 +++---
 arch/arm/mach-spear3xx/spear300.c              |   73 ++++-----
 arch/arm/mach-spear3xx/spear310.c              |  108 ++++++------
 arch/arm/mach-spear3xx/spear320.c              |  158 +++++++++---------
 arch/arm/mach-spear3xx/spear3xx.c              |   25 ++--
 10 files changed, 349 insertions(+), 347 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 0412808..328f8f5 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -27,8 +27,8 @@
  * Following GPT channels will be used as clock source and clockevent
  */
 #define SPEAR_GPT0_BASE		SPEAR3XX_ML1_TMR_BASE
-#define SPEAR_GPT0_CHAN0_IRQ	IRQ_CPU_GPT1_1
-#define SPEAR_GPT0_CHAN1_IRQ	IRQ_CPU_GPT1_2
+#define SPEAR_GPT0_CHAN0_IRQ	SPEAR3XX_IRQ_CPU_GPT1_1
+#define SPEAR_GPT0_CHAN1_IRQ	SPEAR3XX_IRQ_CPU_GPT1_2
 
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device gpio_device;
diff --git a/arch/arm/mach-spear3xx/include/mach/gpio.h b/arch/arm/mach-spear3xx/include/mach/gpio.h
index e531f6d..f15248c 100644
--- a/arch/arm/mach-spear3xx/include/mach/gpio.h
+++ b/arch/arm/mach-spear3xx/include/mach/gpio.h
@@ -51,8 +51,9 @@
 #define RAS_GPIO_5		13
 #define RAS_GPIO_6		14
 #define RAS_GPIO_7		15
+#endif
 
-#elif defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
 #define PLGPIO_0		8
 #define PLGPIO_1		9
 #define PLGPIO_2		10
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index df0c1f3..6e26544 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -15,139 +15,140 @@
 #define __MACH_IRQS_H
 
 /* SPEAr3xx IRQ definitions */
-#define IRQ_HW_ACCEL_MOD_0			0
-#define IRQ_INTRCOMM_RAS_ARM			1
-#define IRQ_CPU_GPT1_1				2
-#define IRQ_CPU_GPT1_2				3
-#define IRQ_BASIC_GPT1_1			4
-#define IRQ_BASIC_GPT1_2			5
-#define IRQ_BASIC_GPT2_1			6
-#define IRQ_BASIC_GPT2_2			7
-#define IRQ_BASIC_DMA				8
-#define IRQ_BASIC_SMI				9
-#define IRQ_BASIC_RTC				10
-#define IRQ_BASIC_GPIO				11
-#define IRQ_BASIC_WDT				12
-#define IRQ_DDR_CONTROLLER			13
-#define IRQ_SYS_ERROR				14
-#define IRQ_WAKEUP_RCV				15
-#define IRQ_JPEG				16
-#define IRQ_IRDA				17
-#define IRQ_ADC					18
-#define IRQ_UART				19
-#define IRQ_SSP					20
-#define IRQ_I2C					21
-#define IRQ_MAC_1				22
-#define IRQ_MAC_2				23
-#define IRQ_USB_DEV				24
-#define IRQ_USB_H_OHCI_0			25
-#define IRQ_USB_H_EHCI_0			26
-#define IRQ_USB_H_EHCI_1			IRQ_USB_H_EHCI_0
-#define IRQ_USB_H_OHCI_1			27
-#define IRQ_GEN_RAS_1				28
-#define IRQ_GEN_RAS_2				29
-#define IRQ_GEN_RAS_3				30
-#define IRQ_HW_ACCEL_MOD_1			31
-#define IRQ_VIC_END				32
-
-#define VIRQ_START				IRQ_VIC_END
+#define SPEAR3XX_IRQ_HW_ACCEL_MOD_0		0
+#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM		1
+#define SPEAR3XX_IRQ_CPU_GPT1_1			2
+#define SPEAR3XX_IRQ_CPU_GPT1_2			3
+#define SPEAR3XX_IRQ_BASIC_GPT1_1		4
+#define SPEAR3XX_IRQ_BASIC_GPT1_2		5
+#define SPEAR3XX_IRQ_BASIC_GPT2_1		6
+#define SPEAR3XX_IRQ_BASIC_GPT2_2		7
+#define SPEAR3XX_IRQ_BASIC_DMA			8
+#define SPEAR3XX_IRQ_BASIC_SMI			9
+#define SPEAR3XX_IRQ_BASIC_RTC			10
+#define SPEAR3XX_IRQ_BASIC_GPIO			11
+#define SPEAR3XX_IRQ_BASIC_WDT			12
+#define SPEAR3XX_IRQ_DDR_CONTROLLER		13
+#define SPEAR3XX_IRQ_SYS_ERROR			14
+#define SPEAR3XX_IRQ_WAKEUP_RCV			15
+#define SPEAR3XX_IRQ_JPEG			16
+#define SPEAR3XX_IRQ_IRDA			17
+#define SPEAR3XX_IRQ_ADC			18
+#define SPEAR3XX_IRQ_UART			19
+#define SPEAR3XX_IRQ_SSP			20
+#define SPEAR3XX_IRQ_I2C			21
+#define SPEAR3XX_IRQ_MAC_1			22
+#define SPEAR3XX_IRQ_MAC_2			23
+#define SPEAR3XX_IRQ_USB_DEV			24
+#define SPEAR3XX_IRQ_USB_H_OHCI_0		25
+#define SPEAR3XX_IRQ_USB_H_EHCI_0		26
+#define SPEAR3XX_IRQ_USB_H_EHCI_1		SPEAR3XX_IRQ_USB_H_EHCI_0
+#define SPEAR3XX_IRQ_USB_H_OHCI_1		27
+#define SPEAR3XX_IRQ_GEN_RAS_1			28
+#define SPEAR3XX_IRQ_GEN_RAS_2			29
+#define SPEAR3XX_IRQ_GEN_RAS_3			30
+#define SPEAR3XX_IRQ_HW_ACCEL_MOD_1		31
+#define SPEAR3XX_IRQ_VIC_END			32
+
+#define SPEAR3XX_VIRQ_START			SPEAR3XX_IRQ_VIC_END
 
 /* SPEAr300 Virtual irq definitions */
-#ifdef CONFIG_MACH_SPEAR300
 /* IRQs sharing IRQ_GEN_RAS_1 */
-#define VIRQ_IT_PERS_S				(VIRQ_START + 0)
-#define VIRQ_IT_CHANGE_S			(VIRQ_START + 1)
-#define VIRQ_I2S				(VIRQ_START + 2)
-#define VIRQ_TDM				(VIRQ_START + 3)
-#define VIRQ_CAMERA_L				(VIRQ_START + 4)
-#define VIRQ_CAMERA_F				(VIRQ_START + 5)
-#define VIRQ_CAMERA_V				(VIRQ_START + 6)
-#define VIRQ_KEYBOARD				(VIRQ_START + 7)
-#define VIRQ_GPIO1				(VIRQ_START + 8)
+#define SPEAR300_VIRQ_IT_PERS_S			(SPEAR3XX_VIRQ_START + 0)
+#define SPEAR300_VIRQ_IT_CHANGE_S		(SPEAR3XX_VIRQ_START + 1)
+#define SPEAR300_VIRQ_I2S			(SPEAR3XX_VIRQ_START + 2)
+#define SPEAR300_VIRQ_TDM			(SPEAR3XX_VIRQ_START + 3)
+#define SPEAR300_VIRQ_CAMERA_L			(SPEAR3XX_VIRQ_START + 4)
+#define SPEAR300_VIRQ_CAMERA_F			(SPEAR3XX_VIRQ_START + 5)
+#define SPEAR300_VIRQ_CAMERA_V			(SPEAR3XX_VIRQ_START + 6)
+#define SPEAR300_VIRQ_KEYBOARD			(SPEAR3XX_VIRQ_START + 7)
+#define SPEAR300_VIRQ_GPIO1			(SPEAR3XX_VIRQ_START + 8)
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
-#define IRQ_CLCD				IRQ_GEN_RAS_3
+#define SPEAR300_IRQ_CLCD			SPEAR3XX_IRQ_GEN_RAS_3
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define IRQ_SDHCI				IRQ_INTRCOMM_RAS_ARM
-
-/* GPIO pins virtual irqs */
-#define SPEAR_GPIO_INT_BASE			(VIRQ_START + 9)
-#define SPEAR_GPIO1_INT_BASE			(SPEAR_GPIO_INT_BASE + 8)
-#define SPEAR_GPIO_INT_END			(SPEAR_GPIO1_INT_BASE + 8)
+#define SPEAR300_IRQ_SDHCI			SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
 
 /* SPEAr310 Virtual irq definitions */
-#elif defined(CONFIG_MACH_SPEAR310)
 /* IRQs sharing IRQ_GEN_RAS_1 */
-#define VIRQ_SMII0				(VIRQ_START + 0)
-#define VIRQ_SMII1				(VIRQ_START + 1)
-#define VIRQ_SMII2				(VIRQ_START + 2)
-#define VIRQ_SMII3				(VIRQ_START + 3)
-#define VIRQ_WAKEUP_SMII0			(VIRQ_START + 4)
-#define VIRQ_WAKEUP_SMII1			(VIRQ_START + 5)
-#define VIRQ_WAKEUP_SMII2			(VIRQ_START + 6)
-#define VIRQ_WAKEUP_SMII3			(VIRQ_START + 7)
+#define SPEAR310_VIRQ_SMII0			(SPEAR3XX_VIRQ_START + 0)
+#define SPEAR310_VIRQ_SMII1			(SPEAR3XX_VIRQ_START + 1)
+#define SPEAR310_VIRQ_SMII2			(SPEAR3XX_VIRQ_START + 2)
+#define SPEAR310_VIRQ_SMII3			(SPEAR3XX_VIRQ_START + 3)
+#define SPEAR310_VIRQ_WAKEUP_SMII0		(SPEAR3XX_VIRQ_START + 4)
+#define SPEAR310_VIRQ_WAKEUP_SMII1		(SPEAR3XX_VIRQ_START + 5)
+#define SPEAR310_VIRQ_WAKEUP_SMII2		(SPEAR3XX_VIRQ_START + 6)
+#define SPEAR310_VIRQ_WAKEUP_SMII3		(SPEAR3XX_VIRQ_START + 7)
 
 /* IRQs sharing IRQ_GEN_RAS_2 */
-#define VIRQ_UART1				(VIRQ_START + 8)
-#define VIRQ_UART2				(VIRQ_START + 9)
-#define VIRQ_UART3				(VIRQ_START + 10)
-#define VIRQ_UART4				(VIRQ_START + 11)
-#define VIRQ_UART5				(VIRQ_START + 12)
+#define SPEAR310_VIRQ_UART1			(SPEAR3XX_VIRQ_START + 8)
+#define SPEAR310_VIRQ_UART2			(SPEAR3XX_VIRQ_START + 9)
+#define SPEAR310_VIRQ_UART3			(SPEAR3XX_VIRQ_START + 10)
+#define SPEAR310_VIRQ_UART4			(SPEAR3XX_VIRQ_START + 11)
+#define SPEAR310_VIRQ_UART5			(SPEAR3XX_VIRQ_START + 12)
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
-#define VIRQ_EMI				(VIRQ_START + 13)
-#define VIRQ_PLGPIO				(VIRQ_START + 14)
+#define SPEAR310_VIRQ_EMI			(SPEAR3XX_VIRQ_START + 13)
+#define SPEAR310_VIRQ_PLGPIO			(SPEAR3XX_VIRQ_START + 14)
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define VIRQ_TDM_HDLC				(VIRQ_START + 15)
-#define VIRQ_RS485_0				(VIRQ_START + 16)
-#define VIRQ_RS485_1				(VIRQ_START + 17)
-
-/* GPIO pins virtual irqs */
-#define SPEAR_GPIO_INT_BASE			(VIRQ_START + 18)
+#define SPEAR310_VIRQ_TDM_HDLC			(SPEAR3XX_VIRQ_START + 15)
+#define SPEAR310_VIRQ_RS485_0			(SPEAR3XX_VIRQ_START + 16)
+#define SPEAR310_VIRQ_RS485_1			(SPEAR3XX_VIRQ_START + 17)
 
 /* SPEAr320 Virtual irq definitions */
-#else
 /* IRQs sharing IRQ_GEN_RAS_1 */
-#define VIRQ_EMI				(VIRQ_START + 0)
-#define VIRQ_CLCD				(VIRQ_START + 1)
-#define VIRQ_SPP				(VIRQ_START + 2)
+#define SPEAR320_VIRQ_EMI			(SPEAR3XX_VIRQ_START + 0)
+#define SPEAR320_VIRQ_CLCD			(SPEAR3XX_VIRQ_START + 1)
+#define SPEAR320_VIRQ_SPP			(SPEAR3XX_VIRQ_START + 2)
 
 /* IRQs sharing IRQ_GEN_RAS_2 */
-#define IRQ_SDHCI				IRQ_GEN_RAS_2
+#define SPEAR320_IRQ_SDHCI			SPEAR3XX_IRQ_GEN_RAS_2
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
-#define VIRQ_PLGPIO				(VIRQ_START + 3)
-#define VIRQ_I2S_PLAY				(VIRQ_START + 4)
-#define VIRQ_I2S_REC				(VIRQ_START + 5)
+#define SPEAR320_VIRQ_PLGPIO			(SPEAR3XX_VIRQ_START + 3)
+#define SPEAR320_VIRQ_I2S_PLAY			(SPEAR3XX_VIRQ_START + 4)
+#define SPEAR320_VIRQ_I2S_REC			(SPEAR3XX_VIRQ_START + 5)
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define VIRQ_CANU				(VIRQ_START + 6)
-#define VIRQ_CANL				(VIRQ_START + 7)
-#define VIRQ_UART1				(VIRQ_START + 8)
-#define VIRQ_UART2				(VIRQ_START + 9)
-#define VIRQ_SSP1				(VIRQ_START + 10)
-#define VIRQ_SSP2				(VIRQ_START + 11)
-#define VIRQ_SMII0				(VIRQ_START + 12)
-#define VIRQ_MII1_SMII1				(VIRQ_START + 13)
-#define VIRQ_WAKEUP_SMII0			(VIRQ_START + 14)
-#define VIRQ_WAKEUP_MII1_SMII1			(VIRQ_START + 15)
-#define VIRQ_I2C1				(VIRQ_START + 16)
-
-/* GPIO pins virtual irqs */
-#define SPEAR_GPIO_INT_BASE			(VIRQ_START + 17)
+#define SPEAR320_VIRQ_CANU			(SPEAR3XX_VIRQ_START + 6)
+#define SPEAR320_VIRQ_CANL			(SPEAR3XX_VIRQ_START + 7)
+#define SPEAR320_VIRQ_UART1			(SPEAR3XX_VIRQ_START + 8)
+#define SPEAR320_VIRQ_UART2			(SPEAR3XX_VIRQ_START + 9)
+#define SPEAR320_VIRQ_SSP1			(SPEAR3XX_VIRQ_START + 10)
+#define SPEAR320_VIRQ_SSP2			(SPEAR3XX_VIRQ_START + 11)
+#define SPEAR320_VIRQ_SMII0			(SPEAR3XX_VIRQ_START + 12)
+#define SPEAR320_VIRQ_MII1_SMII1		(SPEAR3XX_VIRQ_START + 13)
+#define SPEAR320_VIRQ_WAKEUP_SMII0		(SPEAR3XX_VIRQ_START + 14)
+#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1		(SPEAR3XX_VIRQ_START + 15)
+#define SPEAR320_VIRQ_I2C1			(SPEAR3XX_VIRQ_START + 16)
 
+/*
+ * GPIO pins virtual irqs
+ * Use the lowest number for the GPIO virtual IRQs base on which subarchs
+ * we have compiled in
+ */
+#if defined(CONFIG_MACH_SPEAR310)
+#define SPEAR3XX_GPIO_INT_BASE			(SPEAR3XX_VIRQ_START + 18)
+#elif defined(CONFIG_MACH_SPEAR320)
+#define SPEAR3XX_GPIO_INT_BASE			(SPEAR3XX_VIRQ_START + 17)
+#else
+#define SPEAR3XX_GPIO_INT_BASE			(SPEAR3XX_VIRQ_START + 9)
 #endif
 
-/* PLGPIO Virtual IRQs */
-#define SPEAR_PLGPIO_COUNT	102
+#define SPEAR300_GPIO1_INT_BASE			(SPEAR3XX_GPIO_INT_BASE + 8)
+#define SPEAR3XX_PLGPIO_COUNT	102
+
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-#define SPEAR_PLGPIO_INT_BASE	(SPEAR_GPIO_INT_BASE + 8)
-#define SPEAR_GPIO_INT_END	(SPEAR_PLGPIO_INT_BASE + SPEAR_PLGPIO_COUNT)
+#define SPEAR3XX_PLGPIO_INT_BASE		(SPEAR3XX_GPIO_INT_BASE + 8)
+#define SPEAR3XX_GPIO_INT_END			(SPEAR3XX_PLGPIO_INT_BASE + \
+							SPEAR3XX_PLGPIO_COUNT)
+#else
+#define SPEAR3XX_GPIO_INT_END	(SPEAR300_GPIO1_INT_BASE + 8)
 #endif
 
-#define VIRQ_END		SPEAR_GPIO_INT_END
-#define NR_IRQS			VIRQ_END
+#define SPEAR3XX_VIRQ_END	SPEAR3XX_GPIO_INT_END
+#define NR_IRQS			SPEAR3XX_VIRQ_END
 
 #endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index 4fd2d22..7d5db76 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -20,19 +20,19 @@
 #define SPEAR300_TELECOM_BASE		UL(0x50000000)
 
 /* Interrupt registers offsets and masks */
-#define INT_ENB_MASK_REG		0x54
-#define INT_STS_MASK_REG		0x58
-#define IT_PERS_S_IRQ_MASK		(1 << 0)
-#define IT_CHANGE_S_IRQ_MASK		(1 << 1)
-#define I2S_IRQ_MASK			(1 << 2)
-#define TDM_IRQ_MASK			(1 << 3)
-#define CAMERA_L_IRQ_MASK		(1 << 4)
-#define CAMERA_F_IRQ_MASK		(1 << 5)
-#define CAMERA_V_IRQ_MASK		(1 << 6)
-#define KEYBOARD_IRQ_MASK		(1 << 7)
-#define GPIO1_IRQ_MASK			(1 << 8)
-
-#define SHIRQ_RAS1_MASK			0x1FF
+#define SPEAR300_INT_ENB_MASK_REG	0x54
+#define SPEAR300_INT_STS_MASK_REG	0x58
+#define SPEAR300_IT_PERS_S_IRQ_MASK	(1 << 0)
+#define SPEAR300_IT_CHANGE_S_IRQ_MASK	(1 << 1)
+#define SPEAR300_I2S_IRQ_MASK		(1 << 2)
+#define SPEAR300_TDM_IRQ_MASK		(1 << 3)
+#define SPEAR300_CAMERA_L_IRQ_MASK	(1 << 4)
+#define SPEAR300_CAMERA_F_IRQ_MASK	(1 << 5)
+#define SPEAR300_CAMERA_V_IRQ_MASK	(1 << 6)
+#define SPEAR300_KEYBOARD_IRQ_MASK	(1 << 7)
+#define SPEAR300_GPIO1_IRQ_MASK		(1 << 8)
+
+#define SPEAR300_SHIRQ_RAS1_MASK	0x1FF
 
 #define SPEAR300_CLCD_BASE		UL(0x60000000)
 #define SPEAR300_SDHCI_BASE		UL(0x70000000)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index 37556b6..0780c47 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -38,29 +38,29 @@
 #define SPEAR310_SOC_CONFIG_BASE	UL(0xB4000000)
 
 /* Interrupt registers offsets and masks */
-#define INT_STS_MASK_REG		0x04
-#define SMII0_IRQ_MASK			(1 << 0)
-#define SMII1_IRQ_MASK			(1 << 1)
-#define SMII2_IRQ_MASK			(1 << 2)
-#define SMII3_IRQ_MASK			(1 << 3)
-#define WAKEUP_SMII0_IRQ_MASK		(1 << 4)
-#define WAKEUP_SMII1_IRQ_MASK		(1 << 5)
-#define WAKEUP_SMII2_IRQ_MASK		(1 << 6)
-#define WAKEUP_SMII3_IRQ_MASK		(1 << 7)
-#define UART1_IRQ_MASK			(1 << 8)
-#define UART2_IRQ_MASK			(1 << 9)
-#define UART3_IRQ_MASK			(1 << 10)
-#define UART4_IRQ_MASK			(1 << 11)
-#define UART5_IRQ_MASK			(1 << 12)
-#define EMI_IRQ_MASK			(1 << 13)
-#define TDM_HDLC_IRQ_MASK		(1 << 14)
-#define RS485_0_IRQ_MASK		(1 << 15)
-#define RS485_1_IRQ_MASK		(1 << 16)
+#define SPEAR310_INT_STS_MASK_REG	0x04
+#define SPEAR310_SMII0_IRQ_MASK		(1 << 0)
+#define SPEAR310_SMII1_IRQ_MASK		(1 << 1)
+#define SPEAR310_SMII2_IRQ_MASK		(1 << 2)
+#define SPEAR310_SMII3_IRQ_MASK		(1 << 3)
+#define SPEAR310_WAKEUP_SMII0_IRQ_MASK	(1 << 4)
+#define SPEAR310_WAKEUP_SMII1_IRQ_MASK	(1 << 5)
+#define SPEAR310_WAKEUP_SMII2_IRQ_MASK	(1 << 6)
+#define SPEAR310_WAKEUP_SMII3_IRQ_MASK	(1 << 7)
+#define SPEAR310_UART1_IRQ_MASK		(1 << 8)
+#define SPEAR310_UART2_IRQ_MASK		(1 << 9)
+#define SPEAR310_UART3_IRQ_MASK		(1 << 10)
+#define SPEAR310_UART4_IRQ_MASK		(1 << 11)
+#define SPEAR310_UART5_IRQ_MASK		(1 << 12)
+#define SPEAR310_EMI_IRQ_MASK		(1 << 13)
+#define SPEAR310_TDM_HDLC_IRQ_MASK	(1 << 14)
+#define SPEAR310_RS485_0_IRQ_MASK	(1 << 15)
+#define SPEAR310_RS485_1_IRQ_MASK	(1 << 16)
 
-#define SHIRQ_RAS1_MASK			0x000FF
-#define SHIRQ_RAS2_MASK			0x01F00
-#define SHIRQ_RAS3_MASK			0x02000
-#define SHIRQ_INTRCOMM_RAS_MASK		0x1C000
+#define SPEAR310_SHIRQ_RAS1_MASK	0x000FF
+#define SPEAR310_SHIRQ_RAS2_MASK	0x01F00
+#define SPEAR310_SHIRQ_RAS3_MASK	0x02000
+#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK	0x1C000
 
 #endif /* __MACH_SPEAR310_H */
 
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 4f60073..30ea941 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -42,31 +42,31 @@
 #define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
 
 /* Interrupt registers offsets and masks */
-#define INT_STS_MASK_REG		0x04
-#define INT_CLR_MASK_REG		0x04
-#define INT_ENB_MASK_REG		0x08
-#define GPIO_IRQ_MASK			(1 << 0)
-#define I2S_PLAY_IRQ_MASK		(1 << 1)
-#define I2S_REC_IRQ_MASK		(1 << 2)
-#define EMI_IRQ_MASK			(1 << 7)
-#define CLCD_IRQ_MASK			(1 << 8)
-#define SPP_IRQ_MASK			(1 << 9)
-#define SDHCI_IRQ_MASK			(1 << 10)
-#define CAN_U_IRQ_MASK			(1 << 11)
-#define CAN_L_IRQ_MASK			(1 << 12)
-#define UART1_IRQ_MASK			(1 << 13)
-#define UART2_IRQ_MASK			(1 << 14)
-#define SSP1_IRQ_MASK			(1 << 15)
-#define SSP2_IRQ_MASK			(1 << 16)
-#define SMII0_IRQ_MASK			(1 << 17)
-#define MII1_SMII1_IRQ_MASK		(1 << 18)
-#define WAKEUP_SMII0_IRQ_MASK		(1 << 19)
-#define WAKEUP_MII1_SMII1_IRQ_MASK	(1 << 20)
-#define I2C1_IRQ_MASK			(1 << 21)
+#define SPEAR320_INT_STS_MASK_REG		0x04
+#define SPEAR320_INT_CLR_MASK_REG		0x04
+#define SPEAR320_INT_ENB_MASK_REG		0x08
+#define SPEAR320_GPIO_IRQ_MASK			(1 << 0)
+#define SPEAR320_I2S_PLAY_IRQ_MASK		(1 << 1)
+#define SPEAR320_I2S_REC_IRQ_MASK		(1 << 2)
+#define SPEAR320_EMI_IRQ_MASK			(1 << 7)
+#define SPEAR320_CLCD_IRQ_MASK			(1 << 8)
+#define SPEAR320_SPP_IRQ_MASK			(1 << 9)
+#define SPEAR320_SDHCI_IRQ_MASK			(1 << 10)
+#define SPEAR320_CAN_U_IRQ_MASK			(1 << 11)
+#define SPEAR320_CAN_L_IRQ_MASK			(1 << 12)
+#define SPEAR320_UART1_IRQ_MASK			(1 << 13)
+#define SPEAR320_UART2_IRQ_MASK			(1 << 14)
+#define SPEAR320_SSP1_IRQ_MASK			(1 << 15)
+#define SPEAR320_SSP2_IRQ_MASK			(1 << 16)
+#define SPEAR320_SMII0_IRQ_MASK			(1 << 17)
+#define SPEAR320_MII1_SMII1_IRQ_MASK		(1 << 18)
+#define SPEAR320_WAKEUP_SMII0_IRQ_MASK		(1 << 19)
+#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK	(1 << 20)
+#define SPEAR320_I2C1_IRQ_MASK			(1 << 21)
 
-#define SHIRQ_RAS1_MASK			0x000380
-#define SHIRQ_RAS3_MASK			0x000007
-#define SHIRQ_INTRCOMM_RAS_MASK		0x3FF800
+#define SPEAR320_SHIRQ_RAS1_MASK		0x000380
+#define SPEAR320_SHIRQ_RAS3_MASK		0x000007
+#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK	0x3FF800
 
 #endif /* __MACH_SPEAR320_H */
 
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index bbaf872..b041427 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -538,13 +538,13 @@ struct amba_device clcd_device = {
 		.flags = IORESOURCE_MEM,
 	},
 	.dma_mask = ~0,
-	.irq = {IRQ_CLCD, NO_IRQ},
+	.irq = {SPEAR300_IRQ_CLCD, NO_IRQ},
 };
 
 /* arm gpio1 device registeration */
 static struct pl061_platform_data gpio1_plat_data = {
 	.gpio_base	= 8,
-	.irq_base	= SPEAR_GPIO1_INT_BASE,
+	.irq_base	= SPEAR300_GPIO1_INT_BASE,
 };
 
 struct amba_device gpio1_device = {
@@ -557,7 +557,7 @@ struct amba_device gpio1_device = {
 		.end = SPEAR300_GPIO_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_GPIO1, NO_IRQ},
+	.irq = {SPEAR300_VIRQ_GPIO1, NO_IRQ},
 };
 
 /* keyboard device registration */
@@ -567,7 +567,7 @@ static struct resource kbd_resources[] = {
 		.end = SPEAR300_KEYBOARD_BASE + SZ_1K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_KEYBOARD,
+		.start = SPEAR300_VIRQ_KEYBOARD,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -683,7 +683,7 @@ static struct resource sdhci_resources[] = {
 		.end	= SPEAR300_SDHCI_BASE + SZ_256 - 1,
 		.flags	= IORESOURCE_MEM,
 	}, {
-		.start	= IRQ_SDHCI,
+		.start	= SPEAR300_IRQ_SDHCI,
 		.flags	= IORESOURCE_IRQ,
 	}
 };
@@ -701,53 +701,52 @@ struct platform_device sdhci_device = {
 /* spear3xx shared irq */
 static struct shirq_dev_config shirq_ras1_config[] = {
 	{
-		.virq = VIRQ_IT_PERS_S,
-		.enb_mask = IT_PERS_S_IRQ_MASK,
-		.status_mask = IT_PERS_S_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_IT_PERS_S,
+		.enb_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
+		.status_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
 	}, {
-		.virq = VIRQ_IT_CHANGE_S,
-		.enb_mask = IT_CHANGE_S_IRQ_MASK,
-		.status_mask = IT_CHANGE_S_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_IT_CHANGE_S,
+		.enb_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
+		.status_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
 	}, {
-		.virq = VIRQ_I2S,
-		.enb_mask = I2S_IRQ_MASK,
-		.status_mask = I2S_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_I2S,
+		.enb_mask = SPEAR300_I2S_IRQ_MASK,
+		.status_mask = SPEAR300_I2S_IRQ_MASK,
 	}, {
-		.virq = VIRQ_TDM,
-		.enb_mask = TDM_IRQ_MASK,
-		.status_mask = TDM_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_TDM,
+		.enb_mask = SPEAR300_TDM_IRQ_MASK,
+		.status_mask = SPEAR300_TDM_IRQ_MASK,
 	}, {
-		.virq = VIRQ_CAMERA_L,
-		.enb_mask = CAMERA_L_IRQ_MASK,
-		.status_mask = CAMERA_L_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_CAMERA_L,
+		.enb_mask = SPEAR300_CAMERA_L_IRQ_MASK,
+		.status_mask = SPEAR300_CAMERA_L_IRQ_MASK,
 	}, {
-		.virq = VIRQ_CAMERA_F,
-		.enb_mask = CAMERA_F_IRQ_MASK,
-		.status_mask = CAMERA_F_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_CAMERA_F,
+		.enb_mask = SPEAR300_CAMERA_F_IRQ_MASK,
+		.status_mask = SPEAR300_CAMERA_F_IRQ_MASK,
 	}, {
-		.virq = VIRQ_CAMERA_V,
-		.enb_mask = CAMERA_V_IRQ_MASK,
-		.status_mask = CAMERA_V_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_CAMERA_V,
+		.enb_mask = SPEAR300_CAMERA_V_IRQ_MASK,
+		.status_mask = SPEAR300_CAMERA_V_IRQ_MASK,
 	}, {
-		.virq = VIRQ_KEYBOARD,
-		.enb_mask = KEYBOARD_IRQ_MASK,
-		.status_mask = KEYBOARD_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_KEYBOARD,
+		.enb_mask = SPEAR300_KEYBOARD_IRQ_MASK,
+		.status_mask = SPEAR300_KEYBOARD_IRQ_MASK,
 	}, {
-		.virq = VIRQ_GPIO1,
-		.enb_mask = GPIO1_IRQ_MASK,
-		.status_mask = GPIO1_IRQ_MASK,
+		.virq = SPEAR300_VIRQ_GPIO1,
+		.enb_mask = SPEAR300_GPIO1_IRQ_MASK,
+		.status_mask = SPEAR300_GPIO1_IRQ_MASK,
 	},
 };
 
-
 static struct spear_shirq shirq_ras1 = {
-	.irq = IRQ_GEN_RAS_1,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
 	.regs = {
-		.enb_reg = INT_ENB_MASK_REG,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS1_MASK,
+		.enb_reg = SPEAR300_INT_ENB_MASK_REG,
+		.status_reg = SPEAR300_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR300_SHIRQ_RAS1_MASK,
 		.clear_reg = -1,
 	},
 };
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 7d4ff0e..6fb20c3 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -205,7 +205,7 @@ struct amba_device uart1_device = {
 		.end = SPEAR310_UART1_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART1, NO_IRQ},
+	.irq = {SPEAR310_VIRQ_UART1, NO_IRQ},
 };
 
 /* uart2 device registeration */
@@ -218,7 +218,7 @@ struct amba_device uart2_device = {
 		.end = SPEAR310_UART2_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART2, NO_IRQ},
+	.irq = {SPEAR310_VIRQ_UART2, NO_IRQ},
 };
 
 /* uart3 device registeration */
@@ -231,7 +231,7 @@ struct amba_device uart3_device = {
 		.end = SPEAR310_UART3_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART3, NO_IRQ},
+	.irq = {SPEAR310_VIRQ_UART3, NO_IRQ},
 };
 
 /* uart4 device registeration */
@@ -244,7 +244,7 @@ struct amba_device uart4_device = {
 		.end = SPEAR310_UART4_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART4, NO_IRQ},
+	.irq = {SPEAR310_VIRQ_UART4, NO_IRQ},
 };
 
 /* uart5 device registeration */
@@ -257,7 +257,7 @@ struct amba_device uart5_device = {
 		.end = SPEAR310_UART5_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART5, NO_IRQ},
+	.irq = {SPEAR310_VIRQ_UART5, NO_IRQ},
 };
 
 /* nand device registeration */
@@ -331,8 +331,8 @@ struct platform_device emi_nor_device = {
 
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
-	.irq_base = SPEAR_PLGPIO_INT_BASE,
-	.gpio_count = SPEAR_PLGPIO_COUNT,
+	.irq_base = SPEAR3XX_PLGPIO_INT_BASE,
+	.gpio_count = SPEAR3XX_PLGPIO_COUNT,
 	.p2o = spear300_p2o,
 	.o2p = spear300_o2p,
 	/* list of registers with inconsistency */
@@ -346,7 +346,7 @@ static struct resource plgpio_resources[] = {
 		.end = SPEAR310_SOC_CONFIG_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_PLGPIO,
+		.start = SPEAR310_VIRQ_PLGPIO,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -365,115 +365,115 @@ struct platform_device plgpio_device = {
 /* spear3xx shared irq */
 static struct shirq_dev_config shirq_ras1_config[] = {
 	{
-		.virq = VIRQ_SMII0,
-		.status_mask = SMII0_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_SMII0,
+		.status_mask = SPEAR310_SMII0_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SMII1,
-		.status_mask = SMII1_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_SMII1,
+		.status_mask = SPEAR310_SMII1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SMII2,
-		.status_mask = SMII2_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_SMII2,
+		.status_mask = SPEAR310_SMII2_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SMII3,
-		.status_mask = SMII3_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_SMII3,
+		.status_mask = SPEAR310_SMII3_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_SMII0,
-		.status_mask = WAKEUP_SMII0_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_WAKEUP_SMII0,
+		.status_mask = SPEAR310_WAKEUP_SMII0_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_SMII1,
-		.status_mask = WAKEUP_SMII1_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_WAKEUP_SMII1,
+		.status_mask = SPEAR310_WAKEUP_SMII1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_SMII2,
-		.status_mask = WAKEUP_SMII2_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_WAKEUP_SMII2,
+		.status_mask = SPEAR310_WAKEUP_SMII2_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_SMII3,
-		.status_mask = WAKEUP_SMII3_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_WAKEUP_SMII3,
+		.status_mask = SPEAR310_WAKEUP_SMII3_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_ras1 = {
-	.irq = IRQ_GEN_RAS_1,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS1_MASK,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR310_SHIRQ_RAS1_MASK,
 		.clear_reg = -1,
 	},
 };
 
 static struct shirq_dev_config shirq_ras2_config[] = {
 	{
-		.virq = VIRQ_UART1,
-		.status_mask = UART1_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_UART1,
+		.status_mask = SPEAR310_UART1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART2,
-		.status_mask = UART2_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_UART2,
+		.status_mask = SPEAR310_UART2_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART3,
-		.status_mask = UART3_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_UART3,
+		.status_mask = SPEAR310_UART3_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART4,
-		.status_mask = UART4_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_UART4,
+		.status_mask = SPEAR310_UART4_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART5,
-		.status_mask = UART5_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_UART5,
+		.status_mask = SPEAR310_UART5_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_ras2 = {
-	.irq = IRQ_GEN_RAS_2,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_2,
 	.dev_config = shirq_ras2_config,
 	.dev_count = ARRAY_SIZE(shirq_ras2_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS2_MASK,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR310_SHIRQ_RAS2_MASK,
 		.clear_reg = -1,
 	},
 };
 
 static struct shirq_dev_config shirq_ras3_config[] = {
 	{
-		.virq = VIRQ_EMI,
-		.status_mask = EMI_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_EMI,
+		.status_mask = SPEAR310_EMI_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_ras3 = {
-	.irq = IRQ_GEN_RAS_3,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_3,
 	.dev_config = shirq_ras3_config,
 	.dev_count = ARRAY_SIZE(shirq_ras3_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS3_MASK,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR310_SHIRQ_RAS3_MASK,
 		.clear_reg = -1,
 	},
 };
 
 static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	{
-		.virq = VIRQ_TDM_HDLC,
-		.status_mask = TDM_HDLC_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_TDM_HDLC,
+		.status_mask = SPEAR310_TDM_HDLC_IRQ_MASK,
 	}, {
-		.virq = VIRQ_RS485_0,
-		.status_mask = RS485_0_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_RS485_0,
+		.status_mask = SPEAR310_RS485_0_IRQ_MASK,
 	}, {
-		.virq = VIRQ_RS485_1,
-		.status_mask = RS485_1_IRQ_MASK,
+		.virq = SPEAR310_VIRQ_RS485_1,
+		.status_mask = SPEAR310_RS485_1_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_intrcomm_ras = {
-	.irq = IRQ_INTRCOMM_RAS_ARM,
+	.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
 	.dev_config = shirq_intrcomm_ras_config,
 	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK,
+		.status_reg = SPEAR310_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR310_SHIRQ_INTRCOMM_RAS_MASK,
 		.clear_reg = -1,
 	},
 };
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 948ca8e..03d3486 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -606,7 +606,7 @@ struct amba_device clcd_device = {
 		.flags = IORESOURCE_MEM,
 	},
 	.dma_mask = ~0,
-	.irq = {VIRQ_CLCD, NO_IRQ},
+	.irq = {SPEAR320_VIRQ_CLCD, NO_IRQ},
 };
 
 /* ssp device registeration */
@@ -634,7 +634,7 @@ struct amba_device ssp_device[] = {
 			.end = SPEAR320_SSP0_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
-		.irq = {VIRQ_SSP1, NO_IRQ},
+		.irq = {SPEAR320_VIRQ_SSP1, NO_IRQ},
 	}, {
 		.dev = {
 			.coherent_dma_mask = ~0,
@@ -646,7 +646,7 @@ struct amba_device ssp_device[] = {
 			.end = SPEAR320_SSP1_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
-		.irq = {VIRQ_SSP2, NO_IRQ},
+		.irq = {SPEAR320_VIRQ_SSP2, NO_IRQ},
 	}
 };
 
@@ -660,7 +660,7 @@ struct amba_device uart1_device = {
 		.end = SPEAR320_UART1_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART1, NO_IRQ},
+	.irq = {SPEAR320_VIRQ_UART1, NO_IRQ},
 };
 
 /* uart2 device registeration */
@@ -673,7 +673,7 @@ struct amba_device uart2_device = {
 		.end = SPEAR320_UART2_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {VIRQ_UART2, NO_IRQ},
+	.irq = {SPEAR320_VIRQ_UART2, NO_IRQ},
 };
 
 /* emi nor flash device registeration */
@@ -687,8 +687,8 @@ struct platform_device emi_nor_device = {
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
-	.irq_base = SPEAR_PLGPIO_INT_BASE,
-	.gpio_count = SPEAR_PLGPIO_COUNT,
+	.irq_base = SPEAR3XX_PLGPIO_INT_BASE,
+	.gpio_count = SPEAR3XX_PLGPIO_COUNT,
 };
 
 /* CAN device registeration */
@@ -698,7 +698,7 @@ static struct resource can0_resources[] = {
 		.end = SPEAR320_CAN0_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_CANU,
+		.start = SPEAR320_VIRQ_CANU,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -716,7 +716,7 @@ static struct resource can1_resources[] = {
 		.end = SPEAR320_CAN1_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_CANL,
+		.start = SPEAR320_VIRQ_CANL,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -735,7 +735,7 @@ static struct resource i2c1_resources[] = {
 		.end = SPEAR320_I2C_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_I2C1 ,
+		.start = SPEAR320_VIRQ_I2C1 ,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -781,7 +781,7 @@ static struct resource plgpio_resources[] = {
 		.end = SPEAR320_SOC_CONFIG_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = VIRQ_PLGPIO,
+		.start = SPEAR320_VIRQ_PLGPIO,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -819,7 +819,7 @@ static struct resource sdhci_resources[] = {
 		.end	= SPEAR320_SDHCI_BASE + SZ_256 - 1,
 		.flags	= IORESOURCE_MEM,
 	}, {
-		.start	= IRQ_SDHCI,
+		.start	= SPEAR320_IRQ_SDHCI,
 		.flags	= IORESOURCE_IRQ,
 	}
 };
@@ -837,123 +837,123 @@ struct platform_device sdhci_device = {
 /* spear3xx shared irq */
 static struct shirq_dev_config shirq_ras1_config[] = {
 	{
-		.virq = VIRQ_EMI,
-		.status_mask = EMI_IRQ_MASK,
-		.clear_mask = EMI_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_EMI,
+		.status_mask = SPEAR320_EMI_IRQ_MASK,
+		.clear_mask = SPEAR320_EMI_IRQ_MASK,
 	}, {
-		.virq = VIRQ_CLCD,
-		.status_mask = CLCD_IRQ_MASK,
-		.clear_mask = CLCD_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_CLCD,
+		.status_mask = SPEAR320_CLCD_IRQ_MASK,
+		.clear_mask = SPEAR320_CLCD_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SPP,
-		.status_mask = SPP_IRQ_MASK,
-		.clear_mask = SPP_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_SPP,
+		.status_mask = SPEAR320_SPP_IRQ_MASK,
+		.clear_mask = SPEAR320_SPP_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_ras1 = {
-	.irq = IRQ_GEN_RAS_1,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS1_MASK,
-		.clear_reg = INT_CLR_MASK_REG,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR320_SHIRQ_RAS1_MASK,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
 		.reset_to_clear = 1,
 	},
 };
 
 static struct shirq_dev_config shirq_ras3_config[] = {
 	{
-		.virq = VIRQ_PLGPIO,
-		.enb_mask = GPIO_IRQ_MASK,
-		.status_mask = GPIO_IRQ_MASK,
-		.clear_mask = GPIO_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_PLGPIO,
+		.enb_mask = SPEAR320_GPIO_IRQ_MASK,
+		.status_mask = SPEAR320_GPIO_IRQ_MASK,
+		.clear_mask = SPEAR320_GPIO_IRQ_MASK,
 	}, {
-		.virq = VIRQ_I2S_PLAY,
-		.enb_mask = I2S_PLAY_IRQ_MASK,
-		.status_mask = I2S_PLAY_IRQ_MASK,
-		.clear_mask = I2S_PLAY_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_I2S_PLAY,
+		.enb_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
+		.status_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
+		.clear_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
 	}, {
-		.virq = VIRQ_I2S_REC,
-		.enb_mask = I2S_REC_IRQ_MASK,
-		.status_mask = I2S_REC_IRQ_MASK,
-		.clear_mask = I2S_REC_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_I2S_REC,
+		.enb_mask = SPEAR320_I2S_REC_IRQ_MASK,
+		.status_mask = SPEAR320_I2S_REC_IRQ_MASK,
+		.clear_mask = SPEAR320_I2S_REC_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_ras3 = {
-	.irq = IRQ_GEN_RAS_3,
+	.irq = SPEAR3XX_IRQ_GEN_RAS_3,
 	.dev_config = shirq_ras3_config,
 	.dev_count = ARRAY_SIZE(shirq_ras3_config),
 	.regs = {
-		.enb_reg = INT_ENB_MASK_REG,
+		.enb_reg = SPEAR320_INT_ENB_MASK_REG,
 		.reset_to_enb = 1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_RAS3_MASK,
-		.clear_reg = INT_CLR_MASK_REG,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR320_SHIRQ_RAS3_MASK,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
 		.reset_to_clear = 1,
 	},
 };
 
 static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	{
-		.virq = VIRQ_CANU,
-		.status_mask = CAN_U_IRQ_MASK,
-		.clear_mask = CAN_U_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_CANU,
+		.status_mask = SPEAR320_CAN_U_IRQ_MASK,
+		.clear_mask = SPEAR320_CAN_U_IRQ_MASK,
 	}, {
-		.virq = VIRQ_CANL,
-		.status_mask = CAN_L_IRQ_MASK,
-		.clear_mask = CAN_L_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_CANL,
+		.status_mask = SPEAR320_CAN_L_IRQ_MASK,
+		.clear_mask = SPEAR320_CAN_L_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART1,
-		.status_mask = UART1_IRQ_MASK,
-		.clear_mask = UART1_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_UART1,
+		.status_mask = SPEAR320_UART1_IRQ_MASK,
+		.clear_mask = SPEAR320_UART1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_UART2,
-		.status_mask = UART2_IRQ_MASK,
-		.clear_mask = UART2_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_UART2,
+		.status_mask = SPEAR320_UART2_IRQ_MASK,
+		.clear_mask = SPEAR320_UART2_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SSP1,
-		.status_mask = SSP1_IRQ_MASK,
-		.clear_mask = SSP1_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_SSP1,
+		.status_mask = SPEAR320_SSP1_IRQ_MASK,
+		.clear_mask = SPEAR320_SSP1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SSP2,
-		.status_mask = SSP2_IRQ_MASK,
-		.clear_mask = SSP2_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_SSP2,
+		.status_mask = SPEAR320_SSP2_IRQ_MASK,
+		.clear_mask = SPEAR320_SSP2_IRQ_MASK,
 	}, {
-		.virq = VIRQ_SMII0,
-		.status_mask = SMII0_IRQ_MASK,
-		.clear_mask = SMII0_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_SMII0,
+		.status_mask = SPEAR320_SMII0_IRQ_MASK,
+		.clear_mask = SPEAR320_SMII0_IRQ_MASK,
 	}, {
-		.virq = VIRQ_MII1_SMII1,
-		.status_mask = MII1_SMII1_IRQ_MASK,
-		.clear_mask = MII1_SMII1_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_MII1_SMII1,
+		.status_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
+		.clear_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_SMII0,
-		.status_mask = WAKEUP_SMII0_IRQ_MASK,
-		.clear_mask = WAKEUP_SMII0_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_WAKEUP_SMII0,
+		.status_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
+		.clear_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
 	}, {
-		.virq = VIRQ_WAKEUP_MII1_SMII1,
-		.status_mask = WAKEUP_MII1_SMII1_IRQ_MASK,
-		.clear_mask = WAKEUP_MII1_SMII1_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_WAKEUP_MII1_SMII1,
+		.status_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
+		.clear_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
 	}, {
-		.virq = VIRQ_I2C1,
-		.status_mask = I2C1_IRQ_MASK,
-		.clear_mask = I2C1_IRQ_MASK,
+		.virq = SPEAR320_VIRQ_I2C1,
+		.status_mask = SPEAR320_I2C1_IRQ_MASK,
+		.clear_mask = SPEAR320_I2C1_IRQ_MASK,
 	},
 };
 
 static struct spear_shirq shirq_intrcomm_ras = {
-	.irq = IRQ_INTRCOMM_RAS_ARM,
+	.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
 	.dev_config = shirq_intrcomm_ras_config,
 	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
 	.regs = {
 		.enb_reg = -1,
-		.status_reg = INT_STS_MASK_REG,
-		.status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK,
-		.clear_reg = INT_CLR_MASK_REG,
+		.status_reg = SPEAR320_INT_STS_MASK_REG,
+		.status_reg_mask = SPEAR320_SHIRQ_INTRCOMM_RAS_MASK,
+		.clear_reg = SPEAR320_INT_CLR_MASK_REG,
 		.reset_to_clear = 1,
 	},
 };
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 544072d..2765d32 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -22,13 +22,14 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 
-#define SPEAR3XX_WKUP_SRCS	(1 << IRQ_MAC_1 | 1 << IRQ_USB_DEV | \
-				1 << IRQ_BASIC_RTC | 1 << IRQ_BASIC_GPIO)
+#define SPEAR3XX_WKUP_SRCS	(1 << SPEAR3XX_IRQ_MAC_1 | 1 << \
+		SPEAR3XX_IRQ_USB_DEV | 1 << SPEAR3XX_IRQ_BASIC_RTC | 1 << \
+		SPEAR3XX_IRQ_BASIC_GPIO)
 /* Add spear3xx machines common devices here */
 /* gpio device registeration */
 static struct pl061_platform_data gpio_plat_data = {
 	.gpio_base	= 0,
-	.irq_base	= SPEAR_GPIO_INT_BASE,
+	.irq_base	= SPEAR3XX_GPIO_INT_BASE,
 };
 
 struct amba_device gpio_device = {
@@ -41,7 +42,7 @@ struct amba_device gpio_device = {
 		.end = SPEAR3XX_ICM3_GPIO_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {IRQ_BASIC_GPIO, NO_IRQ},
+	.irq = {SPEAR3XX_IRQ_BASIC_GPIO, NO_IRQ},
 };
 
 /* ssp device registeration */
@@ -71,7 +72,7 @@ struct amba_device ssp0_device = {
 		.end = SPEAR3XX_ICM1_SSP_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {IRQ_SSP, NO_IRQ},
+	.irq = {SPEAR3XX_IRQ_SSP, NO_IRQ},
 };
 
 /* uart device registeration */
@@ -84,7 +85,7 @@ struct amba_device uart_device = {
 		.end = SPEAR3XX_ICM1_UART_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
-	.irq = {IRQ_UART, NO_IRQ},
+	.irq = {SPEAR3XX_IRQ_UART, NO_IRQ},
 };
 
 /* watchdog device registeration */
@@ -106,7 +107,7 @@ static struct resource i2c_resources[] = {
 		.end = SPEAR3XX_ICM1_I2C_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = IRQ_I2C,
+		.start = SPEAR3XX_IRQ_I2C,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -129,7 +130,7 @@ static struct resource ehci_resources[] = {
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start = IRQ_USB_H_EHCI_0,
+		.start = SPEAR3XX_IRQ_USB_H_EHCI_0,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -141,7 +142,7 @@ static struct resource ohci0_resources[] = {
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start = IRQ_USB_H_OHCI_0,
+		.start = SPEAR3XX_IRQ_USB_H_OHCI_0,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -153,7 +154,7 @@ static struct resource ohci1_resources[] = {
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start = IRQ_USB_H_OHCI_1,
+		.start = SPEAR3XX_IRQ_USB_H_OHCI_1,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -208,7 +209,7 @@ static struct resource rtc_resources[] = {
 		.end = SPEAR3XX_ICM3_RTC_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = IRQ_BASIC_RTC,
+		.start = SPEAR3XX_IRQ_BASIC_RTC,
 		.flags = IORESOURCE_IRQ,
 	},
 };
@@ -227,7 +228,7 @@ static struct resource smi_resources[] = {
 		.end = SPEAR3XX_ICM3_SMI_CTRL_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	}, {
-		.start = IRQ_BASIC_SMI,
+		.start = SPEAR3XX_IRQ_BASIC_SMI,
 		.flags = IORESOURCE_IRQ,
 	},
 };
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:02 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:02 +0530
Subject: [PATCH V2 42/69] SPEAr Power Management: Added the support for
	Standby mode.
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <d87f4ffdd726bd68f7f43bfb75508ad0bce664c1.1285933332.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri at st.com>

OPEN POINTS: 	1. Suspend to RAM support needs to be added.
		2. The basic framework added for S2R.
		3. SPEAr13xx: The power domains need to be added.
		4. Extensive testing needs to be done.
		5. For SPEAr13xx: PLL-4 has not been switch off while moving
		into sleep. There is some problem in getting the pll back to on.
		6. Not functional on SPEAr6XX

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/Makefile               |    1 +
 arch/arm/mach-spear13xx/include/mach/suspend.h |   47 +++
 arch/arm/mach-spear13xx/pm.c                   |  107 ++++++
 arch/arm/mach-spear13xx/sleep.S                |  435 ++++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear13xx.c            |    5 +
 arch/arm/mach-spear3xx/include/mach/suspend.h  |   44 +++
 arch/arm/mach-spear3xx/spear3xx.c              |    5 +-
 arch/arm/mach-spear6xx/include/mach/suspend.h  |   44 +++
 arch/arm/mach-spear6xx/spear6xx.c              |    9 +-
 arch/arm/plat-spear/Makefile                   |    6 +
 arch/arm/plat-spear/pm.c                       |  104 ++++++
 arch/arm/plat-spear/sleep.S                    |  288 ++++++++++++++++
 12 files changed, 1093 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/suspend.h
 create mode 100644 arch/arm/mach-spear13xx/pm.c
 create mode 100644 arch/arm/mach-spear13xx/sleep.S
 create mode 100644 arch/arm/mach-spear3xx/include/mach/suspend.h
 create mode 100644 arch/arm/mach-spear6xx/include/mach/suspend.h
 create mode 100644 arch/arm/plat-spear/pm.c
 create mode 100644 arch/arm/plat-spear/sleep.S

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index 9312fcd..799eefa 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -7,6 +7,7 @@ obj-y					+= spear13xx.o clock.o fsmc-nor.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
 obj-$(CONFIG_PCIEPORTBUS)		+= pcie.o
+obj-$(CONFIG_PM)			+= pm.o sleep.o
 
 # spear1300 specific files
 obj-$(CONFIG_MACH_SPEAR1300)		+= spear1300.o
diff --git a/arch/arm/mach-spear13xx/include/mach/suspend.h b/arch/arm/mach-spear13xx/include/mach/suspend.h
new file mode 100644
index 0000000..c8d13e6
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/suspend.h
@@ -0,0 +1,47 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr13xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/spear.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+extern void spear_wakeup(void);
+extern unsigned int spear_wakeup_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_STRT_OFF	0x500
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR13XX_SYSRAM1_BASE
+#define SPEAR_LIMIT_SRAM	(SPEAR_START_SRAM + SZ_4K - 1)
+#define SPEAR_SRAM_STACK_PA	(SPEAR_START_SRAM + SRAM_STACK_STRT_OFF)
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define MPMC_BASE_PA		SPEAR13XX_MPMC_BASE
+#define MISC_BASE_PA		SPEAR13XX_MISC_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear13xx/pm.c b/arch/arm/mach-spear13xx/pm.c
new file mode 100644
index 0000000..1fe3f54
--- /dev/null
+++ b/arch/arm/mach-spear13xx/pm.c
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/mach-spear13xx/pm.c
+ *
+ * SPEAr13xx Power Management source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/suspend.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <mach/irqs.h>
+#include <mach/suspend.h>
+#include <mach/hardware.h>
+
+static int spear_pm_sleep(suspend_state_t state)
+{
+	void (*spear_sram_sleep)(suspend_state_t state) = NULL;
+	void (*spear_sram_wake)(void) = NULL;
+	void *sram_dest = (void *)IO_ADDRESS(SPEAR_START_SRAM);
+
+	if (state == PM_SUSPEND_MEM) {
+		spear_sram_wake = memcpy(sram_dest, (void *)spear_wakeup,
+				spear_wakeup_sz);
+		/* Increment destination pointer by the size copied*/
+		sram_dest += roundup(spear_wakeup_sz, 4);
+	}
+
+	/* Copy the Sleep code on to the SRAM*/
+	spear_sram_sleep = memcpy(sram_dest, (void *)spear_sleep_mode,
+			spear_sleep_mode_sz);
+	flush_cache_all();
+	/* Jump to the suspend routines in sram */
+	spear_sram_sleep(state);
+	return 0;
+}
+
+/*
+ *	spear_pm_prepare - Do preliminary suspend work.
+ *
+ */
+static int spear_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	disable_hlt();
+	return 0;
+}
+
+/*
+ *	spear_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+static int spear_pm_enter(suspend_state_t state)
+{
+	int ret;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = spear_pm_sleep(state);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ *	spear_pm_finish - Finish up suspend sequence.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+static void spear_pm_finish(void)
+{
+	enable_hlt();
+}
+
+static const struct platform_suspend_ops spear_pm_ops = {
+	.prepare	= spear_pm_prepare,
+	.enter		= spear_pm_enter,
+	.finish		= spear_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int __init spear_pm_init(void)
+{
+	void * sram_limit_va = (void *)IO_ADDRESS(SPEAR_LIMIT_SRAM);
+	void * sram_st_va = (void *)IO_ADDRESS(SPEAR_START_SRAM);
+
+	/* In case the suspend code size is more than sram size return */
+	if (spear_sleep_mode_sz > (sram_limit_va - sram_st_va))
+		return	-ENOMEM;
+
+	suspend_set_ops(&spear_pm_ops);
+
+	return 0;
+}
+arch_initcall(spear_pm_init);
diff --git a/arch/arm/mach-spear13xx/sleep.S b/arch/arm/mach-spear13xx/sleep.S
new file mode 100644
index 0000000..9c7f12b
--- /dev/null
+++ b/arch/arm/mach-spear13xx/sleep.S
@@ -0,0 +1,435 @@
+/*
+ * linux/arch/arm/mach-spear13xx/sleep.S
+ *
+ * SPEAR13xx specific functions that will run in internal SRAM.
+ * The functions are used in power management.
+ *
+ * Copyright (C) 2010 ST MicroElectronics
+ * Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+/* #define DDR_PLL_SREFRESH */
+/* #define TEST_PWRDOMAINS */
+.text
+ENTRY(spear_wakeup)
+
+spear_wakeup:
+	b	spear_wakeup
+	adr	r0, spear_sleep_restore
+	bx	r0
+
+ENTRY(spear_wakeup_sz)
+	.word	. - spear_wakeup
+/*
+ * spear_sleep_mode()
+ * Forces SPEAr into sleep
+ */
+ENTRY(spear_sleep_mode)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+	/* Store Stack address in r8 */
+	ldr	r8, SRAM_STACK_VA
+
+	/* Store sp and spsr to SDRAM */
+	mov	r4, sp
+	mrs	r5, spsr
+	mov	r6, lr
+	stmia	r8!, {r4-r6}
+
+	/* Save all ARM registers */
+	/* Coprocessor access control register */
+	mrc	p15, 0, r6, c1, c0, 2
+	stmia	r8!, {r6}
+	/* TTBR0, TTBR1 and Translation table base control */
+	mrc	p15, 0, r4, c2, c0, 0
+	mrc	p15, 0, r5, c2, c0, 1
+	mrc	p15, 0, r6, c2, c0, 2
+	stmia	r8!, {r4-r6}
+	/*
+	 * Domain access control register, data fault status register,
+	 * and instruction fault status register
+	 */
+	mrc	p15, 0, r4, c3, c0, 0
+	mrc	p15, 0, r5, c5, c0, 0
+	mrc	p15, 0, r6, c5, c0, 1
+	stmia	r8!, {r4-r6}
+	/*
+	 * Data aux fault status register, instruction aux fault status,
+	 * data fault address register and instruction fault address register
+	 */
+	mrc	p15, 0, r4, c5, c1, 0
+	mrc	p15, 0, r5, c5, c1, 1
+	mrc	p15, 0, r6, c6, c0, 0
+	mrc	p15, 0, r7, c6, c0, 2
+	stmia	r8!, {r4-r7}
+	/*
+	 * user r/w thread and process ID, user r/o thread and process ID,
+	 * priv only thread and process ID, cache size selection
+	 */
+	mrc	p15, 0, r4, c13, c0, 2
+	mrc	p15, 0, r5, c13, c0, 3
+	mrc	p15, 0, r6, c13, c0, 4
+	mrc	p15, 2, r7, c0, c0, 0
+	stmia	r8!, {r4-r7}
+	/* Data TLB lockdown, instruction TLB lockdown registers */
+	mrc	p15, 0, r5, c10, c0, 0
+	mrc	p15, 0, r6, c10, c0, 1
+	stmia	r8!, {r5-r6}
+	/* Secure or non secure vector base address, FCSE PID, Context PID*/
+	mrc	p15, 0, r4, c12, c0, 0
+	mrc	p15, 0, r5, c13, c0, 0
+	mrc	p15, 0, r6, c13, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Primary remap, normal remap registers */
+	mrc	p15, 0, r4, c10, c2, 0
+	mrc	p15, 0, r5, c10, c2, 1
+	stmia	r8!, {r4-r5}
+	/* Store current cpsr*/
+	mrs	r2, cpsr
+	stmia	r8!, {r2}
+	mrc	p15, 0, r4, c1, c0, 0
+	/* save control register */
+	stmia	r8!, {r4}
+	/* Data memory barrier and Data sync barrier */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+	dsb
+	isb
+	/* Extract the physical address to jump to */
+	adr	r0, mmu_off
+	mov	r1, #0xcfffffff
+	and	r0, r0, r1
+	ldr	r1, =0x20000000
+	orr	r0, r0, r1
+	mov	r2, r0
+
+	/* Disable MMU */
+	mrc	p15, 0, r0, c1, c0, 0
+	ldr	r1, DISABLE_I_C_M_V
+	bic	r0, r0, r1
+	mcr	p15, 0, r0, c1, c0, 0
+	/* Move the Physical address into PC */
+	bx	r2
+	nop
+mmu_off:
+	/* Put the DDR in self refresh mode */
+	ldr	r6, MISC_BASE_P
+	/* Program MPMC Control Status register in Misc Space */
+	ldr	r0, [r6, #0x334]
+	/* Set srefresh_enter bit(2) */
+	orr	r0, r0, #0x4
+	str	r0, [r6, #0x334]
+wait_till_srefresh_on:
+	ldr	r0, [r6, #0x334]
+	/* check for cke_status bit(13) */
+	tst	r0, #0x2000
+	beq	wait_till_srefresh_on
+
+	/* Put the system in slow mode */
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x4
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x2
+	str	r0, [r6, #0x200]	/* System is now in slow mode */
+wait_till_slow_mode:
+	ldr	r0, [r6, #0x200]
+	/* Wait for the mode to be updated */
+	and	r0, r0, #0xF0000
+	/* Poll the SCCTRL register status bits (6:3) */
+	cmp	r0, #0xA0000
+	bne wait_till_slow_mode
+
+	/*
+	 * Put the all the system pll's to off state
+	 * The loop of count 3 is provided below to
+	 * switch off the pll-1/2/3.
+	 * r1 contains the offset for the pll control
+	 * registers in the misc space.
+	 * DDR pll-4 requires different processing.
+	 */
+	ldr	r1, MISC_PLL_OFFS
+	ldr	r2, =0x0	/* PLL Counter 1, 2, 3, 4 */
+swoff_pll:
+	ldr	r0, [r6, r1]
+	/* Clear pll_enable bit(1) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x02
+	str	r0, [r6, r1]
+	add	r1, #0xc
+	add	r2, #0x1
+	cmp	r2, #0x3	/* Switch off pll-1/2/3 */
+	bne	swoff_pll
+
+#ifdef DDR_PLL_SREFRESH
+	/* Switch off pll-4 */
+	ldr	r0, [r6, r1]
+	/* Clear pll_enable bit(2) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, r1]
+#endif
+
+#ifdef TEST_PWRDOMAINS
+	/* Switch off the undesired PLL's */
+	nop
+	ldr	r6, MISC_BASE_P
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x7
+	orr	r0, r0, #0x2
+	str	r0, [r6, #0x200	]
+wait_ack0:
+	ldr	r0, [r6, #0x200]
+	and	r0, r0, #0xF0000
+	cmp	r0, #0xA0000
+	bne	wait_ack0
+	ldr	r6, MISC_BASE_P
+	ldr	r0, [r6, #0x100]
+
+	/*
+	 * Switch off the power domains.
+	 * Clear the ack bit
+	 */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x1000
+	str	r0, [r6, #0x100]
+
+wait_ack1:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack1
+
+	/* Clear the ack bit */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x0800
+	str	r0, [r6, #0x100]
+wait_ack2:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack2
+
+	/* Clear the ack bit */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x2400
+	str	r0, [r6, #0x100]
+wait_ack3:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack3
+#endif
+	wfi				@ wait for interrupt
+	nop
+spear_sleep_restore:
+	/*
+	 * Reenable the switched off pll's. The Pll's are
+	 * enabled using loop count of 4 to activalte all the
+	 * pll-1/2/3/4.
+	 * The strobing is done for pll-4 only.
+	 */
+
+	ldr	r6, MISC_BASE_P
+	ldr	r1, MISC_PLL_OFFS
+	ldr	r2, =0x0	/* PLL Counter 1, 2, 3, 4 */
+swon_pll_1_3:
+	/* Switch on Pll-1/2/3 */
+	ldr	r0, [r6, r1]
+	orr	r0, r0, #0x2
+	str	r0, [r6, r1]
+pll_lock_1_3:
+	/* Set the pll_lock bit(0) in PLLX_CTR register in misc space*/
+	ldr	r5, [r6, r1]
+	and	r5, r5, #0x1
+	/* Wait for pll lock status */
+	cmp	r5, #0x1
+	bne	pll_lock_1_3
+
+	/* Loop for all the pll's */
+	add	r1, #0xc
+	add	r2, #0x1
+	cmp	r2, #0x3	/* Switch on till pll-3 */
+	bne	swon_pll_1_3
+
+#ifdef DDR_PLL_SREFRESH
+	/* Switch on PLL-4, strobe the pll also */
+	ldr	r0, [r6, r1]
+	ldr	r0, PLL_VAL1
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL3
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, r1]
+pll_lock_4:
+	/* Set the pll_lock bit(0) in PLLX_CTR register in misc space*/
+	ldr	r5, [r6, r1]
+	and	r5, r5, #0x1
+	/* Wait for pll lock status */
+	cmp	r5, #0x1
+	bne	pll_lock_4
+#endif
+
+	/* Put the system in normal mode */
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x7
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x4
+	str	r0, [r6, #0x200]	/* System is now in slow mode */
+wait_till_normal_mode:
+	ldr	r0, [r6, #0x200]
+	/* Wait for the mode to be updated */
+	and	r0, r0, #0xF0000
+	/* Poll the SCCTRL register status bits (6:3) */
+	cmp	r0, #0xf0000
+	bne wait_till_normal_mode
+
+	/*
+	 * Invalidate all instruction caches to PoU
+	 * and flush branch target cache
+	 */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c5, 0
+
+	ldr	r3, SRAM_STACK_PA
+	ldmia	r3!, {r4-r6}
+	mov	sp, r4
+	msr	spsr_cxsf, r5
+	mov	lr, r6
+
+	ldmia	r3!, {r4-r9}
+	/* Coprocessor access Control Register */
+	mcr	p15, 0, r4, c1, c0, 2
+
+	/* TTBR0 */
+	mcr	p15, 0, r5, c2, c0, 0
+	/* TTBR1 */
+	mcr	p15, 0, r6, c2, c0, 1
+	/* Translation table base control register */
+	mcr	p15, 0, r7, c2, c0, 2
+	/*domain access Control Register */
+	mcr	p15, 0, r8, c3, c0, 0
+	/* data fault status Register */
+	mcr	p15, 0, r9, c5, c0, 0
+
+	ldmia	r3!, {r4-r8}
+	/* instruction fault status Register */
+	mcr	p15, 0, r4, c5, c0, 1
+	/*Data Auxiliary Fault Status Register */
+	mcr	p15, 0, r5, c5, c1, 0
+	/*Instruction Auxiliary Fault Status Register*/
+	mcr	p15, 0, r6, c5, c1, 1
+	/*Data Fault Address Register */
+	mcr	p15, 0, r7, c6, c0, 0
+	/*Instruction Fault Address Register*/
+	mcr	p15, 0, r8, c6, c0, 2
+	ldmia	r3!, {r4-r7}
+
+	/* user r/w thread and process ID */
+	mcr	p15, 0, r4, c13, c0, 2
+	/* user ro thread and process ID */
+	mcr	p15, 0, r5, c13, c0, 3
+	/*Privileged only thread and process ID */
+	mcr	p15, 0, r6, c13, c0, 4
+	/* cache size selection */
+	mcr	p15, 2, r7, c0, c0, 0
+	ldmia	r3!, {r4-r8}
+	/* Data TLB lockdown registers */
+	mcr	p15, 0, r4, c10, c0, 0
+	/* Instruction TLB lockdown registers */
+	mcr	p15, 0, r5, c10, c0, 1
+	/* Secure or Nonsecure Vector Base Address */
+	mcr	p15, 0, r6, c12, c0, 0
+	/* FCSE PID */
+	mcr	p15, 0, r7, c13, c0, 0
+	/* Context PID */
+	mcr	p15, 0, r8, c13, c0, 1
+
+	ldmia	r3!, {r4-r5}
+	/* primary memory remap register */
+	mcr	p15, 0, r4, c10, c2, 0
+	/*normal memory remap register */
+	mcr	p15, 0, r5, c10, c2, 1
+
+	/* Restore cpsr */
+	ldmfd	r3!, {r4}	/*load CPSR from SDRAM*/
+	msr	cpsr, r4	/*store cpsr */
+	dsb
+	isb
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
+	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
+	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
+	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
+
+	adr	r5, mmu_on
+	mov	r1, #0xcfffffff
+	and	r5, r5, r1
+	ldr	r1, =0x30000000
+	orr	r5, r5, r1
+	mov	r4, r5
+
+	/* Move the DDR out of self refresh mode */
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	/* Program MPMC Control Status register in Misc Space */
+	ldr	r0, [r6, #0x334]
+	/* Clear srefresh_enter bit(2) */
+	bic	r0, r0, #0x4
+	str	r0, [r6, #0x334]
+	/* Additional clearance is required in the mpmc space */
+	ldr	r0, [r7, #0x2c]
+	/*
+	 * Clear bit srefresh bit (2) of MPMC_11 register
+	 * The misc wrapper does not works fine by itself till
+	 * this bit is also cleared.
+	 */
+	bic	r0, r0, #0x10000
+	str	r0, [r7, #0x2c]
+wait_for_refresh_exit:
+	ldr	r0, [r6, #0x334]
+	tst	r0, #0x2000
+	bne	wait_for_refresh_exit
+
+	ldmfd	r3!, {r2}
+	/* restore the MMU control register from stack to enable mmu */
+	mcr	p15, 0, r2, c1, c0, 0
+	bx	r4
+
+mmu_on:
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+	nop
+
+MPMC_BASE_P :
+	.word MPMC_BASE_PA
+MISC_BASE_P :
+	.word MISC_BASE_PA
+SRAM_STACK_VA :
+	.word IO_ADDRESS(SPEAR_SRAM_STACK_PA)
+SRAM_STACK_PA :
+	.word SPEAR_SRAM_STACK_PA
+DISABLE_I_C_M_V:
+	.word 0x1805
+MISC_PLL_OFFS:
+	.word 0x214
+#ifdef DDR_PLL_SREFRESH
+PLL_VAL1:
+	.word 0x060a
+PLL_VAL2:
+	.word 0x060e
+PLL_VAL3:
+	.word 0x0606
+#endif
+ENTRY(spear_sleep_mode_sz)
+	.word	. - spear_sleep_mode
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index cdf132e..08e87d7 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -464,6 +464,11 @@ struct map_desc spear13xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR13XX_SYSRAM0_BASE),
 		.length		= SZ_32K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR13XX_SYSRAM1_BASE),
+		.pfn		= __phys_to_pfn(SPEAR13XX_SYSRAM1_BASE),
+		.length		= SZ_1M,
+		.type		= MT_MEMORY_NONCACHED
 	},
 };
 
diff --git a/arch/arm/mach-spear3xx/include/mach/suspend.h b/arch/arm/mach-spear3xx/include/mach/suspend.h
new file mode 100644
index 0000000..a525173
--- /dev/null
+++ b/arch/arm/mach-spear3xx/include/mach/suspend.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-spear3xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr3xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/spear.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR3XX_ICM1_SRAM_BASE
+#define SPEAR_SRAM_SIZE		SZ_4K
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define SYS_CTRL_BASE_PA	SPEAR3XX_ICM3_SYS_CTRL_BASE
+#define MPMC_BASE_PA		SPEAR3XX_ICM3_SDRAM_CTRL_BASE
+#define MISC_BASE_PA		SPEAR3XX_ICM3_MISC_REG_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index c9727ac..2dfa9d5 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -22,6 +22,8 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 
+#define SPEAR3XX_WKUP_SRCS	(1 << IRQ_MAC_1 | 1 << IRQ_USB_DEV | \
+				1 << IRQ_BASIC_RTC | 1 << IRQ_BASIC_GPIO)
 /* Add spear3xx machines common devices here */
 /* gpio device registeration */
 static struct pl061_platform_data gpio_plat_data = {
@@ -246,7 +248,8 @@ void __init spear3xx_init(void)
 /* This will initialize vic */
 void __init spear3xx_init_irq(void)
 {
-	vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0, 0);
+	vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0,
+			SPEAR3XX_WKUP_SRCS);
 }
 
 /* Following will create static virtual/physical mappings */
diff --git a/arch/arm/mach-spear6xx/include/mach/suspend.h b/arch/arm/mach-spear6xx/include/mach/suspend.h
new file mode 100644
index 0000000..e98e831
--- /dev/null
+++ b/arch/arm/mach-spear6xx/include/mach/suspend.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-spear6xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr6xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/spear.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR6XX_ICM1_SRAM_BASE
+#define SPEAR_SRAM_SIZE		SZ_4K
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define SYS_CTRL_BASE_PA	SPEAR6XX_ICM3_SYS_CTRL_BASE
+#define MPMC_BASE_PA		SPEAR6XX_ICM3_SDRAM_CTRL_BASE
+#define MISC_BASE_PA		SPEAR6XX_ICM3_MISC_REG_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index cc2692e..8334841 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -24,6 +24,12 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 
+/* The wake sources are routed through vic-2 */
+#define SPEAR6XX_WKUP_SRCS_VIC2		(1 << (IRQ_GMAC_1 - 32) | \
+					1 << (IRQ_USB_DEV - 32) | \
+					1 << (IRQ_BASIC_RTC - 32) |\
+					1 << (IRQ_BASIC_GPIO - 32))
+
 /* Add spear6xx machines common devices here */
 
 /* CLCD device registration */
@@ -400,7 +406,8 @@ void __init spear6xx_init(void)
 void __init spear6xx_init_irq(void)
 {
 	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_PRI_BASE, 0, ~0, 0);
-	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0, 0);
+	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0,
+			SPEAR6XX_WKUP_SRCS_VIC2);
 }
 
 /* Following will create static virtual/physical mappings */
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 0e2cf75..1c8ee4a 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -6,6 +6,7 @@
 obj-y	:= clcd.o clock.o pll_clk.o smi.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
+
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 obj-$(CONFIG_SPEAR_PWM)		+= pwm.o
@@ -16,3 +17,8 @@ obj-$(CONFIG_BOARD_SPEAR300_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR310_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR320_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR600_EVB)	+= i2c_eval_board.o
+
+ifeq ($(CONFIG_PM),y)
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= pm.o sleep.o
+obj-$(CONFIG_ARCH_SPEAR6XX)	+= pm.o sleep.o
+endif
diff --git a/arch/arm/plat-spear/pm.c b/arch/arm/plat-spear/pm.c
new file mode 100644
index 0000000..df7c7a1
--- /dev/null
+++ b/arch/arm/plat-spear/pm.c
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/plat-spear/pm.c
+ *
+ * SPEAr3xx & SPEAr6xx Power Management source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri <deepak.sikri at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/suspend.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <mach/irqs.h>
+#include <mach/suspend.h>
+
+static void (*saved_idle)(void);
+static void __iomem *spear_sram_base;
+
+static int spear_pm_sleep(suspend_state_t state)
+{
+	void (*spear_sram_sleep)(suspend_state_t state) = NULL;
+
+	/* Copy the Sleep code on to the SRAM*/
+	spear_sram_sleep = memcpy((void *)spear_sram_base,
+			(void *)spear_sleep_mode, spear_sleep_mode_sz);
+	flush_cache_all();
+	/* Jump to the suspend routines in sram */
+	spear_sram_sleep(state);
+	return 0;
+}
+
+/*
+ *	spear_pm_prepare - Do preliminary suspend work.
+ *
+ */
+static int spear_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+	return 0;
+}
+
+/*
+ *	spear_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+static int spear_pm_enter(suspend_state_t state)
+{
+	int ret;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = spear_pm_sleep(state);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ *	spear_pm_finish - Finish up suspend sequence.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+static void spear_pm_finish(void)
+{
+	pm_idle = saved_idle;
+}
+
+static const struct platform_suspend_ops spear_pm_ops = {
+	.prepare	= spear_pm_prepare,
+	.enter		= spear_pm_enter,
+	.finish		= spear_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int __init spear_pm_init(void)
+{
+
+	spear_sram_base = ioremap(SPEAR_START_SRAM, SPEAR_SRAM_SIZE);
+
+	if (!spear_sram_base)
+		return -ENOMEM;
+
+	/* In case the suspend code size is more than sram size return */
+	if (spear_sleep_mode_sz > (SPEAR_SRAM_SIZE))
+		return	-ENOMEM;
+
+	suspend_set_ops(&spear_pm_ops);
+	return 0;
+}
+arch_initcall(spear_pm_init);
diff --git a/arch/arm/plat-spear/sleep.S b/arch/arm/plat-spear/sleep.S
new file mode 100644
index 0000000..5347789
--- /dev/null
+++ b/arch/arm/plat-spear/sleep.S
@@ -0,0 +1,288 @@
+/*
+ * arch/arm/plat-spear/sleep.S
+ *
+ * SPEAR3xx and SPEAR6xx specific functions that will run in
+ * internal SRAM. The functions are used in power management.
+ *
+ * Copyright (ST) 2010 Deepak Sikri <deepak.sikri at .com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+.text
+ENTRY(spear_sleep_mode)
+	stmfd	sp!, {r0-r12, lr}
+
+	/* Latch some of MMU registers on to stack */
+	mrc	p15, 0, r0, c5, c0, 0 /* FSR--Domain Fault */
+	mrc	p15, 0, r1, c5, c0, 1 /* FSR--Instruction Fault */
+	mrc	p15, 0, r2, c6, c0, 0 /* FAR */
+	mrc	p15, 0, r3, c9, c0, 0 /* Read Dcache Lockdown */
+	mrc	p15, 0, r4, c9, c0, 1 /* Read ICache Lockdown */
+	mrc	p15, 0, r5, c9, c1, 0 /* Read Data TLB */
+	mrc	p15, 0, r6, c9, c1, 1 /* Read Instr TCM region register */
+
+	mrc	p15, 0, r7, c10, c0, 0 /* Data TLBLock Down operation */
+	mrc	p15, 0, r8, c13, c0, 0 /* FCSE--PID */
+	mrc	p15, 0, r9, c13, c0, 1 /* Context-ID */
+
+	/* Save all these registers onto the stack */
+	stmfd	sp!, {r0-r9}
+	/* Save the stack pointer */
+	mov	r3, sp
+	/* Store the two mode registers */
+	stmfd	r3!, {sp, lr}
+	/* Save the current mode with irq disabled */
+	mrs	r0, cpsr
+	stmfd	r3!, {r0}
+	/*
+	 * Save the MMU registers on the SRAM Stack
+	 * Domain Register on Back-up RAM structure
+	 */
+	mrc	p15, 0, r2, c3, c0, 0
+	/* TTB Register */
+	mrc	p15, 0, r1, c2, c0, 0
+	/* MMU Enable Register */
+	mrc	p15, 0, r0, c1, c0, 0
+	stmfd	r3!, {r0, r1, r2}
+	/*
+	 * Capture the Physical Address.
+	 * This will be used once MMU is Off
+	 */
+	adr	r0, mmu_off
+	adr	r1, spear_sleep_mode
+	/* Store the virtual address on to DDR */
+	stmfd	r3!, {r1}
+	sub	r1, r0, r1
+	ldr	r0, SRAM_START_P
+	add	r2, r1, r0
+
+	/* Disable MMU */
+	mrc	p15, 0, r0, c1, c0, 0
+	ldr	r1, DISABLE_I_C_M_V
+	bic	r0, r0, r1
+	mcr	p15, 0, r0, c1, c0, 0
+	/* Move the Physical address into PC */
+	bx	r2
+
+	/*
+	 * This portion of code is executed from SRAM
+	 * post MMU has been turned off
+	 */
+mmu_off:
+	/* Store the DDR stack address onto scratch pad location */
+	ldr	r0, SCRATCH_PAD
+	str	r3, [r0]
+
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	ldr	r8, SYS_CTRL_BASE_P
+
+	/*
+	 * Put SDRAM in self-refresh mode
+	 * Clear START bit(24) of MEMCTL_GP_03 register in MPMC
+	 */
+	ldr	r0, [r7, #0x1c]
+	ldr	r4, =0x1000000
+	/* Begin the command processing in controller */
+	bic	r0, r0, r4
+	str	r0, [r7, #0x1c]
+	ldr	r0, [r7, #0x1c]
+	/* set the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	orr	r0, r0, r4
+	str	r0, [r7, #0x1c]
+
+	/* Put the DDR into low power mode */
+	ldr	r0, [r6, #0xf0]
+	ldr	r4, =0x00000001
+	/* Clear DDR_LOW_POWER_DDR2_MODE bit(1) of DDR_PAD register */
+	bic	r0, r0, r4
+	str	r0, [r6, #0xf0]
+
+	/* Put the system in slow mode, use system controller */
+	ldr	r0, [r8]
+	bic	r0, r0, #0x4
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x2
+	str	r0, [r8]	/* System is now in slow mode */
+
+wait_till_slow_mode:
+	ldr	r0, [r8]
+	and	r0, r0, #0x78	/* Wait for the mode to be updated */
+	cmp	r0, #0x10	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_slow_mode
+
+	/* Put the Pll-1 to off. */
+	ldr	r0, [r6, #0x08]
+	/* Clear pll_enable bit(2) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, #0x08]
+
+	/* Put the Pll-2 to off */
+	ldr	r0, [r6, #0x14]
+	/* Clear pll_enable bit(2) of PLL2_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, #0x14]
+	mov	r2, #0
+	/* Put the system in sleep */
+	ldr	r0, [r8]
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	bic	r0, r0, #0x7
+#ifdef TEST_SLOW
+	orr	r0, r0, #0x2 /* Slow Mode */
+#endif
+	str	r0, [r8]
+	/* Put system in WFI */
+	mcr	p15, 0, r2, c7, c0, 4
+wakeup_addr:
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	ldr	r8, SYS_CTRL_BASE_P
+	/* Reenable pll1 and pll2 */
+	ldr	r0, PLL_VAL1
+	str	r0, [r6, #0x08]
+	str	r0, [r6, #0x14]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, #0x08]
+	str	r0, [r6, #0x14]
+	/* Strobe */
+	ldr	r2, PLL_VAL3
+	str	r2, [r6, #0x08]
+	str	r2, [r6, #0x14]
+	ldr	r2, PLL_VAL2
+	str	r2, [r6, #0x08]
+	str	r2, [r6, #0x14]
+pll1_lock_1:
+	/* Set the pll_lock bit(0) in PLL1_CTR register in misc space*/
+	ldr	r2, [r6, #0x08]
+	and	r2, r2, #0x1
+	/* Wait for pll-1 lock status */
+	cmp	r2, #0x1
+	bne	pll1_lock_1
+
+pll2_lock_2:
+	/* Set the pll_lock bit(0) in PLL2_CTR register in misc space*/
+	ldr	r2, [r6, #0x14]
+	and	r2, r2, #0x1
+	/* Wait for pll-2 lock status */
+	cmp	r2, #0x1
+	bne	pll2_lock_2
+
+	/* Move the system in Normal mode, use system controller */
+	ldr	r3, [r8]
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	bic	r3, r3, #0x7
+	orr	r3, r3, #0x4
+	str	r3, [r8]
+
+wait_till_norm_mode:
+	ldr	r3, [r8]
+	and	r3, r3, #0x78
+	cmp	r3, #0x20	/* Poll the SCCTRL register status bits (6:3) */
+	bne	wait_till_norm_mode
+
+	/* Resume the DDR from Low power mode. */
+	ldr	r0, [r6, #0xf0]
+	/* Set DDR_LOW_POWER_DDR2_MODE bit(1) of DDR_PAD register */
+	orr	r0, r0, #0x01
+	str	r0, [r6, #0xf0]
+
+	/* Exit DDR-SDRAM from self-refresh mode */
+	ldr	r1, [r7, #0x1c]
+	/* clear the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	bic	r1, r1, r4
+	str	r1, [r7, #0x1c]
+
+	/* Begin the command processing in controller */
+	ldr	r4, =0x1000000
+	/* Set START bit(24) of MEMCTL_GP_03 register in MPMC*/
+	orr	r1, r1, r4
+	str	r1, [r7, #0x1c]
+
+	mov	r0, r0
+	/* Start the Restore Processing */
+	ldr	r0, SCRATCH_PAD
+	ldr	r6, [r0]
+
+	/* Restore the Virtual Address to be used */
+	/* Once MMU is made on */
+	ldr	r0, SRAM_START_P
+	adr	r1, mmu_on
+	sub	r0, r1, r0
+	/* Get the physical Address */
+	mov	r3, #0xc0000000
+	sub	r6, r6, r3
+	/* Fetch the sram virtual address */
+	ldmfd	r6!, {r1}
+	add	r4, r1, r0
+
+	/* Fetch the MMU Related information latched on SDRAM */
+	ldmfd	r6!, {r0, r1, r2}
+	/* Enable the MMU */
+	mcr	p15, 0, r2, c3, c0, 0
+	mcr	p15, 0, r1, c2, c0, 0
+	mcr	p15, 0, r0, c1, c0, 0
+	bx	r4
+mmu_on:
+	add	r6, r6, r3
+	/* Store the value of cpsr in R0 */
+	mrs	r0, cpsr
+	bic	r0, r0, #MODE_BITS
+
+	/* Here we will restore our cpsr IRQ/FIQ Disabled */
+	ldr	r0, [r6]
+	msr	cpsr_cxsf, r0
+	add	r6, r6, #4
+
+	/* Now only two user-mode registers are left */
+	ldmfd	r6!, {sp, lr}
+	mov	r0, r0
+
+	/* Restore stack pointer for the current mode */
+	mov	sp, r6
+
+	ldmfd	sp!, {r0-r9}
+	mcr	p15, 0, r0, c5, c0, 0 /* FSR--Domain Fault */
+	mcr	p15, 0, r1, c5, c0, 1 /* FSR--Instruction Fault */
+	mcr	p15, 0, r2, c6, c0, 0 /* FAR */
+	mcr	p15, 0, r3, c9, c0, 0 /* Read Dcache Lockdown */
+	mcr	p15, 0, r4, c9, c0, 1 /* Read ICache Lockdown */
+	mcr 	p15, 0, r5, c9, c1, 0 /* Read Data TLB */
+	mcr	p15, 0, r6, c9, c1, 1 /* Read Instruction Lockdown */
+
+	mcr	p15, 0, r7, c10, c0, 0 /* Data TLB LockDown operation */
+	mcr	p15, 0, r8, c13, c0, 0 /* FCSE--PID */
+	mcr	p15, 0, r9, c13, c0, 1 /* Context-ID */
+
+	mov	r0, #0
+	ldmfd	sp!, {r0-r12, pc}
+
+SYS_CTRL_BASE_P :
+	.word SYS_CTRL_BASE_PA
+MPMC_BASE_P :
+	.word MPMC_BASE_PA
+MISC_BASE_P :
+	.word MISC_BASE_PA
+SRAM_START_P:
+	.word SPEAR_START_SRAM
+SCRATCH_PAD:
+	.word SPEAR_SRAM_SCR_REG
+DISABLE_I_C_M_V:
+	.word 0x1005
+PLL_VAL1:
+	.word 0x1c0a
+PLL_VAL2:
+	.word 0x1c0e
+PLL_VAL3:
+	.word 0x1c06
+ENTRY(spear_sleep_mode_sz)
+	.word . - spear_sleep_mode
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:56 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:56 +0530
Subject: [PATCH V2 36/69] ST SPEAr: Adding miscellaneous devices
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <f230f323b2dc881014ae3e5759f3424af7c8aa75.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/include/mach/generic.h |    7 ++
 arch/arm/mach-spear3xx/spear310.c             |  115 +++++++++++++++++++------
 arch/arm/mach-spear3xx/spear320.c             |   26 ++++++
 3 files changed, 123 insertions(+), 25 deletions(-)

diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 9bd9424..ea170a6 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -161,6 +161,11 @@ extern struct clcd_board clcd_plat_data;
 /* spear310 declarations */
 #elif defined(CONFIG_MACH_SPEAR310)
 /* Add spear310 machine device structure declarations here */
+extern struct amba_device uart1_device;
+extern struct amba_device uart2_device;
+extern struct amba_device uart3_device;
+extern struct amba_device uart4_device;
+extern struct amba_device uart5_device;
 extern struct platform_device plgpio_device;
 extern struct platform_device nand_device;
 
@@ -182,6 +187,8 @@ void __init spear310_init(void);
 /* Add spear320 machine device structure declarations here */
 extern struct amba_device clcd_device;
 extern struct amba_device ssp_device[];
+extern struct amba_device uart1_device;
+extern struct amba_device uart2_device;
 extern struct platform_device i2c1_device;
 extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 189e3d4..25a0e94 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -142,6 +142,96 @@ struct pmx_driver pmx_driver = {
 };
 
 /* Add spear310 specific devices here */
+/* uart1 device registeration */
+struct amba_device uart1_device = {
+	.dev = {
+		.init_name = "uart1",
+	},
+	.res = {
+		.start = SPEAR310_UART1_BASE,
+		.end = SPEAR310_UART1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART1, NO_IRQ},
+};
+
+/* uart2 device registeration */
+struct amba_device uart2_device = {
+	.dev = {
+		.init_name = "uart2",
+	},
+	.res = {
+		.start = SPEAR310_UART2_BASE,
+		.end = SPEAR310_UART2_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART2, NO_IRQ},
+};
+
+/* uart3 device registeration */
+struct amba_device uart3_device = {
+	.dev = {
+		.init_name = "uart3",
+	},
+	.res = {
+		.start = SPEAR310_UART3_BASE,
+		.end = SPEAR310_UART3_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART3, NO_IRQ},
+};
+
+/* uart4 device registeration */
+struct amba_device uart4_device = {
+	.dev = {
+		.init_name = "uart4",
+	},
+	.res = {
+		.start = SPEAR310_UART4_BASE,
+		.end = SPEAR310_UART4_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART4, NO_IRQ},
+};
+
+/* uart5 device registeration */
+struct amba_device uart5_device = {
+	.dev = {
+		.init_name = "uart5",
+	},
+	.res = {
+		.start = SPEAR310_UART5_BASE,
+		.end = SPEAR310_UART5_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART5, NO_IRQ},
+};
+
+/* nand device registeration */
+static struct fsmc_nand_platform_data nand_platform_data;
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR310_NAND_BASE,
+		.end = SPEAR310_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR310_FSMC_BASE,
+		.end = SPEAR310_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand_device = {
+	.name = "nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+	.dev.platform_data = &nand_platform_data,
+};
+
 /* plgpio device registeration */
 /*
  * pin to offset and offset to pin converter functions
@@ -178,31 +268,6 @@ int spear300_o2p(int offset)
 		return offset + 2;
 }
 
-/* nand device registeration */
-static struct fsmc_nand_platform_data nand_platform_data;
-
-static struct resource nand_resources[] = {
-	{
-		.name = "nand_data",
-		.start = SPEAR310_NAND_BASE,
-		.end = SPEAR310_NAND_BASE + SZ_16 - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.name = "fsmc_regs",
-		.start = SPEAR310_FSMC_BASE,
-		.end = SPEAR310_FSMC_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device nand_device = {
-	.name = "nand",
-	.id = -1,
-	.resource = nand_resources,
-	.num_resources = ARRAY_SIZE(nand_resources),
-	.dev.platform_data = &nand_platform_data,
-};
-
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
 	.irq_base = SPEAR_PLGPIO_INT_BASE,
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 3f1c88b..8ecad40 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -447,6 +447,32 @@ struct amba_device ssp_device[] = {
 	}
 };
 
+/* uart1 device registeration */
+struct amba_device uart1_device = {
+	.dev = {
+		.init_name = "uart1",
+	},
+	.res = {
+		.start = SPEAR320_UART1_BASE,
+		.end = SPEAR320_UART1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART1, NO_IRQ},
+};
+
+/* uart2 device registeration */
+struct amba_device uart2_device = {
+	.dev = {
+		.init_name = "uart2",
+	},
+	.res = {
+		.start = SPEAR320_UART2_BASE,
+		.end = SPEAR320_UART2_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_UART2, NO_IRQ},
+};
+
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:49 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:49 +0530
Subject: [PATCH V2 29/69] Newly erased page read workaround
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <0420ee3d85bb74f000c7c5f35e0c615f4779d9ad.1285933331.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

A newly erased page contains ff in data as well as spare area. While reading an
erased page, the read out ecc from spare area does not match the ecc generated
by fsmc ecc hardware accelarator. This is because ecc of data ff ff is not ff
ff. This leads to errors when jffs2 fs erases and reads back the pages to
ensure consistency.

This patch adds a software workaround to ensure that the ecc check is not
performed for erased pages. An erased page is checked by checking data as ff ff.

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   28 ++++++++++++++++++++++------
 1 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 2ca48fc..5d659df 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -382,7 +382,7 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
 	struct fsmc_eccplace *ecc_place = host->ecc_place;
-	int i, j, s, stat, eccsize = chip->ecc.size;
+	int i, j, k, s, stat, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
 	u8 *p = buf;
@@ -422,11 +422,27 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 		memcpy(&ecc_code[i], oob, 13);
 		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
-		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
-		if (stat < 0)
-			mtd->ecc_stats.failed++;
-		else
-			mtd->ecc_stats.corrected += stat;
+		/*
+		 * This is a temporary erase check. A newly erased page read
+		 * would result in an ecc error because the oob data is also
+		 * erased to FF and the calculated ecc for an FF data is not
+		 * FF..FF.
+		 * This is a workaround to skip performing correction in case
+		 * data is FF..FF
+		 */
+		for (k = 0; k < eccsize; k++) {
+			if (*(p + k) != 0xff)
+				break;
+		}
+
+		if (k < eccsize) {
+			stat = chip->ecc.correct(mtd, p, &ecc_code[i],
+					&ecc_calc[i]);
+			if (stat < 0)
+				mtd->ecc_stats.failed++;
+			else
+				mtd->ecc_stats.corrected += stat;
+		}
 	}
 
 	return 0;
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:04 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:04 +0530
Subject: [PATCH V2 44/69] SPEAr CPU freq: Adding support for CPU Freq framework
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <0260f7ebc3d1dd80c3bb40faefc946e35f9436fd.1285933332.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri at st.com>

Signed-off-by: Deepak Sikri <deepak.sikri at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/Kconfig                |    1 +
 arch/arm/mach-spear13xx/clock.c |    1 +
 arch/arm/mach-spear3xx/clock.c  |    1 +
 arch/arm/mach-spear6xx/clock.c  |    1 +
 arch/arm/plat-spear/Makefile    |    2 +-
 arch/arm/plat-spear/cpufreq.c   |  159 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 164 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/plat-spear/cpufreq.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 158bf06..cdd0a2b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -821,6 +821,7 @@ config PLAT_SPEAR
 	select COMMON_CLKDEV
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
+	select ARCH_HAS_CPUFREQ
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 4f320fa..79942a9 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -91,6 +91,7 @@ static struct pll_clk_config pll1_config = {
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	/* PCLK 24MHz */
+	{.mode = 0, .m = 0x64, .n = 0x03, .p = 0x2}, /* 400 MHz */
 	{.mode = 0, .m = 0x7D, .n = 0x03, .p = 0x2}, /* 500 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x03, .p = 0x2}, /* 664 MHz */
 	{.mode = 0, .m = 0xC8, .n = 0x03, .p = 0x2}, /* 800 MHz */
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 4f049fe..64d9cdc 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -55,6 +55,7 @@ static struct pll_clk_masks pll_masks = {
 
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* 166 MHz */
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 99cc21d..f1429f5 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -55,6 +55,7 @@ static struct pll_clk_masks pll_masks = {
 
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* 166 MHz */
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 1c8ee4a..c25e5b8 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -6,7 +6,7 @@
 obj-y	:= clcd.o clock.o pll_clk.o smi.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
-
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 obj-$(CONFIG_SPEAR_PWM)		+= pwm.o
diff --git a/arch/arm/plat-spear/cpufreq.c b/arch/arm/plat-spear/cpufreq.c
new file mode 100644
index 0000000..9384d65
--- /dev/null
+++ b/arch/arm/plat-spear/cpufreq.c
@@ -0,0 +1,159 @@
+/*
+ * arch/arm/plat-spear/cpufreq.c
+ *
+ * CPU Frequency Scaling for SPEAr platform
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri<deepak.sikri at st.com>
+ *
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+
+#define CPU_CLK		"cpu_clk"
+
+#ifdef CONFIG_ARCH_SPEAR13XX
+#define MIN_CPU_FREQ	200000
+#define MAX_CPU_FREQ	500000
+
+static u32 spear_cpu_freq[] = {
+	200000,	/* 200 MHZ */
+	250000,	/* 250 MHZ */
+	332000,	/* 332 MHZ */
+	400000,	/* 400 MHZ */
+	500000,	/* 500 MHZ */
+};
+#elif defined(CONFIG_ARCH_SPEAR6XX) || defined(CONFIG_ARCH_SPEAR3XX)
+#define MIN_CPU_FREQ	166000
+#define MAX_CPU_FREQ	332000
+
+static u32 spear_cpu_freq[] = {
+	166000,	/* 166 MHZ */
+	266000,	/* 266 MHZ */
+	332000,	/* 333 MHZ */
+};
+#endif
+
+static struct
+	cpufreq_frequency_table spear_freq_tbl[ARRAY_SIZE(spear_cpu_freq) + 1];
+static struct clk *cpu_clk;
+
+int spear_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, spear_freq_tbl);
+}
+
+unsigned int spear_cpufreq_get(unsigned int cpu)
+{
+	unsigned long rate;
+
+	if (cpu)
+		return 0;
+
+	rate = clk_get_rate(cpu_clk) / 1000;
+	return rate;
+}
+
+static int spear_cpufreq_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	int ret = 0;
+	int index;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, spear_freq_tbl,
+				target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.old = spear_cpufreq_get(0);
+	freqs.new = spear_cpu_freq[index];
+	freqs.cpu = policy->cpu;
+
+	if (freqs.old == target_freq)
+		return 0;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return ret;
+}
+
+static int spear_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int result;
+	int i = 0;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	cpu_clk = clk_get(NULL, CPU_CLK);
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	policy->cpuinfo.min_freq = MIN_CPU_FREQ;
+	policy->cpuinfo.max_freq = MAX_CPU_FREQ;
+	policy->cur = policy->min = policy->max = spear_cpufreq_get(0);
+
+	for (i = 0; i < ARRAY_SIZE(spear_cpu_freq); i++) {
+		spear_freq_tbl[i].index = i;
+		spear_freq_tbl[i].frequency = spear_cpu_freq[i];
+	}
+
+	spear_freq_tbl[i].index = i;
+	spear_freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+	result = cpufreq_frequency_table_cpuinfo(policy, spear_freq_tbl);
+	if (!result)
+		cpufreq_frequency_table_get_attr(spear_freq_tbl,
+				policy->cpu);
+
+	policy->cpuinfo.transition_latency = 300*1000; /*250 uS*/
+
+	return 0;
+}
+
+static int spear_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	clk_put(cpu_clk);
+	return 0;
+}
+
+static struct freq_attr *spear_cpufreq_attr[] = {
+	 &cpufreq_freq_attr_scaling_available_freqs,
+	 NULL,
+};
+
+static struct cpufreq_driver spear_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= spear_cpufreq_verify,
+	.target		= spear_cpufreq_target,
+	.get		= spear_cpufreq_get,
+	.init		= spear_cpufreq_init,
+	.exit		= spear_cpufreq_exit,
+	.name		= "spear_cpufreq",
+	.attr		= spear_cpufreq_attr,
+};
+
+static int __init spear_cpufreq_register(void)
+{
+	return cpufreq_register_driver(&spear_driver);
+}
+
+arch_initcall(spear_cpufreq_register);
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:06 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:06 +0530
Subject: [PATCH V2 46/69] ST SPEAr13xx: Adding machine support for pci gadget
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <52b8b1701090d726b3af6b79b98cd967229113d8.1285933332.git.viresh.kumar@st.com>

From: Pratyush Anand <pratyush.anand at st.com>

Signed-off-by: Pratyush Anand <pratyush.anand at st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    3 +
 arch/arm/mach-spear13xx/include/mach/spear.h   |    2 +-
 arch/arm/mach-spear13xx/spear1300_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear1310_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear13xx.c            |   94 ++++++++++++++++++++++++
 5 files changed, 100 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 9b0f009..56ed7a7 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -40,6 +40,9 @@ extern struct platform_device spear13xx_kbd_device;
 extern struct platform_device spear13xx_nand_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
+extern struct platform_device spear13xx_pcie_gadget0_device;
+extern struct platform_device spear13xx_pcie_gadget1_device;
+extern struct platform_device spear13xx_pcie_gadget2_device;
 extern struct platform_device spear13xx_rtc_device;
 extern struct platform_device spear13xx_sdhci_device;
 extern struct platform_device spear13xx_smi_device;
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index cf25eb5..d043280 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -60,7 +60,7 @@
 #define SPEAR13XX_SYS_LOCATION		(SPEAR13XX_SYSRAM0_BASE + 0x600)
 
 #define SPEAR13XX_SYSRAM1_BASE		UL(0xE0800000)
-#define SPEAR13XX_SYSRAM1_SIZE		0x00800000
+#define SPEAR13XX_SYSRAM1_SIZE		0x00001000
 #define SPEAR13XX_CLCD_BASE		UL(0xE1000000)
 #define SPEAR13XX_C3_BASE		UL(0xE1800000)
 #define SPEAR13XX_GETH_BASE		UL(0xE2000000)
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index e56fbd4..34e2647 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -52,6 +52,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_nand_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
+	&spear13xx_pcie_gadget0_device,
 	&spear13xx_rtc_device,
 	&spear13xx_sdhci_device,
 	&spear13xx_smi_device,
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index f6b4323..1af152f 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -53,6 +53,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_nand_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
+	&spear13xx_pcie_gadget0_device,
 	&spear13xx_rtc_device,
 	&spear13xx_sdhci_device,
 	&spear13xx_smi_device,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 08e87d7..c86bd1c 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -429,6 +429,100 @@ struct platform_device spear13xx_sdhci_device = {
 	.resource = sdhci_resources,
 };
 
+/* pcie gadget registration */
+static struct resource pcie_gadget0_resources[] = {
+	{
+		.start = SPEAR13XX_PCIE0_APP_BASE,
+		.end = SPEAR13XX_PCIE0_APP_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR13XX_PCIE0_BASE,
+		.end = SPEAR13XX_PCIE0_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_PCIE0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* pcie_gadget0_id defaults to 0, being static variable */
+static int pcie_gadget0_id;
+static u64 pcie_gadget0_dmamask = ~0;
+
+struct platform_device spear13xx_pcie_gadget0_device = {
+	.name = "pcie-gadget-spear",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &pcie_gadget0_dmamask,
+		.platform_data = &pcie_gadget0_id,
+	},
+	.num_resources = ARRAY_SIZE(pcie_gadget0_resources),
+	.resource = pcie_gadget0_resources,
+};
+
+static struct resource pcie_gadget1_resources[] = {
+	{
+		.start = SPEAR13XX_PCIE1_APP_BASE,
+		.end = SPEAR13XX_PCIE1_APP_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR13XX_PCIE1_BASE,
+		.end = SPEAR13XX_PCIE1_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_PCIE1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* pcie_gadget1_id defaults to 0, being static variable */
+static int pcie_gadget1_id;
+static u64 pcie_gadget1_dmamask = ~0;
+
+struct platform_device spear13xx_pcie_gadget1_device = {
+	.name = "pcie-gadget-spear",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &pcie_gadget1_dmamask,
+		.platform_data = &pcie_gadget1_id,
+	},
+	.num_resources = ARRAY_SIZE(pcie_gadget1_resources),
+	.resource = pcie_gadget1_resources,
+};
+
+static struct resource pcie_gadget2_resources[] = {
+	{
+		.start = SPEAR13XX_PCIE2_APP_BASE,
+		.end = SPEAR13XX_PCIE2_APP_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR13XX_PCIE2_BASE,
+		.end = SPEAR13XX_PCIE2_BASE + SZ_8K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_PCIE2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* pcie_gadget2_id defaults to 0, being static variable */
+static int pcie_gadget2_id;
+static u64 pcie_gadget2_dmamask = ~0;
+
+struct platform_device spear13xx_pcie_gadget2_device = {
+	.name = "pcie-gadget-spear",
+	.id = 2,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &pcie_gadget2_dmamask,
+		.platform_data = &pcie_gadget2_id,
+	},
+	.num_resources = ARRAY_SIZE(pcie_gadget2_resources),
+	.resource = pcie_gadget2_resources,
+};
+
 /* Do spear13xx familiy common initialization part here */
 void __init spear13xx_init(void)
 {
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:17 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:17 +0530
Subject: [PATCH V2 57/69] SPEAr3xx: Make local structures static
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <a4419b75d9a8f793c745d89e1cd0ba5d23880bd1.1285933332.git.viresh.kumar@st.com>

From: Ryan Mallon <ryan at bluewatersys.com>

Several structures in arch/arm/mach-spear3xx are not marked static
like they should be. Fix this.

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/spear300.c |    6 +++---
 arch/arm/mach-spear3xx/spear310.c |   16 ++++++++--------
 arch/arm/mach-spear3xx/spear320.c |   12 ++++++------
 arch/arm/mach-spear3xx/spear3xx.c |    2 --
 4 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 9885fe9..bbaf872 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -114,7 +114,6 @@ struct pmx_mode caml_lcd_mode = {
 	.value = 0x0F,
 };
 
-/* devices */
 /* Pad multiplexing for FSMC 2 NAND devices */
 static struct pmx_mux_reg pmx_fsmc_2_mux[] = {
 	{
@@ -700,7 +699,7 @@ struct platform_device sdhci_device = {
 };
 
 /* spear3xx shared irq */
-struct shirq_dev_config shirq_ras1_config[] = {
+static struct shirq_dev_config shirq_ras1_config[] = {
 	{
 		.virq = VIRQ_IT_PERS_S,
 		.enb_mask = IT_PERS_S_IRQ_MASK,
@@ -740,7 +739,8 @@ struct shirq_dev_config shirq_ras1_config[] = {
 	},
 };
 
-struct spear_shirq shirq_ras1 = {
+
+static struct spear_shirq shirq_ras1 = {
 	.irq = IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index be2f9de..7d4ff0e 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -363,7 +363,7 @@ struct platform_device plgpio_device = {
 
 
 /* spear3xx shared irq */
-struct shirq_dev_config shirq_ras1_config[] = {
+static struct shirq_dev_config shirq_ras1_config[] = {
 	{
 		.virq = VIRQ_SMII0,
 		.status_mask = SMII0_IRQ_MASK,
@@ -391,7 +391,7 @@ struct shirq_dev_config shirq_ras1_config[] = {
 	},
 };
 
-struct spear_shirq shirq_ras1 = {
+static struct spear_shirq shirq_ras1 = {
 	.irq = IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
@@ -403,7 +403,7 @@ struct spear_shirq shirq_ras1 = {
 	},
 };
 
-struct shirq_dev_config shirq_ras2_config[] = {
+static struct shirq_dev_config shirq_ras2_config[] = {
 	{
 		.virq = VIRQ_UART1,
 		.status_mask = UART1_IRQ_MASK,
@@ -422,7 +422,7 @@ struct shirq_dev_config shirq_ras2_config[] = {
 	},
 };
 
-struct spear_shirq shirq_ras2 = {
+static struct spear_shirq shirq_ras2 = {
 	.irq = IRQ_GEN_RAS_2,
 	.dev_config = shirq_ras2_config,
 	.dev_count = ARRAY_SIZE(shirq_ras2_config),
@@ -434,14 +434,14 @@ struct spear_shirq shirq_ras2 = {
 	},
 };
 
-struct shirq_dev_config shirq_ras3_config[] = {
+static struct shirq_dev_config shirq_ras3_config[] = {
 	{
 		.virq = VIRQ_EMI,
 		.status_mask = EMI_IRQ_MASK,
 	},
 };
 
-struct spear_shirq shirq_ras3 = {
+static struct spear_shirq shirq_ras3 = {
 	.irq = IRQ_GEN_RAS_3,
 	.dev_config = shirq_ras3_config,
 	.dev_count = ARRAY_SIZE(shirq_ras3_config),
@@ -453,7 +453,7 @@ struct spear_shirq shirq_ras3 = {
 	},
 };
 
-struct shirq_dev_config shirq_intrcomm_ras_config[] = {
+static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	{
 		.virq = VIRQ_TDM_HDLC,
 		.status_mask = TDM_HDLC_IRQ_MASK,
@@ -466,7 +466,7 @@ struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	},
 };
 
-struct spear_shirq shirq_intrcomm_ras = {
+static struct spear_shirq shirq_intrcomm_ras = {
 	.irq = IRQ_INTRCOMM_RAS_ARM,
 	.dev_config = shirq_intrcomm_ras_config,
 	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index bd308b8..948ca8e 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -835,7 +835,7 @@ struct platform_device sdhci_device = {
 };
 
 /* spear3xx shared irq */
-struct shirq_dev_config shirq_ras1_config[] = {
+static struct shirq_dev_config shirq_ras1_config[] = {
 	{
 		.virq = VIRQ_EMI,
 		.status_mask = EMI_IRQ_MASK,
@@ -851,7 +851,7 @@ struct shirq_dev_config shirq_ras1_config[] = {
 	},
 };
 
-struct spear_shirq shirq_ras1 = {
+static struct spear_shirq shirq_ras1 = {
 	.irq = IRQ_GEN_RAS_1,
 	.dev_config = shirq_ras1_config,
 	.dev_count = ARRAY_SIZE(shirq_ras1_config),
@@ -864,7 +864,7 @@ struct spear_shirq shirq_ras1 = {
 	},
 };
 
-struct shirq_dev_config shirq_ras3_config[] = {
+static struct shirq_dev_config shirq_ras3_config[] = {
 	{
 		.virq = VIRQ_PLGPIO,
 		.enb_mask = GPIO_IRQ_MASK,
@@ -883,7 +883,7 @@ struct shirq_dev_config shirq_ras3_config[] = {
 	},
 };
 
-struct spear_shirq shirq_ras3 = {
+static struct spear_shirq shirq_ras3 = {
 	.irq = IRQ_GEN_RAS_3,
 	.dev_config = shirq_ras3_config,
 	.dev_count = ARRAY_SIZE(shirq_ras3_config),
@@ -897,7 +897,7 @@ struct spear_shirq shirq_ras3 = {
 	},
 };
 
-struct shirq_dev_config shirq_intrcomm_ras_config[] = {
+static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	{
 		.virq = VIRQ_CANU,
 		.status_mask = CAN_U_IRQ_MASK,
@@ -945,7 +945,7 @@ struct shirq_dev_config shirq_intrcomm_ras_config[] = {
 	},
 };
 
-struct spear_shirq shirq_intrcomm_ras = {
+static struct spear_shirq shirq_intrcomm_ras = {
 	.irq = IRQ_INTRCOMM_RAS_ARM,
 	.dev_config = shirq_intrcomm_ras_config,
 	.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index ec1340c..544072d 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -292,7 +292,6 @@ void __init spear3xx_map_io(void)
 }
 
 /* pad multiplexing support */
-/* devices */
 
 /* Pad multiplexing for firda device */
 static struct pmx_mux_reg pmx_firda_mux[] = {
@@ -625,7 +624,6 @@ struct pmx_dev pmx_timer_1_2 = {
 };
 
 #if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
-/* plgpios devices */
 /* Pad multiplexing for plgpio_0_1 devices */
 static struct pmx_mux_reg pmx_plgpio_0_1_mux[] = {
 	{
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:09 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:09 +0530
Subject: [PATCH V2 49/69] ST SPEAr13xx: add L2 cache support
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <cfeb5d8653735f68acee9dfed7d91e4e2441d329.1285933332.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/spear13xx.c |   19 +++++++++++++++++++
 arch/arm/mm/Kconfig                 |    2 +-
 2 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index c86bd1c..8c8a21d 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -22,6 +22,7 @@
 #include <asm/irq.h>
 #include <asm/localtimer.h>
 #include <asm/mach/arch.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <asm/smp_twd.h>
 #include <mach/irqs.h>
 #include <mach/generic.h>
@@ -526,6 +527,17 @@ struct platform_device spear13xx_pcie_gadget2_device = {
 /* Do spear13xx familiy common initialization part here */
 void __init spear13xx_init(void)
 {
+#ifdef CONFIG_CACHE_L2X0
+	/*
+	 * 512KB (64KB/way), 8-way associativity, parity supported
+	 *
+	 * TODO: 0x249, picked from nomadik, to be analyzed
+	 * Comment from nomadik:
+	 * At full speed latency must be >=2, so 0x249 in low bits
+	 */
+	l2x0_init(__io_address(SPEAR13XX_L2CC_BASE), 0x00260249, 0xfe00ffff);
+#endif
+
 	sdhci_enable();
 }
 
@@ -548,6 +560,13 @@ struct map_desc spear13xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR13XX_A9SM_PERIP_BASE),
 		.length		= SZ_8K,
 		.type		= MT_DEVICE
+#ifdef CONFIG_CACHE_L2X0
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR13XX_L2CC_BASE),
+		.pfn		= __phys_to_pfn(SPEAR13XX_L2CC_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
+#endif
 	}, {
 		.virtual	= IO_ADDRESS(SPEAR13XX_MISC_BASE),
 		.pfn		= __phys_to_pfn(SPEAR13XX_MISC_BASE),
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index a0a2928..f3eea13 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -772,7 +772,7 @@ config CACHE_L2X0
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
 		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
 		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
-		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4
+		   ARCH_SPEAR13XX || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
 	default y
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:54 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:54 +0530
Subject: [PATCH V2 34/69] ST SPEAr: Replacing SIZE macro's with actual
	required size
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <c3401e12797cf90712981251c4b39f89a9d0c112.1285933332.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

In arch specific files SIZE macro's were defined which were used for
creating memory/io mappings for sepecific devices. These macro's are
coming straight from h/w user manual and are much greated than required
sizes. Replacing these macros by actual required size.

Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/spear300.c |    9 +++------
 arch/arm/mach-spear3xx/spear310.c |    2 +-
 arch/arm/mach-spear3xx/spear320.c |    2 +-
 arch/arm/mach-spear3xx/spear3xx.c |    8 ++++----
 arch/arm/mach-spear6xx/spear6xx.c |   10 +++++-----
 5 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index c299e52..03e050b 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -604,8 +604,7 @@ struct spear_shirq shirq_ras1 = {
 void sdhci_i2s_mem_enable(u8 mask)
 {
 	u32 val;
-	void __iomem *base = ioremap(SPEAR300_SOC_CONFIG_BASE,
-			SPEAR300_SOC_CONFIG_SIZE);
+	void __iomem *base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
 	if (!base) {
 		pr_debug("sdhci_i2s_enb: ioremap fail\n");
 		return;
@@ -628,8 +627,7 @@ void __init spear300_init(void)
 	spear3xx_init();
 
 	/* shared irq registeration */
-	shirq_ras1.regs.base =
-		ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE);
+	shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
 	if (shirq_ras1.regs.base) {
 		ret = spear_shirq_register(&shirq_ras1);
 		if (ret)
@@ -637,8 +635,7 @@ void __init spear300_init(void)
 	}
 
 	/* pmx initialization */
-	pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE,
-			SPEAR300_SOC_CONFIG_SIZE);
+	pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
 	if (pmx_driver.base) {
 		ret = pmx_register(&pmx_driver);
 		if (ret)
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 1c84303..189e3d4 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -362,7 +362,7 @@ void __init spear310_init(void)
 	spear3xx_init();
 
 	/* shared irq registeration */
-	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index c228286..3f1c88b 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -694,7 +694,7 @@ void __init spear320_init(void)
 	spear3xx_init();
 
 	/* shared irq registeration */
-	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 34d8286..f7b8915 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -254,22 +254,22 @@ struct map_desc spear3xx_io_desc[] __initdata = {
 	{
 		.virtual	= VA_SPEAR3XX_ICM1_UART_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE),
-		.length		= SPEAR3XX_ICM1_UART_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ML1_VIC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE),
-		.length		= SPEAR3XX_ML1_VIC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR3XX_ICM3_SYS_CTRL_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR3XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index e64fc57..f91380e 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -408,27 +408,27 @@ static struct map_desc spear6xx_io_desc[] __initdata = {
 	{
 		.virtual	= VA_SPEAR6XX_ICM1_UART0_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE),
-		.length		= SPEAR6XX_ICM1_UART0_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_PRI_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE),
-		.length		= SPEAR6XX_CPU_VIC_PRI_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_SEC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE),
-		.length		= SPEAR6XX_CPU_VIC_SEC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_BASE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:14 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:14 +0530
Subject: [PATCH V2 54/69] SPEAr : Updating pad multiplexing support
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <28d44ee4486a0621725fbad048014785f40e72a3.1285933332.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar at st.com>

This patch makes the following changes
-> Addition of SPEAr1310 pad multiplexing devices.
-> A few bugfixes eg. clcd1 and clcd2 removed and clcd/clcd_hires added
-> Support for modifying multiple regiters in different address ranges

Signed-off-by: Vipin Kumar <vipin.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |   50 +++-
 arch/arm/mach-spear13xx/include/mach/spear.h   |    3 -
 arch/arm/mach-spear13xx/spear1300.c            |   11 +-
 arch/arm/mach-spear13xx/spear1300_evb.c        |    5 +-
 arch/arm/mach-spear13xx/spear1310.c            |  346 +++++++++++++++++++++++-
 arch/arm/mach-spear13xx/spear1310_evb.c        |   17 +-
 arch/arm/mach-spear13xx/spear13xx.c            |  169 +++++++-----
 arch/arm/mach-spear3xx/include/mach/generic.h  |   12 +-
 arch/arm/mach-spear3xx/include/mach/spear300.h |    1 -
 arch/arm/mach-spear3xx/spear300.c              |   67 ++---
 arch/arm/mach-spear3xx/spear310.c              |   20 +-
 arch/arm/mach-spear3xx/spear320.c              |   61 ++---
 arch/arm/mach-spear3xx/spear3xx.c              |   60 ++--
 arch/arm/plat-spear/include/plat/padmux.h      |   10 +-
 arch/arm/plat-spear/padmux.c                   |   36 ++-
 15 files changed, 626 insertions(+), 242 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 8a0dc8c..f619b70 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -24,10 +24,21 @@
 /*
  * Function enable (Pad multiplexing register) offsets
  */
-#define PAD_MUX_CONFIG_REG_0	0x0
-#define PAD_MUX_CONFIG_REG_1	0x4
-#define PAD_MUX_CONFIG_REG_2	0x8
-#define PAD_MUX_CONFIG_REG_3	0xC
+/* Pad multiplexing base */
+#define SPEAR13XX_FUNC_ENB_BASE		UL(0xE0700650)
+#define SPEAR13XX_PCM_CFG_BASE		UL(0xE0700100)
+
+#define PAD_MUX_CONFIG_REG_0	UL(0xE0700650)
+#define PAD_MUX_CONFIG_REG_1	UL(0xE0700654)
+#define PAD_MUX_CONFIG_REG_2	UL(0xE0700658)
+#define PAD_MUX_CONFIG_REG_3	UL(0xE070065C)
+
+#if defined(CONFIG_MACH_SPEAR1310)
+#define SPEAR1310_FUNC_CNTL_0	UL(0x6C800000)
+
+#define PMX_SMII_MASK		(1 << 24)	/* Func cntl reg0 */
+#define PMX_EGPIO7_MASK		(1 << 2)	/* Pcm cfg reg */
+#endif
 
 /* pad mux declarations */
 #define PMX_I2S1_MASK		(1 << 3)
@@ -111,9 +122,8 @@
 #define PMX_KBD_ROWCOL68_MASK	(1 << 4)	/* Offset 4 */
 #define PMX_KBD_COL0_MASK	(1 << 21)	/* Offset 4 */
 #define PMX_KBD_COL1_MASK	(1 << 19)	/* Offset 4 */
-#define PMX_KEYBOARD_MASK	(PMX_KBD_ROW0_MASK | PMX_KBD_ROW1_MASK | \
-		PMX_KBD_ROWCOL25_MASK | PMX_KBD_ROWCOL68_MASK | \
-		PMX_KBD_COL0_MASK | PMX_KBD_COL1_MASK)
+#define PMX_KEYBOARD_6X6_MASK	(PMX_KBD_ROW0_MASK | PMX_KBD_ROW1_MASK | \
+		PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL0_MASK | PMX_KBD_COL1_MASK)
 
 #define PMX_UART0_MASK		(1 << 1)
 #define PMX_I2C_MASK		(1 << 2)
@@ -164,16 +174,18 @@
 /* pad mux devices */
 extern struct pmx_dev pmx_i2c;
 extern struct pmx_dev pmx_ssp;
+extern struct pmx_dev pmx_i2s1;
 extern struct pmx_dev pmx_i2s2;
-extern struct pmx_dev pmx_clcd1;
-extern struct pmx_dev pmx_clcd2;
+extern struct pmx_dev pmx_clcd;
+extern struct pmx_dev pmx_clcd_hires;
 extern struct pmx_dev pmx_egpio_grp;
 extern struct pmx_dev pmx_smi_2_chips;
 extern struct pmx_dev pmx_smi_4_chips;
 extern struct pmx_dev pmx_gmii;
 extern struct pmx_dev pmx_nand_8bit;
 extern struct pmx_dev pmx_nand_16bit;
-extern struct pmx_dev pmx_keyboard;
+extern struct pmx_dev pmx_keyboard_6x6;
+extern struct pmx_dev pmx_keyboard_9x9;
 extern struct pmx_dev pmx_uart0;
 extern struct pmx_dev pmx_uart0_modem;
 extern struct pmx_dev pmx_gpt_0_1;
@@ -182,6 +194,24 @@ extern struct pmx_dev pmx_gpt_1_1;
 extern struct pmx_dev pmx_gpt_1_2;
 extern struct pmx_dev pmx_mcif;
 
+#if defined(CONFIG_MACH_SPEAR1310)
+extern struct pmx_dev pmx_uart1_modem;
+extern struct pmx_dev pmx_uart_1;
+extern struct pmx_dev pmx_uart_2;
+extern struct pmx_dev pmx_uart_3_4_5;
+extern struct pmx_dev pmx_rs485_hdlc_1_2;
+extern struct pmx_dev pmx_tdm_hdlc_1_2;
+extern struct pmx_dev pmx_nand32bit;
+extern struct pmx_dev pmx_fsmc16bit_4_chips;
+extern struct pmx_dev pmx_fsmc32bit_4_chips;
+extern struct pmx_dev pmx_gmii1;
+extern struct pmx_dev pmx_rgmii;
+extern struct pmx_dev pmx_i2c1;
+extern struct pmx_dev pmx_smii_0_1_2;
+extern struct pmx_dev pmx_can;
+extern struct pmx_dev pmx_uart1_modem;
+#endif
+
 /*
  * Each GPT has 2 timer channels
  * Following GPT channels will be used as clock source and clockevent
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 03f9616..d043280 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -88,9 +88,6 @@
 #define SPEAR13XX_MCIF_CF_BASE		UL(0xB2800000)
 #define SPEAR13XX_MCIF_SDHCI_BASE	UL(0xB3000000)
 
-/* Pad multiplexing base */
-#define SPEAR13XX_FUNC_ENB_BASE		UL(0xE0700650)
-
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR13XX_UART_BASE
 #define VA_SPEAR_DBG_UART_BASE		VA_SPEAR13XX_UART_BASE
diff --git a/arch/arm/mach-spear13xx/spear1300.c b/arch/arm/mach-spear13xx/spear1300.c
index 4569cb5..28822a3 100644
--- a/arch/arm/mach-spear13xx/spear1300.c
+++ b/arch/arm/mach-spear13xx/spear1300.c
@@ -27,12 +27,7 @@ void __init spear1300_init(void)
 	spear13xx_init();
 
 	/* pmx initialization */
-	pmx_driver.base = ioremap(SPEAR13XX_FUNC_ENB_BASE, SZ_4K);
-	if (pmx_driver.base) {
-		ret = pmx_register(&pmx_driver);
-		if (ret)
-			pr_err("padmux: registeration failed. err no: %d\n",
-					ret);
-		iounmap(pmx_driver.base);
-	}
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index e35a496..ceb3bd0 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -43,11 +43,10 @@ static struct pmx_dev *pmx_devs[] = {
 	&pmx_i2c,
 	&pmx_i2s1,
 	&pmx_i2s2,
-	&pmx_clcd1,
-	&pmx_clcd2,
+	&pmx_clcd,
 	&pmx_egpio_grp,
 	&pmx_gmii,
-	&pmx_keyboard,
+	&pmx_keyboard_6x6,
 	&pmx_mcif,
 	&pmx_nand_8bit,
 	&pmx_smi_4_chips,
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index cd0878e..39ea491 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -19,6 +19,341 @@
 /* pmx driver structure */
 struct pmx_driver pmx_driver;
 
+/* Pad multiplexing for uart1_modem device */
+static struct pmx_mux_reg pmx_uart1_modem_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2S1_MASK | PMX_SSP_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
+	{
+		.mux_regs = pmx_uart1_modem_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_modem_mux),
+	},
+};
+
+struct pmx_dev pmx_uart1_modem = {
+	.name = "uart1_modem",
+	.modes = pmx_uart1_modem_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
+};
+
+/* Pad multiplexing for uart1 device */
+static struct pmx_mux_reg pmx_uart1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modes[] = {
+	{
+		.mux_regs = pmx_uart1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_1 = {
+	.name = "uart1",
+	.modes = pmx_uart1_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
+};
+
+/* Pad multiplexing for uart2 device */
+static struct pmx_mux_reg pmx_uart2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK | PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart2_modes[] = {
+	{
+		.mux_regs = pmx_uart2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart2_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_2 = {
+	.name = "uart2",
+	.modes = pmx_uart2_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
+};
+
+/* Pad multiplexing for uart_3_4_5 device */
+static struct pmx_mux_reg pmx_uart_3_4_5_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart_3_4_5_modes[] = {
+	{
+		.mux_regs = pmx_uart_3_4_5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart_3_4_5_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_3_4_5 = {
+	.name = "uart_3_4_5",
+	.modes = pmx_uart_3_4_5_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart_3_4_5_modes),
+};
+
+/* Pad multiplexing for rs485_hdlc_1_2 device */
+static struct pmx_mux_reg pmx_rs485_hdlc_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_rs485_hdlc_1_2_modes[] = {
+	{
+		.mux_regs = pmx_rs485_hdlc_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_rs485_hdlc_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_rs485_hdlc_1_2 = {
+	.name = "rs485_hdlc_1_2",
+	.modes = pmx_rs485_hdlc_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_rs485_hdlc_1_2_modes),
+};
+
+/* Pad multiplexing for tdm_hdlc_1_2 device */
+static struct pmx_mux_reg pmx_tdm_hdlc_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_tdm_hdlc_1_2_modes[] = {
+	{
+		.mux_regs = pmx_tdm_hdlc_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_tdm_hdlc_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_tdm_hdlc_1_2 = {
+	.name = "tdm_hdlc_1_2",
+	.modes = pmx_tdm_hdlc_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_tdm_hdlc_1_2_modes),
+};
+
+/* Pad multiplexing for fsmc32bit device */
+static struct pmx_mux_reg pmx_fsmc32bit_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_EGPIO_0_GRP_MASK | PMX_SMI_MASK | \
+			PMX_NAND16BIT4DEV_0_MASK | PMX_CLCD1_MASK,
+		.value = 0,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_NAND16BIT4DEV_1_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR13XX_PCM_CFG_BASE,
+		.mask = PMX_EGPIO7_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc32bit_modes[] = {
+	{
+		.mux_regs = pmx_fsmc32bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc32bit_mux),
+	},
+};
+
+struct pmx_dev pmx_fsmc32bit_4_chips = {
+	.name = "fsmc32bit",
+	.modes = pmx_fsmc32bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_fsmc32bit_modes),
+};
+
+/* Pad multiplexing for fsmc16bit device */
+static struct pmx_mux_reg pmx_fsmc16bit_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT4DEV_0_MASK,
+		.value = 0,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_NAND16BIT4DEV_1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc16bit_modes[] = {
+	{
+		.mux_regs = pmx_fsmc16bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc16bit_mux),
+	},
+};
+
+struct pmx_dev pmx_fsmc16bit_4_chips = {
+	.name = "fsmc16bit",
+	.modes = pmx_fsmc16bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_fsmc16bit_modes),
+};
+
+/* Pad multiplexing for gmii1 device */
+static struct pmx_mux_reg pmx_gmii1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_gmii1_modes[] = {
+	{
+		.mux_regs = pmx_gmii1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gmii1_mux),
+	},
+};
+
+struct pmx_dev pmx_gmii1 = {
+	.name = "gmii1",
+	.modes = pmx_gmii1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gmii1_modes),
+};
+
+/* Pad multiplexing for rgmii device */
+static struct pmx_mux_reg pmx_rgmii_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_rgmii_modes[] = {
+	{
+		.mux_regs = pmx_rgmii_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_rgmii_mux),
+	},
+};
+
+struct pmx_dev pmx_rgmii = {
+	.name = "rgmii",
+	.modes = pmx_rgmii_modes,
+	.mode_count = ARRAY_SIZE(pmx_rgmii_modes),
+};
+
+/* Pad multiplexing for i2c1 device */
+static struct pmx_mux_reg pmx_i2c1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c1_modes[] = {
+	{
+		.mux_regs = pmx_i2c1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c1_mux),
+	},
+};
+
+struct pmx_dev pmx_i2c1 = {
+	.name = "i2c1",
+	.modes = pmx_i2c1_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2c1_modes),
+};
+
+/* Pad multiplexing for smii_0_1_2 device */
+static struct pmx_mux_reg pmx_smii_0_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK | PMX_KBD_ROWCOL68_MASK | \
+			PMX_EGPIO_1_GRP_MASK | PMX_GPT0_TMR1_MASK | \
+			PMX_GPT0_TMR2_MASK | PMX_GPT1_TMR1_MASK | \
+			PMX_GPT1_TMR2_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR1310_FUNC_CNTL_0,
+		.mask = PMX_SMII_MASK,
+		.value = PMX_SMII_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smii_0_1_2_modes[] = {
+	{
+		.mux_regs = pmx_smii_0_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smii_0_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_smii_0_1_2 = {
+	.name = "smii_0_1_2",
+	.modes = pmx_smii_0_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_smii_0_1_2_modes),
+};
+
+/* Pad multiplexing for pci1 device */
+static struct pmx_mux_reg pmx_pci1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK | PMX_KBD_ROWCOL68_MASK | \
+			PMX_EGPIO_1_GRP_MASK | PMX_GPT0_TMR1_MASK | \
+			PMX_GPT0_TMR2_MASK | PMX_GPT1_TMR1_MASK | \
+			PMX_GPT1_TMR2_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR1310_FUNC_CNTL_0,
+		.mask = PMX_SMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pci1_modes[] = {
+	{
+		.mux_regs = pmx_pci1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pci1_mux),
+	},
+};
+
+struct pmx_dev pmx_pci1 = {
+	.name = "pci1",
+	.modes = pmx_pci1_modes,
+	.mode_count = ARRAY_SIZE(pmx_pci1_modes),
+};
+
+/* Pad multiplexing for can device */
+static struct pmx_mux_reg pmx_can_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_I2S2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_can_modes[] = {
+	{
+		.mux_regs = pmx_can_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_can_mux),
+	},
+};
+
+struct pmx_dev pmx_can = {
+	.name = "can",
+	.modes = pmx_can_modes,
+	.mode_count = ARRAY_SIZE(pmx_can_modes),
+};
+
 /* Add spear1310 specific devices here */
 
 /* CAN device registeration */
@@ -66,12 +401,7 @@ void __init spear1310_init(void)
 	spear13xx_init();
 
 	/* pmx initialization */
-	pmx_driver.base = ioremap(SPEAR13XX_FUNC_ENB_BASE, SZ_4K);
-	if (pmx_driver.base) {
-		ret = pmx_register(&pmx_driver);
-		if (ret)
-			pr_err("padmux: registeration failed. err no: %d\n",
-					ret);
-		iounmap(pmx_driver.base);
-	}
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index 87f27cf..c4b83b2 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -41,19 +41,24 @@ static struct pmx_dev *pmx_devs[] = {
 	/* spear13xx specific devices */
 	&pmx_i2c,
 	&pmx_i2s1,
-	&pmx_i2s2,
-	&pmx_clcd1,
-	&pmx_clcd2,
 	&pmx_egpio_grp,
 	&pmx_gmii,
-	&pmx_keyboard,
+	&pmx_keyboard_6x6,
 	&pmx_mcif,
 	&pmx_nand_8bit,
-	&pmx_smi_4_chips,
-	&pmx_ssp,
+	&pmx_smi_2_chips,
 	&pmx_uart0,
 
 	/* spear1310 specific devices */
+	&pmx_can,
+	&pmx_i2c1,
+	&pmx_smii_0_1_2,
+	&pmx_fsmc16bit_4_chips,
+	&pmx_rs485_hdlc_1_2,
+	&pmx_tdm_hdlc_1_2,
+	&pmx_uart_1,
+	&pmx_uart_2,
+	&pmx_uart_3_4_5,
 };
 
 static struct amba_device *amba_devs[] __initdata = {
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 623dffd..fd66db1 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -644,7 +644,7 @@ struct sys_timer spear13xx_timer = {
 /* Pad multiplexing for i2c device */
 static struct pmx_mux_reg pmx_i2c_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_I2C_MASK,
 		.value = PMX_I2C_MASK,
 	},
@@ -666,7 +666,7 @@ struct pmx_dev pmx_i2c = {
 /* Pad multiplexing for ssp device */
 static struct pmx_mux_reg pmx_ssp_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_SSP_MASK,
 		.value = PMX_SSP_MASK,
 	},
@@ -688,7 +688,7 @@ struct pmx_dev pmx_ssp = {
 /* Pad multiplexing for i2s1 device */
 static struct pmx_mux_reg pmx_i2s1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_I2S1_MASK,
 		.value = PMX_I2S1_MASK,
 	},
@@ -710,7 +710,7 @@ struct pmx_dev pmx_i2s1 = {
 /* Pad multiplexing for i2s2 device */
 static struct pmx_mux_reg pmx_i2s2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_I2S2_MASK,
 		.value = PMX_I2S2_MASK,
 	},
@@ -729,48 +729,52 @@ struct pmx_dev pmx_i2s2 = {
 	.mode_count = ARRAY_SIZE(pmx_i2s2_modes),
 };
 
-/* Pad multiplexing for clcd1 device */
-static struct pmx_mux_reg pmx_clcd1_mux[] = {
+/* Pad multiplexing for clcd device */
+static struct pmx_mux_reg pmx_clcd_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_CLCD1_MASK,
 		.value = PMX_CLCD1_MASK,
 	},
 };
 
-static struct pmx_dev_mode pmx_clcd1_modes[] = {
+static struct pmx_dev_mode pmx_clcd_modes[] = {
 	{
-		.mux_regs = pmx_clcd1_mux,
-		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd1_mux),
+		.mux_regs = pmx_clcd_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_mux),
 	},
 };
 
-struct pmx_dev pmx_clcd1 = {
-	.name = "clcd1",
-	.modes = pmx_clcd1_modes,
-	.mode_count = ARRAY_SIZE(pmx_clcd1_modes),
+struct pmx_dev pmx_clcd = {
+	.name = "clcd",
+	.modes = pmx_clcd_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
 };
 
-/* Pad multiplexing for clcd2 device */
-static struct pmx_mux_reg pmx_clcd2_mux[] = {
+/* Pad multiplexing for clcd_hires device */
+static struct pmx_mux_reg pmx_clcd_hires_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = PMX_CLCD1_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_CLCD2_MASK,
 		.value = PMX_CLCD2_MASK,
 	},
 };
 
-static struct pmx_dev_mode pmx_clcd2_modes[] = {
+static struct pmx_dev_mode pmx_clcd_hires_modes[] = {
 	{
-		.mux_regs = pmx_clcd2_mux,
-		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd2_mux),
+		.mux_regs = pmx_clcd_hires_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_hires_mux),
 	},
 };
 
-struct pmx_dev pmx_clcd2 = {
-	.name = "clcd2",
-	.modes = pmx_clcd2_modes,
-	.mode_count = ARRAY_SIZE(pmx_clcd2_modes),
+struct pmx_dev pmx_clcd_hires = {
+	.name = "clcd_high_res",
+	.modes = pmx_clcd_hires_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd_hires_modes),
 };
 
 /*
@@ -779,11 +783,11 @@ struct pmx_dev pmx_clcd2 = {
  */
 static struct pmx_mux_reg pmx_egpio_grp_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_EGPIO_0_GRP_MASK,
 		.value = PMX_EGPIO_0_GRP_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_EGPIO_1_GRP_MASK,
 		.value = PMX_EGPIO_1_GRP_MASK,
 	},
@@ -805,7 +809,7 @@ struct pmx_dev pmx_egpio_grp = {
 /* Pad multiplexing for smi 2 chips device */
 static struct pmx_mux_reg pmx_smi_2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_SMI_MASK,
 		.value = PMX_SMI_MASK,
 	},
@@ -827,11 +831,11 @@ struct pmx_dev pmx_smi_2_chips = {
 /* Pad multiplexing for smi 4 chips device */
 static struct pmx_mux_reg pmx_smi_4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_SMI_MASK,
 		.value = PMX_SMI_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
 		.value = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
 	},
@@ -853,7 +857,7 @@ struct pmx_dev pmx_smi_4_chips = {
 /* Pad multiplexing for gmii device */
 static struct pmx_mux_reg pmx_gmii_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_GMII_MASK,
 		.value = PMX_GMII_MASK,
 	},
@@ -875,13 +879,13 @@ struct pmx_dev pmx_gmii = {
 /* Pad multiplexing for nand 8bit (4 chips) */
 static struct pmx_mux_reg pmx_nand8_4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_NAND8BIT4DEV_0_MASK,
 		.value = PMX_NAND8BIT4DEV_0_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
-		.mask = PMX_NAND8BIT4DEV_1_MASK,
-		.value = PMX_NAND8BIT4DEV_1_MASK,
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND8BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
 	},
 };
 
@@ -898,16 +902,16 @@ struct pmx_dev pmx_nand_8bit_4_chips = {
 	.mode_count = ARRAY_SIZE(pmx_nand8_4_modes),
 };
 
-/* Pad multiplexing for nand 8bit device */
+/* Pad multiplexing for nand 8bit device (cs0 only) */
 static struct pmx_mux_reg pmx_nand8_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_NAND8BIT_0_MASK,
 		.value = PMX_NAND8BIT_0_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
-		.mask = PMX_NAND8BIT_1_MASK,
-		.value = PMX_NAND8BIT_1_MASK,
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND8BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
 	},
 };
 
@@ -932,13 +936,13 @@ struct pmx_dev pmx_nand_8bit = {
  */
 static struct pmx_mux_reg pmx_nand16_4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_NAND16BIT4DEV_0_MASK,
 		.value = PMX_NAND16BIT4DEV_0_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
-		.mask = PMX_NAND16BIT4DEV_1_MASK,
-		.value = PMX_NAND16BIT4DEV_1_MASK,
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND16BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
 	},
 };
 
@@ -955,16 +959,16 @@ struct pmx_dev pmx_nand_16bit_4_chips = {
 	.mode_count = ARRAY_SIZE(pmx_nand16_4_modes),
 };
 
-/* Pad multiplexing for nand 16bit device */
+/* Pad multiplexing for nand 16bit device (cs0 only) */
 static struct pmx_mux_reg pmx_nand16_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_NAND16BIT_0_MASK,
 		.value = PMX_NAND16BIT_0_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
-		.mask = PMX_NAND16BIT_1_MASK,
-		.value = PMX_NAND16BIT_1_MASK,
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND16BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
 	},
 };
 
@@ -981,37 +985,64 @@ struct pmx_dev pmx_nand_16bit = {
 	.mode_count = ARRAY_SIZE(pmx_nand16_modes),
 };
 
-/* Pad multiplexing for keyboard device */
-static struct pmx_mux_reg pmx_keyboard_mux[] = {
+/* Pad multiplexing for keyboard_6x6 device */
+static struct pmx_mux_reg pmx_keyboard_6x6_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
-		.mask = PMX_KEYBOARD_MASK,
-		.value = PMX_KEYBOARD_MASK,
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_KEYBOARD_6X6_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_NFIO815_MASK | PMX_NFCE1_MASK | \
 			PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK,
 		.value = 0,
 	},
 };
 
-static struct pmx_dev_mode pmx_keyboard_modes[] = {
+static struct pmx_dev_mode pmx_keyboard_6x6_modes[] = {
 	{
-		.mux_regs = pmx_keyboard_mux,
-		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_mux),
+		.mux_regs = pmx_keyboard_6x6_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_6x6_mux),
 	},
 };
 
-struct pmx_dev pmx_keyboard = {
-	.name = "keyboard",
-	.modes = pmx_keyboard_modes,
-	.mode_count = ARRAY_SIZE(pmx_keyboard_modes),
+struct pmx_dev pmx_keyboard_6x6 = {
+	.name = "keyboard_6x6",
+	.modes = pmx_keyboard_6x6_modes,
+	.mode_count = ARRAY_SIZE(pmx_keyboard_6x6_modes),
+};
+
+/* Pad multiplexing for keyboard_9x9 device */
+static struct pmx_mux_reg pmx_keyboard_9x9_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_KBD_ROWCOL68_MASK,
+		.value = PMX_KEYBOARD_6X6_MASK | PMX_KBD_ROWCOL68_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NFIO815_MASK | PMX_NFCE1_MASK | \
+			PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_keyboard_9x9_modes[] = {
+	{
+		.mux_regs = pmx_keyboard_9x9_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_9x9_mux),
+	},
+};
+
+struct pmx_dev pmx_keyboard_9x9 = {
+	.name = "keyboard_9x9",
+	.modes = pmx_keyboard_9x9_modes,
+	.mode_count = ARRAY_SIZE(pmx_keyboard_9x9_modes),
 };
 
 /* Pad multiplexing for uart0 device */
 static struct pmx_mux_reg pmx_uart0_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_0,
+		.address = PAD_MUX_CONFIG_REG_0,
 		.mask = PMX_UART0_MASK,
 		.value = PMX_UART0_MASK,
 	},
@@ -1033,7 +1064,7 @@ struct pmx_dev pmx_uart0 = {
 /* Pad multiplexing for uart0_modem device */
 static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = PMX_UART0_MODEM_MASK,
 	},
@@ -1055,7 +1086,7 @@ struct pmx_dev pmx_uart0_modem = {
 /* Pad multiplexing for gpt_0_1 device */
 static struct pmx_mux_reg pmx_gpt_0_1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_GPT0_TMR1_MASK,
 		.value = PMX_GPT0_TMR1_MASK,
 	},
@@ -1077,7 +1108,7 @@ struct pmx_dev pmx_gpt_0_1 = {
 /* Pad multiplexing for gpt_0_2 device */
 static struct pmx_mux_reg pmx_gpt_0_2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_GPT0_TMR2_MASK,
 		.value = PMX_GPT0_TMR2_MASK,
 	},
@@ -1099,7 +1130,7 @@ struct pmx_dev pmx_gpt_0_2 = {
 /* Pad multiplexing for gpt_1_1 device */
 static struct pmx_mux_reg pmx_gpt_1_1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_GPT1_TMR1_MASK,
 		.value = PMX_GPT1_TMR1_MASK,
 	},
@@ -1121,7 +1152,7 @@ struct pmx_dev pmx_gpt_1_1 = {
 /* Pad multiplexing for gpt_1_2 device */
 static struct pmx_mux_reg pmx_gpt_1_2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_GPT1_TMR2_MASK,
 		.value = PMX_GPT1_TMR2_MASK,
 	},
@@ -1143,11 +1174,11 @@ struct pmx_dev pmx_gpt_1_2 = {
 /* Pad multiplexing for mcif device */
 static struct pmx_mux_reg pmx_mcif_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG_1,
+		.address = PAD_MUX_CONFIG_REG_1,
 		.mask = PMX_MCIFALL_1_MASK,
 		.value = PMX_MCIFALL_1_MASK,
 	}, {
-		.offset = PAD_MUX_CONFIG_REG_2,
+		.address = PAD_MUX_CONFIG_REG_2,
 		.mask = PMX_MCIFALL_2_MASK,
 		.value = PMX_MCIFALL_2_MASK,
 	},
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 1acb93d..1b97ba8 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -148,7 +148,10 @@ extern struct pmx_dev pmx_telecom_boot_pins;
 extern struct pmx_dev pmx_telecom_sdhci_4bit;
 extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
-#define PAD_MUX_CONFIG_REG	0x00
+
+/* pad multiplexing support */
+#define PAD_MUX_CONFIG_REG	0x99000000
+#define MODE_CONFIG_REG		0x99000004
 
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
@@ -180,7 +183,7 @@ extern struct pmx_dev pmx_uart3_4_5;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_rs485_0_1;
 extern struct pmx_dev pmx_tdm0;
-#define PAD_MUX_CONFIG_REG	0x08
+#define PAD_MUX_CONFIG_REG	0xB4000008
 
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
@@ -230,7 +233,10 @@ extern struct pmx_dev pmx_mii1;
 extern struct pmx_dev pmx_smii0;
 extern struct pmx_dev pmx_smii1;
 extern struct pmx_dev pmx_i2c1;
-#define PAD_MUX_CONFIG_REG	0x0C
+
+/* pad multiplexing support */
+#define PAD_MUX_CONFIG_REG	0xB300000C
+#define MODE_CONFIG_REG		0xB3000010
 
 /* Add spear320 machine function declarations here */
 void __init spear320_init(void);
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index c723515..4fd2d22 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -45,7 +45,6 @@
 #define SPEAR300_NOR_2_BASE		UL(0x92000000)
 #define SPEAR300_NOR_3_BASE		UL(0x93000000)
 #define SPEAR300_FSMC_BASE		UL(0x94000000)
-#define SPEAR300_SOC_CONFIG_BASE	UL(0x99000000)
 #define SPEAR300_KEYBOARD_BASE		UL(0xA0000000)
 #define SPEAR300_GPIO_BASE		UL(0xA9000000)
 
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 0a0485d..2671cfd 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -20,9 +20,6 @@
 #include <mach/spear.h>
 #include <plat/shirq.h>
 
-/* pad multiplexing support */
-#define MODE_CONFIG_REG		0x04
-
 /* modes */
 #define NAND_MODE			(1 << 0)
 #define NOR_MODE			(1 << 1)
@@ -121,7 +118,7 @@ struct pmx_mode caml_lcd_mode = {
 /* Pad multiplexing for FSMC 2 NAND devices */
 static struct pmx_mux_reg pmx_fsmc_2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -145,7 +142,7 @@ struct pmx_dev pmx_fsmc_2_chips = {
 /* Pad multiplexing for FSMC 4 NAND devices */
 static struct pmx_mux_reg pmx_fsmc_4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
 		.value = 0,
 	},
@@ -169,7 +166,7 @@ struct pmx_dev pmx_fsmc_4_chips = {
 /* Pad multiplexing for Keyboard device */
 static struct pmx_mux_reg pmx_kbd_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -195,7 +192,7 @@ struct pmx_dev pmx_keyboard = {
 /* Pad multiplexing for CLCD device */
 static struct pmx_mux_reg pmx_clcd_pfmode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -203,7 +200,7 @@ static struct pmx_mux_reg pmx_clcd_pfmode_mux[] = {
 
 static struct pmx_mux_reg pmx_clcd_lcdmode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -231,7 +228,7 @@ struct pmx_dev pmx_clcd = {
 /* Pad multiplexing for Telecom GPIO device */
 static struct pmx_mux_reg pmx_gpio_lcdmode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -239,7 +236,7 @@ static struct pmx_mux_reg pmx_gpio_lcdmode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_fonemode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -247,7 +244,7 @@ static struct pmx_mux_reg pmx_gpio_fonemode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_atai2smode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -255,7 +252,7 @@ static struct pmx_mux_reg pmx_gpio_atai2smode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_lendfonemode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -263,7 +260,7 @@ static struct pmx_mux_reg pmx_gpio_lendfonemode_mux[] = {
 
 static struct pmx_mux_reg pmx_gpio_atawi2smode_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK
 			| PMX_UART0_MODEM_MASK,
 		.value = 0,
@@ -303,7 +300,7 @@ struct pmx_dev pmx_telecom_gpio = {
 /* Pad multiplexing for TDM device */
 static struct pmx_mux_reg pmx_tdm_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -330,7 +327,7 @@ struct pmx_dev pmx_telecom_tdm = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_spi_cs_i2c_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -355,7 +352,7 @@ struct pmx_dev pmx_telecom_spi_cs_i2c_clk = {
 
 static struct pmx_mux_reg pmx_caml_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -363,7 +360,7 @@ static struct pmx_mux_reg pmx_caml_mux[] = {
 
 static struct pmx_mux_reg pmx_camu_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK,
 		.value = 0,
 	},
@@ -390,7 +387,7 @@ struct pmx_dev pmx_telecom_camera = {
 /* Pad multiplexing for dac device */
 static struct pmx_mux_reg pmx_dac_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -414,7 +411,7 @@ struct pmx_dev pmx_telecom_dac = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_i2s_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -440,7 +437,7 @@ struct pmx_dev pmx_telecom_i2s = {
 /* Pad multiplexing for bootpins device */
 static struct pmx_mux_reg pmx_bootpins_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
 		.value = 0,
@@ -464,7 +461,7 @@ struct pmx_dev pmx_telecom_boot_pins = {
 /* Pad multiplexing for sdhci 4bit device */
 static struct pmx_mux_reg pmx_sdhci_4bit_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
 			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
@@ -493,7 +490,7 @@ struct pmx_dev pmx_telecom_sdhci_4bit = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_sdhci_8bit_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
 			PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
@@ -521,7 +518,7 @@ struct pmx_dev pmx_telecom_sdhci_8bit = {
 /* Pad multiplexing for spi cs i2c device */
 static struct pmx_mux_reg pmx_gpio1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK |
 			PMX_TIMER_3_4_MASK,
 		.value = 0,
@@ -544,7 +541,7 @@ struct pmx_dev pmx_gpio1 = {
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
-	.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x0000000f},
+	.mode_reg = {.address = MODE_CONFIG_REG, .mask = 0x0000000f},
 };
 
 /* Add spear300 specific devices here */
@@ -780,18 +777,20 @@ struct spear_shirq shirq_ras1 = {
 void sdhci_i2s_mem_enable(u8 mask)
 {
 	u32 val;
-	void __iomem *base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
-	if (!base) {
+	void __iomem *config = ioremap(MODE_CONFIG_REG, SZ_16);
+	if (!config) {
 		pr_debug("sdhci_i2s_enb: ioremap fail\n");
 		return;
 	}
 
-	val = readl(base + MODE_CONFIG_REG);
+	val = readl(config);
 	if (mask == SDHCI_MEM_ENB)
 		val |= SDHCI_MEM_SELECT;
 	else
 		val &= ~SDHCI_MEM_SELECT;
-	writel(val, base + MODE_CONFIG_REG);
+	writel(val, config);
+
+	iounmap(config);
 }
 
 /* spear300 routines */
@@ -811,13 +810,7 @@ void __init spear300_init(void)
 	}
 
 	/* pmx initialization */
-	pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
-	if (pmx_driver.base) {
-		ret = pmx_register(&pmx_driver);
-		if (ret)
-			printk(KERN_ERR "padmux: registeration failed. err no"
-					": %d\n", ret);
-		/* Free Mapping, device selection already done */
-		iounmap(pmx_driver.base);
-	}
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 548ad56..79f7105 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -26,7 +26,7 @@
 /* Pad multiplexing for emi_cs_0_1_4_5 devices */
 static struct pmx_mux_reg pmx_emi_cs_0_1_4_5_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -48,7 +48,7 @@ struct pmx_dev pmx_emi_cs_0_1_4_5 = {
 /* Pad multiplexing for emi_cs_2_3 devices */
 static struct pmx_mux_reg pmx_emi_cs_2_3_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -70,7 +70,7 @@ struct pmx_dev pmx_emi_cs_2_3 = {
 /* Pad multiplexing for uart1 device */
 static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -92,7 +92,7 @@ struct pmx_dev pmx_uart1 = {
 /* Pad multiplexing for uart2 device */
 static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -114,7 +114,7 @@ struct pmx_dev pmx_uart2 = {
 /* Pad multiplexing for uart3_4_5 devices */
 static struct pmx_mux_reg pmx_uart3_4_5_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -136,7 +136,7 @@ struct pmx_dev pmx_uart3_4_5 = {
 /* Pad multiplexing for fsmc device */
 static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -158,7 +158,7 @@ struct pmx_dev pmx_fsmc = {
 /* Pad multiplexing for rs485_0_1 devices */
 static struct pmx_mux_reg pmx_rs485_0_1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -180,7 +180,7 @@ struct pmx_dev pmx_rs485_0_1 = {
 /* Pad multiplexing for tdm0 device */
 static struct pmx_mux_reg pmx_tdm0_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -524,9 +524,7 @@ void __init spear310_init(void)
 	}
 
 	/* pmx initialization */
-	pmx_driver.base = base;
 	ret = pmx_register(&pmx_driver);
 	if (ret)
-		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
-				ret);
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index c9f5737c..8481955 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -23,9 +23,6 @@
 #include <plat/gpio.h>
 #include <plat/shirq.h>
 
-/* pad multiplexing support */
-#define MODE_CONFIG_REG		0x10
-
 /* modes */
 #define AUTO_NET_SMII_MODE	(1 << 0)
 #define AUTO_NET_MII_MODE	(1 << 1)
@@ -61,7 +58,7 @@ struct pmx_mode small_printers_mode = {
 /* Pad multiplexing for CLCD device */
 static struct pmx_mux_reg pmx_clcd_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -84,7 +81,7 @@ struct pmx_dev pmx_clcd = {
 /* Pad multiplexing for EMI (Parallel NOR flash) device */
 static struct pmx_mux_reg pmx_emi_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -107,7 +104,7 @@ struct pmx_dev pmx_emi = {
 /* Pad multiplexing for FSMC (NAND flash) device */
 static struct pmx_mux_reg pmx_fsmc_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -130,7 +127,7 @@ struct pmx_dev pmx_fsmc = {
 /* Pad multiplexing for SPP device */
 static struct pmx_mux_reg pmx_spp_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -153,7 +150,7 @@ struct pmx_dev pmx_spp = {
 /* Pad multiplexing for SDHCI device */
 static struct pmx_mux_reg pmx_sdhci_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
@@ -177,7 +174,7 @@ struct pmx_dev pmx_sdhci = {
 /* Pad multiplexing for I2S device */
 static struct pmx_mux_reg pmx_i2s_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -200,7 +197,7 @@ struct pmx_dev pmx_i2s = {
 /* Pad multiplexing for UART1 device */
 static struct pmx_mux_reg pmx_uart1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK,
 		.value = 0,
 	},
@@ -223,7 +220,7 @@ struct pmx_dev pmx_uart1 = {
 /* Pad multiplexing for UART1 Modem device */
 static struct pmx_mux_reg pmx_uart1_modem_autoexp_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK |
 			PMX_SSP_CS_MASK,
 		.value = 0,
@@ -232,7 +229,7 @@ static struct pmx_mux_reg pmx_uart1_modem_autoexp_mux[] = {
 
 static struct pmx_mux_reg pmx_uart1_modem_smallpri_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK |
 			PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK,
 		.value = 0,
@@ -260,7 +257,7 @@ struct pmx_dev pmx_uart1_modem = {
 /* Pad multiplexing for UART2 device */
 static struct pmx_mux_reg pmx_uart2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -283,7 +280,7 @@ struct pmx_dev pmx_uart2 = {
 /* Pad multiplexing for Touchscreen device */
 static struct pmx_mux_reg pmx_touchscreen_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -306,7 +303,7 @@ struct pmx_dev pmx_touchscreen = {
 /* Pad multiplexing for CAN device */
 static struct pmx_mux_reg pmx_can_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
 			PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
 		.value = 0,
@@ -330,7 +327,7 @@ struct pmx_dev pmx_can = {
 /* Pad multiplexing for SDHCI LED device */
 static struct pmx_mux_reg pmx_sdhci_led_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -353,7 +350,7 @@ struct pmx_dev pmx_sdhci_led = {
 /* Pad multiplexing for PWM0 device */
 static struct pmx_mux_reg pmx_pwm0_net_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -361,7 +358,7 @@ static struct pmx_mux_reg pmx_pwm0_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm0_autoexpsmallpri_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -388,7 +385,7 @@ struct pmx_dev pmx_pwm0 = {
 /* Pad multiplexing for PWM1 device */
 static struct pmx_mux_reg pmx_pwm1_net_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -396,7 +393,7 @@ static struct pmx_mux_reg pmx_pwm1_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm1_autoexpsmallpri_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -423,7 +420,7 @@ struct pmx_dev pmx_pwm1 = {
 /* Pad multiplexing for PWM2 device */
 static struct pmx_mux_reg pmx_pwm2_net_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -431,7 +428,7 @@ static struct pmx_mux_reg pmx_pwm2_net_mux[] = {
 
 static struct pmx_mux_reg pmx_pwm2_autoexpsmallpri_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -458,7 +455,7 @@ struct pmx_dev pmx_pwm2 = {
 /* Pad multiplexing for PWM3 device */
 static struct pmx_mux_reg pmx_pwm3_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -481,7 +478,7 @@ struct pmx_dev pmx_pwm3 = {
 /* Pad multiplexing for SSP1 device */
 static struct pmx_mux_reg pmx_ssp1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -504,7 +501,7 @@ struct pmx_dev pmx_ssp1 = {
 /* Pad multiplexing for SSP2 device */
 static struct pmx_mux_reg pmx_ssp2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -527,7 +524,7 @@ struct pmx_dev pmx_ssp2 = {
 /* Pad multiplexing for mii1 device */
 static struct pmx_mux_reg pmx_mii1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -550,7 +547,7 @@ struct pmx_dev pmx_mii1 = {
 /* Pad multiplexing for smii0 device */
 static struct pmx_mux_reg pmx_smii0_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -573,7 +570,7 @@ struct pmx_dev pmx_smii0 = {
 /* Pad multiplexing for smii1 device */
 static struct pmx_mux_reg pmx_smii1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -596,7 +593,7 @@ struct pmx_dev pmx_smii1 = {
 /* Pad multiplexing for i2c1 device */
 static struct pmx_mux_reg pmx_i2c1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = 0x0,
 		.value = 0,
 	},
@@ -618,7 +615,7 @@ struct pmx_dev pmx_i2c1 = {
 
 /* pmx driver structure */
 struct pmx_driver pmx_driver = {
-	.mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x00000007},
+	.mode_reg = {.address = MODE_CONFIG_REG, .mask = 0x00000007},
 };
 
 /* Add spear320 specific devices here */
@@ -1019,9 +1016,7 @@ void __init spear320_init(void)
 	}
 
 	/* pmx initialization */
-	pmx_driver.base = base;
 	ret = pmx_register(&pmx_driver);
 	if (ret)
-		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
-				ret);
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 30e3ab8..45a0774 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -297,7 +297,7 @@ void __init spear3xx_map_io(void)
 /* Pad multiplexing for firda device */
 static struct pmx_mux_reg pmx_firda_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = PMX_FIRDA_MASK,
 	},
@@ -320,7 +320,7 @@ struct pmx_dev pmx_firda = {
 /* Pad multiplexing for i2c device */
 static struct pmx_mux_reg pmx_i2c_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
 		.value = PMX_I2C_MASK,
 	},
@@ -343,7 +343,7 @@ struct pmx_dev pmx_i2c = {
 /* Pad multiplexing for firda device */
 static struct pmx_mux_reg pmx_ssp_cs_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = PMX_SSP_CS_MASK,
 	},
@@ -366,7 +366,7 @@ struct pmx_dev pmx_ssp_cs = {
 /* Pad multiplexing for ssp device */
 static struct pmx_mux_reg pmx_ssp_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
 		.value = PMX_SSP_MASK,
 	},
@@ -389,7 +389,7 @@ struct pmx_dev pmx_ssp = {
 /* Pad multiplexing for mii device */
 static struct pmx_mux_reg pmx_mii_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = PMX_MII_MASK,
 	},
@@ -412,7 +412,7 @@ struct pmx_dev pmx_mii = {
 /* Pad multiplexing for gpio pin0 device */
 static struct pmx_mux_reg pmx_gpio_pin0_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
 		.value = PMX_GPIO_PIN0_MASK,
 	},
@@ -435,7 +435,7 @@ struct pmx_dev pmx_gpio_pin0 = {
 /* Pad multiplexing for gpio pin1 device */
 static struct pmx_mux_reg pmx_gpio_pin1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
 		.value = PMX_GPIO_PIN1_MASK,
 	},
@@ -458,7 +458,7 @@ struct pmx_dev pmx_gpio_pin1 = {
 /* Pad multiplexing for gpio pin2 device */
 static struct pmx_mux_reg pmx_gpio_pin2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
 		.value = PMX_GPIO_PIN2_MASK,
 	},
@@ -481,7 +481,7 @@ struct pmx_dev pmx_gpio_pin2 = {
 /* Pad multiplexing for gpio pin3 device */
 static struct pmx_mux_reg pmx_gpio_pin3_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
 		.value = PMX_GPIO_PIN3_MASK,
 	},
@@ -504,7 +504,7 @@ struct pmx_dev pmx_gpio_pin3 = {
 /* Pad multiplexing for gpio pin4 device */
 static struct pmx_mux_reg pmx_gpio_pin4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
 		.value = PMX_GPIO_PIN4_MASK,
 	},
@@ -527,7 +527,7 @@ struct pmx_dev pmx_gpio_pin4 = {
 /* Pad multiplexing for gpio pin5 device */
 static struct pmx_mux_reg pmx_gpio_pin5_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
 		.value = PMX_GPIO_PIN5_MASK,
 	},
@@ -550,7 +550,7 @@ struct pmx_dev pmx_gpio_pin5 = {
 /* Pad multiplexing for uart0 modem device */
 static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = PMX_UART0_MODEM_MASK,
 	},
@@ -573,7 +573,7 @@ struct pmx_dev pmx_uart0_modem = {
 /* Pad multiplexing for uart0 device */
 static struct pmx_mux_reg pmx_uart0_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
 		.value = PMX_UART0_MASK,
 	},
@@ -596,7 +596,7 @@ struct pmx_dev pmx_uart0 = {
 /* Pad multiplexing for timer 3, 4 device */
 static struct pmx_mux_reg pmx_timer_3_4_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = PMX_TIMER_3_4_MASK,
 	},
@@ -619,7 +619,7 @@ struct pmx_dev pmx_timer_3_4 = {
 /* Pad multiplexing for gpio pin0 device */
 static struct pmx_mux_reg pmx_timer_1_2_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = PMX_TIMER_1_2_MASK,
 	},
@@ -644,7 +644,7 @@ struct pmx_dev pmx_timer_1_2 = {
 /* Pad multiplexing for plgpio_0_1 devices */
 static struct pmx_mux_reg pmx_plgpio_0_1_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_FIRDA_MASK,
 		.value = 0,
 	},
@@ -667,7 +667,7 @@ struct pmx_dev pmx_plgpio_0_1 = {
 /* Pad multiplexing for plgpio_2_3 devices */
 static struct pmx_mux_reg pmx_plgpio_2_3_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MASK,
 		.value = 0,
 	},
@@ -690,7 +690,7 @@ struct pmx_dev pmx_plgpio_2_3 = {
 /* Pad multiplexing for plgpio_4_5 devices */
 static struct pmx_mux_reg pmx_plgpio_4_5_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_I2C_MASK,
 		.value = 0,
 	},
@@ -713,7 +713,7 @@ struct pmx_dev pmx_plgpio_4_5 = {
 /* Pad multiplexing for plgpio_6_9 devices */
 static struct pmx_mux_reg pmx_plgpio_6_9_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_MASK,
 		.value = 0,
 	},
@@ -736,7 +736,7 @@ struct pmx_dev pmx_plgpio_6_9 = {
 /* Pad multiplexing for plgpio_10_27 devices */
 static struct pmx_mux_reg pmx_plgpio_10_27_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_MII_MASK,
 		.value = 0,
 	},
@@ -759,7 +759,7 @@ struct pmx_dev pmx_plgpio_10_27 = {
 /* Pad multiplexing for plgpio_28 devices */
 static struct pmx_mux_reg pmx_plgpio_28_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN0_MASK,
 		.value = 0,
 	},
@@ -782,7 +782,7 @@ struct pmx_dev pmx_plgpio_28 = {
 /* Pad multiplexing for plgpio_29 devices */
 static struct pmx_mux_reg pmx_plgpio_29_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN1_MASK,
 		.value = 0,
 	},
@@ -805,7 +805,7 @@ struct pmx_dev pmx_plgpio_29 = {
 /* Pad multiplexing for plgpio_30 device */
 static struct pmx_mux_reg pmx_plgpio_30_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN2_MASK,
 		.value = 0,
 	},
@@ -828,7 +828,7 @@ struct pmx_dev pmx_plgpio_30 = {
 /* Pad multiplexing for plgpio_31 device */
 static struct pmx_mux_reg pmx_plgpio_31_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN3_MASK,
 		.value = 0,
 	},
@@ -851,7 +851,7 @@ struct pmx_dev pmx_plgpio_31 = {
 /* Pad multiplexing for plgpio_32 device */
 static struct pmx_mux_reg pmx_plgpio_32_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN4_MASK,
 		.value = 0,
 	},
@@ -874,7 +874,7 @@ struct pmx_dev pmx_plgpio_32 = {
 /* Pad multiplexing for plgpio_33 device */
 static struct pmx_mux_reg pmx_plgpio_33_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_GPIO_PIN5_MASK,
 		.value = 0,
 	},
@@ -897,7 +897,7 @@ struct pmx_dev pmx_plgpio_33 = {
 /* Pad multiplexing for plgpio_34_36 device */
 static struct pmx_mux_reg pmx_plgpio_34_36_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_SSP_CS_MASK,
 		.value = 0,
 	},
@@ -920,7 +920,7 @@ struct pmx_dev pmx_plgpio_34_36 = {
 /* Pad multiplexing for plgpio_37_42 device */
 static struct pmx_mux_reg pmx_plgpio_37_42_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_UART0_MODEM_MASK,
 		.value = 0,
 	},
@@ -943,7 +943,7 @@ struct pmx_dev pmx_plgpio_37_42 = {
 /* Pad multiplexing for plgpio_43_44_47_48 device */
 static struct pmx_mux_reg pmx_plgpio_43_44_47_48_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_1_2_MASK,
 		.value = 0,
 	},
@@ -966,7 +966,7 @@ struct pmx_dev pmx_plgpio_43_44_47_48 = {
 /* Pad multiplexing for plgpio_45_46_49_50 device */
 static struct pmx_mux_reg pmx_plgpio_45_46_49_50_mux[] = {
 	{
-		.offset = PAD_MUX_CONFIG_REG,
+		.address = PAD_MUX_CONFIG_REG,
 		.mask = PMX_TIMER_3_4_MASK,
 		.value = 0,
 	},
diff --git a/arch/arm/plat-spear/include/plat/padmux.h b/arch/arm/plat-spear/include/plat/padmux.h
index 1b69ca5..1959235 100644
--- a/arch/arm/plat-spear/include/plat/padmux.h
+++ b/arch/arm/plat-spear/include/plat/padmux.h
@@ -19,23 +19,23 @@
 /*
  * struct pmx_reg: configuration structure for mode reg and mux reg
  *
- * offset: offset of mode reg
+ * address: physical address of mode reg
  * mask: mask of mode reg
  */
 struct pmx_reg {
-	u32 offset;
+	u32 address;
 	u32 mask;
 };
 
 /*
  * struct pmx_mux_reg: configuration structure every group of modes of a device
  *
- * offset: multiplexing register offset
+ * address: physical address of multiplexing register
  * mask: mask for supported mode
  * value: value to be written
  */
 struct pmx_mux_reg {
-	u32 offset;
+	u32 address;
 	u32 mask;
 	u32 value;
 };
@@ -87,14 +87,12 @@ struct pmx_dev {
  * mode: mode to be set
  * devs: array of pointer to pmx devices
  * devs_count: ARRAY_SIZE of devs
- * base: base address of soc config registers
  * mode_reg: structure of mode config register
  */
 struct pmx_driver {
 	struct pmx_mode *mode;
 	struct pmx_dev **devs;
 	u8 devs_count;
-	u32 *base;
 	struct pmx_reg mode_reg;
 };
 
diff --git a/arch/arm/plat-spear/padmux.c b/arch/arm/plat-spear/padmux.c
index f30f94b..97e4d96 100644
--- a/arch/arm/plat-spear/padmux.c
+++ b/arch/arm/plat-spear/padmux.c
@@ -19,12 +19,10 @@
 /*
  * struct pmx: pmx definition structure
  *
- * base: base address of configuration registers
  * mode_reg: mode configurations
  * active_mode: pointer to current active mode
  */
 struct pmx {
-	u32 base;
 	struct pmx_reg mode_reg;
 	struct pmx_mode *active_mode;
 };
@@ -40,17 +38,22 @@ static struct pmx *pmx;
  */
 static int pmx_mode_set(struct pmx_mode *mode)
 {
-	u32 val;
+	u32 val, *address;
 
 	if (!mode->name)
 		return -EFAULT;
 
 	pmx->active_mode = mode;
 
-	val = readl(pmx->base + pmx->mode_reg.offset);
-	val &= ~pmx->mode_reg.mask;
-	val |= mode->value & pmx->mode_reg.mask;
-	writel(val, pmx->base + pmx->mode_reg.offset);
+	address = ioremap(pmx->mode_reg.address, SZ_16);
+	if (address) {
+		val = readl(address);
+		val &= ~pmx->mode_reg.mask;
+		val |= mode->value & pmx->mode_reg.mask;
+		writel(val, address);
+
+		iounmap(address);
+	}
 
 	return 0;
 }
@@ -70,6 +73,7 @@ static int pmx_mode_set(struct pmx_mode *mode)
 static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
 {
 	u32 val, i;
+	u32 *address;
 
 	if (!count)
 		return -EINVAL;
@@ -104,10 +108,15 @@ static int pmx_devs_enable(struct pmx_dev **devs, u8 count)
 			struct pmx_mux_reg *mux_reg =
 				&devs[i]->modes[j].mux_regs[k];
 
-			val = readl(pmx->base + mux_reg->offset);
-			val &= ~mux_reg->mask;
-			val |= mux_reg->value & mux_reg->mask;
-			writel(val, pmx->base + mux_reg->offset);
+			address = ioremap(mux_reg->address, SZ_16);
+			if (address) {
+				val = readl(address);
+				val &= ~mux_reg->mask;
+				val |= mux_reg->value & mux_reg->mask;
+				writel(val, address);
+
+				iounmap(address);
+			}
 		}
 
 		devs[i]->is_active = true;
@@ -134,15 +143,14 @@ int pmx_register(struct pmx_driver *driver)
 
 	if (pmx)
 		return -EPERM;
-	if (!driver->base || !driver->devs)
+	if (!driver->devs)
 		return -EFAULT;
 
 	pmx = kzalloc(sizeof(*pmx), GFP_KERNEL);
 	if (!pmx)
 		return -ENOMEM;
 
-	pmx->base = (u32)driver->base;
-	pmx->mode_reg.offset = driver->mode_reg.offset;
+	pmx->mode_reg.address = driver->mode_reg.address;
 	pmx->mode_reg.mask = driver->mode_reg.mask;
 
 	/* choose mode to enable */
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:52 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:52 +0530
Subject: [PATCH V2 32/69] ST SPEAr: Adding support for SDHCI (SDIO)
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <df88865302536cd3d2f9defaaf00f178633fd96b.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear13xx.c            |   34 +++++++++++++-
 arch/arm/mach-spear3xx/include/mach/generic.h  |   13 ++++--
 arch/arm/mach-spear3xx/include/mach/irqs.h     |    4 +-
 arch/arm/mach-spear3xx/include/mach/spear300.h |    4 +-
 arch/arm/mach-spear3xx/include/mach/spear320.h |    6 +-
 arch/arm/mach-spear3xx/spear300.c              |   62 ++++++++++++++++++++----
 arch/arm/mach-spear3xx/spear300_evb.c          |   18 +++++++-
 arch/arm/mach-spear3xx/spear320.c              |   43 +++++++++++++----
 arch/arm/mach-spear3xx/spear320_evb.c          |   15 +++++-
 11 files changed, 167 insertions(+), 34 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 7419e0b..bfd0667 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -40,6 +40,7 @@ extern struct platform_device spear13xx_nand_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
+extern struct platform_device spear13xx_sdhci_device;
 extern struct platform_device spear13xx_smi_device;
 extern struct sys_timer spear13xx_timer;
 
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index ba46f61..269d9b0 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -43,6 +43,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
+	&spear13xx_sdhci_device,
 	&spear13xx_smi_device,
 };
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 6455ebb..b058c3b 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -349,6 +349,16 @@ struct platform_device spear13xx_smi_device = {
 	.resource = smi_resources,
 };
 
+static void sdhci_enable(void)
+{
+	unsigned val = readl(PERIP_CFG);
+
+	/* This function enables SD/MMC interface out of SD/MMC, CF, XD */
+	val &= ~(MCIF_SEL_MASK << MCIF_SEL_SHIFT);
+	val |= SD_MMC_ACTIVE << MCIF_SEL_SHIFT;
+	writel(val, PERIP_CFG);
+}
+
 #ifdef CONFIG_PCIEPORTBUS
 /* PCIE0 clock always needs to be enabled if any of the three PCIE port
  * have to be used. So call this function from the board initilization
@@ -377,10 +387,32 @@ int enable_pcie0_clk(void)
 }
 #endif
 
+/* sdhci (sdio) device declaration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR13XX_MCIF_SDHCI_BASE,
+		.end	= SPEAR13XX_MCIF_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device spear13xx_sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
+
 /* Do spear13xx familiy common initialization part here */
 void __init spear13xx_init(void)
 {
-	/* nothing to do for now */
+	sdhci_enable();
 }
 
 /* This will initialize vic */
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 04ce8700..9bd9424 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -116,6 +116,7 @@ extern struct platform_device nand0_device;
 extern struct platform_device nand1_device;
 extern struct platform_device nand2_device;
 extern struct platform_device nand3_device;
+extern struct platform_device sdhci_device;
 
 /* pad mux modes */
 extern struct pmx_mode nand_mode;
@@ -144,12 +145,15 @@ extern struct pmx_dev pmx_telecom_camera;
 extern struct pmx_dev pmx_telecom_dac;
 extern struct pmx_dev pmx_telecom_i2s;
 extern struct pmx_dev pmx_telecom_boot_pins;
-extern struct pmx_dev pmx_telecom_sdio_4bit;
-extern struct pmx_dev pmx_telecom_sdio_8bit;
+extern struct pmx_dev pmx_telecom_sdhci_4bit;
+extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
 
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
+#define SDHCI_MEM_ENB	0x1
+#define I2S_MEM_ENB	0x2
+void sdhci_i2s_mem_enable(u8 mask);
 
 /* Add misc structure declarations here */
 extern struct clcd_board clcd_plat_data;
@@ -182,6 +186,7 @@ extern struct platform_device i2c1_device;
 extern struct platform_device nand_device;
 extern struct platform_device plgpio_device;
 extern struct platform_device pwm_device;
+extern struct platform_device sdhci_device;
 
 /* pad mux modes */
 extern struct pmx_mode auto_net_smii_mode;
@@ -194,14 +199,14 @@ extern struct pmx_dev pmx_clcd;
 extern struct pmx_dev pmx_emi;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_spp;
-extern struct pmx_dev pmx_sdio;
+extern struct pmx_dev pmx_sdhci;
 extern struct pmx_dev pmx_i2s;
 extern struct pmx_dev pmx_uart1;
 extern struct pmx_dev pmx_uart1_modem;
 extern struct pmx_dev pmx_uart2;
 extern struct pmx_dev pmx_touchscreen;
 extern struct pmx_dev pmx_can;
-extern struct pmx_dev pmx_sdio_led;
+extern struct pmx_dev pmx_sdhci_led;
 extern struct pmx_dev pmx_pwm0;
 extern struct pmx_dev pmx_pwm1;
 extern struct pmx_dev pmx_pwm2;
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index 5ad7574..df0c1f3 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -69,7 +69,7 @@
 #define IRQ_CLCD				IRQ_GEN_RAS_3
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define IRQ_SDIO				IRQ_INTRCOMM_RAS_ARM
+#define IRQ_SDHCI				IRQ_INTRCOMM_RAS_ARM
 
 /* GPIO pins virtual irqs */
 #define SPEAR_GPIO_INT_BASE			(VIRQ_START + 9)
@@ -115,7 +115,7 @@
 #define VIRQ_SPP				(VIRQ_START + 2)
 
 /* IRQs sharing IRQ_GEN_RAS_2 */
-#define IRQ_SDIO				IRQ_GEN_RAS_2
+#define IRQ_SDHCI				IRQ_GEN_RAS_2
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
 #define VIRQ_PLGPIO				(VIRQ_START + 3)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index ccaa765..1059d5a 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -39,8 +39,8 @@
 #define SPEAR300_CLCD_BASE		0x60000000
 #define SPEAR300_CLCD_SIZE		0x10000000
 
-#define SPEAR300_SDIO_BASE		0x70000000
-#define SPEAR300_SDIO_SIZE		0x10000000
+#define SPEAR300_SDHCI_BASE		0x70000000
+#define SPEAR300_SDHCI_SIZE		0x10000000
 
 #define SPEAR300_NAND_0_BASE		0x80000000
 #define SPEAR300_NAND_0_SIZE		0x04000000
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index aa6727c..89f5bfb 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -28,8 +28,8 @@
 #define SPEAR320_I2S_BASE		0x60000000
 #define SPEAR320_I2S_SIZE		0x10000000
 
-#define SPEAR320_SDIO_BASE		0x70000000
-#define SPEAR320_SDIO_SIZE		0x10000000
+#define SPEAR320_SDHCI_BASE		0x70000000
+#define SPEAR320_SDHCI_SIZE		0x10000000
 
 #define SPEAR320_CLCD_BASE		0x90000000
 #define SPEAR320_CLCD_SIZE		0x10000000
@@ -77,7 +77,7 @@
 #define EMI_IRQ_MASK			(1 << 7)
 #define CLCD_IRQ_MASK			(1 << 8)
 #define SPP_IRQ_MASK			(1 << 9)
-#define SDIO_IRQ_MASK			(1 << 10)
+#define SDHCI_IRQ_MASK			(1 << 10)
 #define CAN_U_IRQ_MASK			(1 << 11)
 #define CAN_L_IRQ_MASK			(1 << 12)
 #define UART1_IRQ_MASK			(1 << 13)
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index c213614..fd83f53 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -311,7 +311,7 @@ struct pmx_dev pmx_telecom_boot_pins = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -324,14 +324,14 @@ struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_4bit = {
-	.name = "telecom_sdio_4bit",
-	.modes = pmx_telecom_sdio_4bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_4bit_modes),
+struct pmx_dev pmx_telecom_sdhci_4bit = {
+	.name = "telecom_sdhci_4bit",
+	.modes = pmx_telecom_sdhci_4bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -343,10 +343,10 @@ struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_8bit = {
-	.name = "telecom_sdio_8bit",
-	.modes = pmx_telecom_sdio_8bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_8bit_modes),
+struct pmx_dev pmx_telecom_sdhci_8bit = {
+	.name = "telecom_sdhci_8bit",
+	.modes = pmx_telecom_sdhci_8bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
 	.enb_on_reset = 1,
 };
 
@@ -524,6 +524,28 @@ struct platform_device nand3_device = {
 	.dev.platform_data = &nand3_platform_data,
 };
 
+/* sdhci (sdio) device declaration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR300_SDHCI_BASE,
+		.end	= SPEAR300_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
+
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -577,6 +599,26 @@ struct spear_shirq shirq_ras1 = {
 	},
 };
 
+/* Function handling sdhci and i2s memory sharing */
+#define SDHCI_MEM_SELECT	0x20000000
+void sdhci_i2s_mem_enable(u8 mask)
+{
+	u32 val;
+	void __iomem *base = ioremap(SPEAR300_SOC_CONFIG_BASE,
+			SPEAR300_SOC_CONFIG_SIZE);
+	if (!base) {
+		pr_debug("sdhci_i2s_enb: ioremap fail\n");
+		return;
+	}
+
+	val = readl(base + MODE_CONFIG_REG);
+	if (mask == SDHCI_MEM_ENB)
+		val |= SDHCI_MEM_SELECT;
+	else
+		val &= ~SDHCI_MEM_SELECT;
+	writel(val, base + MODE_CONFIG_REG);
+}
+
 /* spear300 routines */
 void __init spear300_init(void)
 {
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index c702cc3..2bcb55f 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -17,6 +17,7 @@
 #include <asm/mach-types.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <mach/generic.h>
 #include <mach/gpio.h>
 #include <mach/spear.h>
@@ -37,7 +38,7 @@ static struct pmx_dev *pmx_devs[] = {
 	/* spear300 specific devices */
 	&pmx_fsmc_2_chips,
 	&pmx_clcd,
-	&pmx_telecom_sdio_4bit,
+	&pmx_telecom_sdhci_4bit,
 	&pmx_gpio1,
 };
 
@@ -65,6 +66,15 @@ static struct platform_device *plat_devs[] __initdata = {
 
 	/* spear300 specific devices */
 	&kbd_device,
+	&sdhci_device,
+};
+
+/* sdhci board specific information */
+static struct sdhci_plat_data sdhci_plat_data = {
+	.card_power_gpio = RAS_GPIO_2,
+	.power_active_high = 0,
+	.power_always_enb = 0,
+	.card_int_gpio = RAS_GPIO_0,
 };
 
 /* keyboard specific platform data */
@@ -115,6 +125,12 @@ static void __init spear300_evb_init(void)
 	fsmc_nand_set_plat_data(&nand0_device, NULL, 0, NAND_SKIP_BBTSCAN,
 			FSMC_NAND_BW8);
 
+	/* set sdhci device platform data */
+	sdhci_set_plat_data(&sdhci_device, &sdhci_plat_data);
+
+	/* Enable sdhci memory */
+	sdhci_i2s_mem_enable(SDHCI_MEM_ENB);
+
 	/* call spear300 machine init function */
 	spear300_init();
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index f87cc97..e14e201 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -13,6 +13,8 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/ptrace.h>
+#include <linux/types.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <mtd/fsmc.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
@@ -113,7 +115,7 @@ struct pmx_dev pmx_spp = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_modes[] = {
+struct pmx_dev_mode pmx_sdhci_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
 			SMALL_PRINTERS_MODE,
@@ -121,10 +123,10 @@ struct pmx_dev_mode pmx_sdio_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_sdio = {
-	.name = "sdio",
-	.modes = pmx_sdio_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_modes),
+struct pmx_dev pmx_sdhci = {
+	.name = "sdhci",
+	.modes = pmx_sdhci_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
 	.enb_on_reset = 1,
 };
 
@@ -218,17 +220,17 @@ struct pmx_dev pmx_can = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_led_modes[] = {
+struct pmx_dev_mode pmx_sdhci_led_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
 		.mask = PMX_SSP_CS_MASK,
 	},
 };
 
-struct pmx_dev pmx_sdio_led = {
-	.name = "sdio_led",
-	.modes = pmx_sdio_led_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_led_modes),
+struct pmx_dev pmx_sdhci_led = {
+	.name = "sdhci_led",
+	.modes = pmx_sdhci_led_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
 	.enb_on_reset = 1,
 };
 
@@ -536,6 +538,27 @@ struct platform_device pwm_device = {
 	.resource = pwm_resources,
 };
 
+/* sdhci (sdio) device registeration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR320_SDHCI_BASE,
+		.end	= SPEAR320_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
 
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index dcca84e..2142ad9 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -16,6 +16,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <linux/spi/flash.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <linux/spi/spi.h>
 #include <mach/generic.h>
 #include <mach/gpio.h>
@@ -34,7 +35,7 @@ static struct pmx_dev *pmx_devs[] = {
 
 	/* spear320 specific devices */
 	&pmx_fsmc,
-	&pmx_sdio,
+	&pmx_sdhci,
 	&pmx_i2s,
 	&pmx_uart1,
 	&pmx_uart2,
@@ -69,6 +70,15 @@ static struct platform_device *plat_devs[] __initdata = {
 	&i2c1_device,
 	&plgpio_device,
 	&pwm_device,
+	&sdhci_device,
+};
+
+/* sdhci board specific information */
+static struct sdhci_plat_data sdhci_plat_data = {
+	.card_power_gpio = PLGPIO_61,
+	.power_active_high = 0,
+	.power_always_enb = 1,
+	.card_int_gpio = -1,
 };
 
 static struct spi_board_info __initdata spi_board_info[] = {
@@ -83,6 +93,9 @@ static void __init spear320_evb_init(void)
 {
 	unsigned int i;
 
+	/* set sdhci device platform data */
+	sdhci_set_plat_data(&sdhci_device, &sdhci_plat_data);
+
 	/* padmux initialization, must be done before spear320_init */
 	pmx_driver.mode = &auto_net_mii_mode;
 	pmx_driver.devs = pmx_devs;
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:58 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:58 +0530
Subject: [PATCH V2 38/69] ST SPEAr: Adding support for DDR in clock framework
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <d62d10bc768767f7ef0537328bdce43c273dd88e.1285933332.git.viresh.kumar@st.com>

Changing rate of clk, which is ancestor of DDR requires to put DDR in refresh
mode before changing parents rate. For this DDR support is added in clock
framework. Now at boot time all ancestors of DDR is marked specially and
changing their rate must be first acked by ddr (i.e. ddr will run on that
clock). This patch adds support for this.

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
---
 arch/arm/mach-spear13xx/clock.c                  |   69 ++++++++---
 arch/arm/mach-spear13xx/include/mach/generic.h   |    2 +-
 arch/arm/mach-spear13xx/include/mach/misc_regs.h |    4 +
 arch/arm/mach-spear13xx/spear13xx.c              |    2 +-
 arch/arm/mach-spear3xx/clock.c                   |  105 ++++++++++++++----
 arch/arm/mach-spear3xx/include/mach/generic.h    |    2 +-
 arch/arm/mach-spear3xx/include/mach/misc_regs.h  |    7 +
 arch/arm/mach-spear3xx/spear3xx.c                |    2 +-
 arch/arm/mach-spear6xx/clock.c                   |  105 ++++++++++++++----
 arch/arm/mach-spear6xx/include/mach/generic.h    |    2 +-
 arch/arm/mach-spear6xx/include/mach/misc_regs.h  |    7 +
 arch/arm/mach-spear6xx/spear6xx.c                |    2 +-
 arch/arm/plat-spear/clock.c                      |  133 ++++++++++++++++++---
 arch/arm/plat-spear/include/plat/clock.h         |   42 +++++--
 14 files changed, 385 insertions(+), 99 deletions(-)

diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index ca80c46..4f320fa 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -23,19 +23,19 @@
 /* root clks */
 /* 24 MHz oscillator clock */
 static struct clk osc1_24m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 24000000,
 };
 
 /* 32 KHz oscillator clock */
 static struct clk osc2_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 25 MHz MIPHY oscillator clock */
 static struct clk osc3_25m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 25000000,
 };
 
@@ -99,7 +99,7 @@ struct pll_rate_tbl pll_rtbl[] = {
 
 /* pll1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL1_CLK_SHIFT,
 	.en_reg = PLL1_CTR,
@@ -113,7 +113,7 @@ static struct clk pll1_clk = {
 
 /* pll1div2 clock */
 static struct clk pll1div2_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 2,
 	.recalc = &follow_parent,
@@ -121,7 +121,7 @@ static struct clk pll1div2_clk = {
 
 /* pll1div4 clock */
 static struct clk pll1div4_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 4,
 	.recalc = &follow_parent,
@@ -136,6 +136,7 @@ static struct pll_clk_config pll2_config = {
 
 /* pll2 clock */
 static struct clk pll2_clk = {
+	.flags = SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL2_CLK_SHIFT,
 	.en_reg = PLL2_CTR,
@@ -156,6 +157,7 @@ static struct pll_clk_config pll3_config = {
 
 /* pll3 clock */
 static struct clk pll3_clk = {
+	.flags = SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL3_CLK_SHIFT,
 	.en_reg = PLL3_CTR,
@@ -184,7 +186,7 @@ struct pll_rate_tbl pll4_rtbl[] = {
 
 /* pll4 (DDR) clock */
 static struct clk pll4_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc1_24m_clk,
 	.en_reg = PLL4_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -197,22 +199,54 @@ static struct clk pll4_clk = {
 
 /* pll5 USB 48 MHz clock */
 static struct clk pll5_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc1_24m_clk,
 	.rate = 48000000,
 };
 
 /* pll6 (MIPHY) clock */
 static struct clk pll6_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc3_25m_clk,
 	.rate = 25000000,
 };
 
 /* clocks derived from pll1 clk */
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 332000000,
+	.maxrate = 500000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &pll1_clk,
+		.pclk_val = MCTR_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll4_clk,
+		.pclk_val = MCTR_CLK_PLL4_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 2,
 	.recalc = &follow_parent,
@@ -220,7 +254,7 @@ static struct clk cpu_clk = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 6,
 	.recalc = &follow_parent,
@@ -228,7 +262,7 @@ static struct clk ahb_clk = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 12,
 	.recalc = &follow_parent,
@@ -845,6 +879,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.con_id = "pll6_clk",		.clk = &pll6_clk},
 
 	/* clock derived from pll1 clk */
+	{.con_id = "ddr_clk",		.clk = &ddr_clk},
 	{.con_id = "cpu_clk",		.clk = &cpu_clk},
 	{.con_id = "ahb_clk",		.clk = &ahb_clk},
 	{.con_id = "apb_clk",		.clk = &apb_clk},
@@ -911,12 +946,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 #endif
 };
 
-void __init clk_init(void)
+/* machine clk init */
+void __init spear13xx_clk_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
-		clk_register(&spear_clk_lookups[i]);
-
-	recalc_root_clocks();
+	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
 }
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 83be1f2..cd54e62 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -45,7 +45,7 @@ extern struct platform_device spear13xx_smi_device;
 extern struct sys_timer spear13xx_timer;
 
 /* Add spear13xx family function declarations here */
-void __init clk_init(void);
+void __init spear13xx_clk_init(void);
 void __init i2c_register_board_devices(void);
 void __init spear_setup_timer(void);
 void __init spear13xx_map_io(void);
diff --git a/arch/arm/mach-spear13xx/include/mach/misc_regs.h b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
index a7ba6cb..3cfd4fc 100644
--- a/arch/arm/mach-spear13xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
@@ -98,6 +98,10 @@
 	#define CLCD_CLK_SHIFT		2
 	#define C3_CLK_MASK		1
 	#define C3_CLK_SHIFT		1
+	#define MCTR_CLK_SHIFT		10
+	#define MCTR_CLK_MASK		0x1
+	#define MCTR_CLK_PLL1_VAL	0x0
+	#define MCTR_CLK_PLL4_VAL	0x1
 
 #define GMAC_CLK_CFG		((unsigned int *)(MISC_BASE + 0x248))
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index b058c3b..76920ec 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -453,7 +453,7 @@ void __init spear13xx_map_io(void)
 	iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
 
 	/* This will initialize clock framework */
-	clk_init();
+	spear13xx_clk_init();
 }
 
 static void __init spear13xx_timer_init(void)
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 0a7a548..4f049fe 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -19,13 +19,13 @@
 /* root clks */
 /* 32 KHz oscillator clock */
 static struct clk osc_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 24 MHz oscillator clock */
 static struct clk osc_24m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 24000000,
 };
 
@@ -40,7 +40,7 @@ static struct clk rtc_clk = {
 
 /* clock derived from 24 MHz osc clk */
 /* pll masks structure */
-static struct pll_clk_masks pll1_masks = {
+static struct pll_clk_masks pll_masks = {
 	.mode_mask = PLL_MODE_MASK,
 	.mode_shift = PLL_MODE_SHIFT,
 	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
@@ -53,22 +53,22 @@ static struct pll_clk_masks pll1_masks = {
 	.div_n_shift = PLL_DIV_N_SHIFT,
 };
 
-/* pll1 configuration structure */
-static struct pll_clk_config pll1_config = {
-	.mode_reg = PLL1_CTR,
-	.cfg_reg = PLL1_FRQ,
-	.masks = &pll1_masks,
-};
-
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
+/* pll1 configuration structure */
+static struct pll_clk_config pll1_config = {
+	.mode_reg = PLL1_CTR,
+	.cfg_reg = PLL1_FRQ,
+	.masks = &pll_masks,
+};
+
 /* PLL1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc_24m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -79,9 +79,29 @@ static struct clk pll1_clk = {
 	.private_data = &pll1_config,
 };
 
+/* pll2 configuration structure */
+static struct pll_clk_config pll2_config = {
+	.mode_reg = PLL2_CTR,
+	.cfg_reg = PLL2_FRQ,
+	.masks = &pll_masks,
+};
+
+/* PLL2 clock */
+static struct clk pll2_clk = {
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
+	.pclk = &osc_24m_clk,
+	.en_reg = PLL2_CTR,
+	.en_reg_bit = PLL_ENABLE,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.private_data = &pll2_config,
+};
+
 /* PLL3 48 MHz clock */
 static struct clk pll3_48m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc_24m_clk,
 	.rate = 48000000,
 };
@@ -96,7 +116,7 @@ static struct clk wdt_clk = {
 /* clock derived from pll1 clk */
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.recalc = &follow_parent,
 };
@@ -123,7 +143,7 @@ struct bus_rate_tbl bus_rtbl[] = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -410,6 +430,48 @@ static struct clk usbd_clk = {
 };
 
 /* clock derived from ahb clk */
+/* ahb multiplied by 2 clock */
+static struct clk ahbmult2_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.pclk = &ahb_clk,
+	.recalc = &ahbmult2_clk_recalc,
+};
+
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 166000000,
+	.maxrate = 332000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &ahb_clk,
+		.pclk_val = MCTR_CLK_HCLK_VAL,
+	}, {
+		.pclk = &ahbmult2_clk,
+		.pclk_val = MCTR_CLK_2HCLK_VAL,
+	}, {
+		.pclk = &pll2_clk,
+		.pclk_val = MCTR_CLK_PLL2_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PLL_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* apb masks structure */
 static struct bus_clk_masks apb_masks = {
 	.mask = HCLK_PCLK_RATIO_MASK,
@@ -424,7 +486,7 @@ static struct bus_clk_config apb_config = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &ahb_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -658,6 +720,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 24 MHz osc clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
+	{ .con_id = "pll2_clk",		.clk = &pll2_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
 	{ .dev_id = "wdt",		.clk = &wdt_clk},
 	/* clock derived from pll1 clk */
@@ -677,6 +740,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .con_id = "usbh_clk",		.clk = &usbh_clk},
 	{ .dev_id = "usbd",		.clk = &usbd_clk},
 	/* clock derived from ahb clk */
+	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
+	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
 	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
@@ -732,12 +797,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 #endif
 };
 
-void __init clk_init(void)
+/* machine clk init */
+void __init spear3xx_clk_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
-		clk_register(&spear_clk_lookups[i]);
-
-	recalc_root_clocks();
+	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
 }
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 0f7648b..7b83197 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -44,7 +44,7 @@ extern struct platform_device smi_device;
 extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
-void __init clk_init(void);
+void __init spear3xx_clk_init(void);
 void __init i2c_register_board_devices(void);
 void __init spear_setup_timer(void);
 void __init spear3xx_map_io(void);
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
index 6cb4f3c..6316900 100644
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
@@ -46,6 +46,13 @@
 
 #define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
 #define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
+/* PLL_CLK_CFG register masks */
+#define MCTR_CLK_SHIFT		28
+#define MCTR_CLK_MASK		0x7
+#define MCTR_CLK_HCLK_VAL	0x0
+#define MCTR_CLK_2HCLK_VAL	0x1
+#define MCTR_CLK_PLL2_VAL	0x3
+
 #define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index f7b8915..dcbe020 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -280,7 +280,7 @@ void __init spear3xx_map_io(void)
 	iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
 
 	/* This will initialize clock framework */
-	clk_init();
+	spear3xx_clk_init();
 }
 
 /* pad multiplexing support */
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 9171952..99cc21d 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -19,13 +19,13 @@
 /* root clks */
 /* 32 KHz oscillator clock */
 static struct clk osc_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 30 MHz oscillator clock */
 static struct clk osc_30m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 30000000,
 };
 
@@ -40,7 +40,7 @@ static struct clk rtc_clk = {
 
 /* clock derived from 30 MHz osc clk */
 /* pll masks structure */
-static struct pll_clk_masks pll1_masks = {
+static struct pll_clk_masks pll_masks = {
 	.mode_mask = PLL_MODE_MASK,
 	.mode_shift = PLL_MODE_SHIFT,
 	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
@@ -53,22 +53,22 @@ static struct pll_clk_masks pll1_masks = {
 	.div_n_shift = PLL_DIV_N_SHIFT,
 };
 
-/* pll1 configuration structure */
-static struct pll_clk_config pll1_config = {
-	.mode_reg = PLL1_CTR,
-	.cfg_reg = PLL1_FRQ,
-	.masks = &pll1_masks,
-};
-
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
+/* pll1 configuration structure */
+static struct pll_clk_config pll1_config = {
+	.mode_reg = PLL1_CTR,
+	.cfg_reg = PLL1_FRQ,
+	.masks = &pll_masks,
+};
+
 /* PLL1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc_30m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -79,9 +79,29 @@ static struct clk pll1_clk = {
 	.private_data = &pll1_config,
 };
 
+/* pll2 configuration structure */
+static struct pll_clk_config pll2_config = {
+	.mode_reg = PLL2_CTR,
+	.cfg_reg = PLL2_FRQ,
+	.masks = &pll_masks,
+};
+
+/* PLL2 clock */
+static struct clk pll2_clk = {
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
+	.pclk = &osc_30m_clk,
+	.en_reg = PLL2_CTR,
+	.en_reg_bit = PLL_ENABLE,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.private_data = &pll2_config,
+};
+
 /* PLL3 48 MHz clock */
 static struct clk pll3_48m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc_30m_clk,
 	.rate = 48000000,
 };
@@ -96,7 +116,7 @@ static struct clk wdt_clk = {
 /* clock derived from pll1 clk */
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.recalc = &follow_parent,
 };
@@ -123,7 +143,7 @@ struct bus_rate_tbl bus_rtbl[] = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -491,6 +511,48 @@ static struct clk usbd_clk = {
 };
 
 /* clock derived from ahb clk */
+/* ahb multiplied by 2 clock */
+static struct clk ahbmult2_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.pclk = &ahb_clk,
+	.recalc = &ahbmult2_clk_recalc,
+};
+
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 166000000,
+	.maxrate = 332000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &ahb_clk,
+		.pclk_val = MCTR_CLK_HCLK_VAL,
+	}, {
+		.pclk = &ahbmult2_clk,
+		.pclk_val = MCTR_CLK_2HCLK_VAL,
+	}, {
+		.pclk = &pll2_clk,
+		.pclk_val = MCTR_CLK_PLL2_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PLL_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* apb masks structure */
 static struct bus_clk_masks apb_masks = {
 	.mask = HCLK_PCLK_RATIO_MASK,
@@ -505,7 +567,7 @@ static struct bus_clk_config apb_config = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &ahb_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -630,6 +692,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 30 MHz os		 clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
+	{ .con_id = "pll2_clk",		.clk = &pll2_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
 	{ .dev_id = "wdt",		.clk = &wdt_clk},
 	/* clock derived from pll1 clk */
@@ -654,6 +717,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .con_id = "usbh.1_clk",	.clk = &usbh1_clk},
 	{ .dev_id = "usbd",		.clk = &usbd_clk},
 	/* clock derived from ahb clk */
+	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
+	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
 	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
@@ -671,12 +736,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "gpio2",		.clk = &gpio2_clk},
 };
 
-void __init clk_init(void)
+/* machine clk init */
+void __init spear6xx_clk_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
-		clk_register(&spear_clk_lookups[i]);
-
-	recalc_root_clocks();
+	clk_init(spear_clk_lookups, ARRAY_SIZE(spear_clk_lookups), &ddr_clk);
 }
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index dd29298..4d1d326 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -51,7 +51,7 @@ void __init spear6xx_map_io(void);
 void __init spear6xx_init_irq(void);
 void __init spear6xx_init(void);
 void __init spear600_init(void);
-void __init clk_init(void);
+void __init spear6xx_clk_init(void);
 
 /* Add spear600 machine device structure declarations here */
 
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
index bd71e72..0f4562b 100644
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
@@ -47,6 +47,13 @@
 #define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
 #define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
 #define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
+/* PLL_CLK_CFG register masks */
+#define MCTR_CLK_SHIFT		28
+#define MCTR_CLK_MASK		0x7
+#define MCTR_CLK_HCLK_VAL	0x0
+#define MCTR_CLK_2HCLK_VAL	0x1
+#define MCTR_CLK_PLL2_VAL	0x3
+
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index f91380e..cd2153c 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -439,7 +439,7 @@ void __init spear6xx_map_io(void)
 	iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
 
 	/* This will initialize clock framework */
-	clk_init();
+	spear6xx_clk_init();
 }
 
 static void __init spear6xx_timer_init(void)
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index 7d3338f..fb1c87b 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -21,6 +21,8 @@
 #include <linux/spinlock.h>
 #include <plat/clock.h>
 
+/* pointer to ddr clock structure */
+static struct clk *ddr_clk;
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(root_clks);
 #ifdef CONFIG_DEBUG_FS
@@ -160,7 +162,7 @@ static int do_clk_enable(struct clk *clk)
 		 * time please reclac
 		 */
 		if (clk->recalc) {
-			ret = clk->recalc(clk);
+			ret = clk->recalc(clk, &clk->rate, clk->pclk->rate);
 			if (ret)
 				goto err;
 		}
@@ -298,7 +300,16 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 			propagate_rate(clk, 0);
 		spin_unlock_irqrestore(&clocks_lock, flags);
 	} else if (clk->pclk) {
-		u32 mult = clk->div_factor ? clk->div_factor : 1;
+		u32 mult;
+		/*
+		 * if pclk is SYSTEM_CLK and clk is not SYSTEM_CLK then return
+		 * error
+		 */
+		if (clk->pclk->flags & SYSTEM_CLK)
+			if (!(clk->flags & SYSTEM_CLK))
+				return -EPERM;
+
+		mult = clk->div_factor ? clk->div_factor : 1;
 		ret = clk_set_rate(clk->pclk, mult * rate);
 	}
 
@@ -371,7 +382,7 @@ void propagate_rate(struct clk *pclk, int on_init)
 
 	list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
 		if (clk->recalc) {
-			ret = clk->recalc(clk);
+			ret = clk->recalc(clk, &clk->rate, clk->pclk->rate);
 			/*
 			 * recalc will return error if clk out is not programmed
 			 * In this case configure default rate.
@@ -390,6 +401,47 @@ void propagate_rate(struct clk *pclk, int on_init)
 	}
 }
 
+/* updates "rate" pointer with current_clk's output for input "rate" */
+static void rate_calc(struct clk *current_clk, struct clk *ancestor_clk,
+		unsigned long *rate)
+{
+	if (current_clk->pclk != ancestor_clk)
+		rate_calc(current_clk->pclk, ancestor_clk, rate);
+
+	if (current_clk->recalc)
+		current_clk->recalc(current_clk, rate, *rate);
+}
+
+/*
+ * Check if ancestor clk rate is acceptable to ddr or not.
+ * This will call recursive rate_calc function, starting from ddr upto ancestor
+ * clk mentioned. This will calculate divisions / multiplications by all
+ * intermediate ancestor clocks and return the final rate of ddr if ancestor clk
+ * sets its rate to "rate", value passed in function.
+ */
+static int ddr_rate_acceptable(struct clk *aclk, unsigned long rate)
+{
+	struct ddr_rate_tbl *tbl = ddr_clk->private_data;
+
+	rate_calc(ddr_clk, aclk, &rate);
+	if ((rate >= tbl->minrate) && (rate <= tbl->maxrate))
+		return true;
+
+	return false;
+}
+
+/* mark all ddr ancestors with DDR_ANCESTOR flag */
+static void mark_ddr_ancestors(struct clk *dclk)
+{
+	struct clk *clk = dclk->pclk;
+
+	/* mark all ancestors of DDR */
+	while (clk != NULL) {
+		clk->flags |= DDR_ANCESTOR;
+		clk = clk->pclk;
+	}
+}
+
 /**
  * round_rate - Returns index of closest programmable rate in rate_config tbl
  * @clk: ptr to clock structure
@@ -475,7 +527,7 @@ unsigned long pll_calc_rate(struct clk *clk, int index)
  * In Dithered mode
  * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
  */
-int pll_clk_recalc(struct clk *clk)
+int pll_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct pll_clk_config *config = clk->private_data;
 	unsigned int num = 2, den = 0, val, mode = 0;
@@ -504,7 +556,7 @@ int pll_clk_recalc(struct clk *clk)
 	if (!den)
 		return -EINVAL;
 
-	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	*rate = (((prate/10000) * num) / den) * 10000;
 	return 0;
 }
 
@@ -522,6 +574,25 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 	if (i < 0)
 		return i;
 
+	/* if clk is ddrs ancestor, check if rate is acceptable to ddr */
+	if (ddr_clk && (clk->flags & DDR_ANCESTOR)) {
+		int ret;
+
+		ret = ddr_rate_acceptable(clk, rate);
+		if (ret == false)
+			return -EPERM;
+		else {
+			/*
+			 * call routine to put ddr in refresh mode, and
+			 * configure pll.
+			 */
+			/* TBD */
+			clk->rate = rate;
+		}
+
+		return ret;
+	}
+
 	val = readl(config->mode_reg) &
 		~(config->masks->mode_mask << config->masks->mode_shift);
 	val |= (tbls[i].mode & config->masks->mode_mask) <<
@@ -563,7 +634,7 @@ unsigned long bus_calc_rate(struct clk *clk, int index)
 }
 
 /* calculates current programmed rate of ahb or apb bus */
-int bus_clk_recalc(struct clk *clk)
+int bus_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct bus_clk_config *config = clk->private_data;
 	unsigned int div;
@@ -574,7 +645,7 @@ int bus_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	clk->rate = (unsigned long)clk->pclk->rate / div;
+	*rate = prate / div;
 	return 0;
 }
 
@@ -600,6 +671,14 @@ int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 	return 0;
 }
 
+/* calculates current programmed rate of ahbmult2 */
+int
+ahbmult2_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
+{
+	*rate = prate * 2;
+	return 0;
+}
+
 /*
  * gives rate for different values of eq, x and y
  *
@@ -627,7 +706,7 @@ unsigned long aux_calc_rate(struct clk *clk, int index)
  *
  * Selection of eqn 1 or 2 is programmed in register
  */
-int aux_clk_recalc(struct clk *clk)
+int aux_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct aux_clk_config *config = clk->private_data;
 	unsigned int num = 1, den = 1, val, eqn;
@@ -650,7 +729,7 @@ int aux_clk_recalc(struct clk *clk)
 	if (!den)
 		return -EINVAL;
 
-	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	*rate = (((prate / 10000) * num) / den) * 10000;
 	return 0;
 }
 
@@ -704,7 +783,7 @@ unsigned long gpt_calc_rate(struct clk *clk, int index)
  * Fout from synthesizer can be given from below equations:
  * Fout= Fin/((2 ^ (N+1)) * (M+1))
  */
-int gpt_clk_recalc(struct clk *clk)
+int gpt_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct gpt_clk_config *config = clk->private_data;
 	unsigned int div = 1, val;
@@ -718,7 +797,7 @@ int gpt_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	clk->rate = (unsigned long)clk->pclk->rate / div;
+	*rate = prate / div;
 	return 0;
 }
 
@@ -786,11 +865,10 @@ unsigned long clcd_calc_rate(struct clk *clk, int index)
  * complete div (including fractional part) and then right shift the
  * result by 14 places.
  */
-int clcd_clk_recalc(struct clk *clk)
+int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct clcd_clk_config *config = clk->private_data;
 	unsigned int div = 1;
-	unsigned long prate;
 	unsigned int val;
 
 	val = readl(config->synth_reg);
@@ -800,10 +878,10 @@ int clcd_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
+	prate = prate / 1000; /* first level division, make it KHz */
 
-	clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
-	clk->rate *= 1000;
+	*rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
+	*rate *= 1000;
 	return 0;
 }
 
@@ -834,11 +912,11 @@ int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
  * Used for clocks that always have value as the parent clock divided by a
  * fixed divisor
  */
-int follow_parent(struct clk *clk)
+int follow_parent(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
 
-	clk->rate = clk->pclk->rate/div_factor;
+	*rate = prate / div_factor;
 	return 0;
 }
 
@@ -857,7 +935,7 @@ void recalc_root_clocks(void)
 	spin_lock_irqsave(&clocks_lock, flags);
 	list_for_each_entry(pclk, &root_clks, sibling) {
 		if (pclk->recalc) {
-			ret = pclk->recalc(pclk);
+			ret = pclk->recalc(pclk, &pclk->rate, pclk->pclk->rate);
 			/*
 			 * recalc will return error if clk out is not programmed
 			 * In this case configure default clock.
@@ -873,6 +951,23 @@ void recalc_root_clocks(void)
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 
+void __init
+clk_init(struct clk_lookup *clk_lookups, u32 count, struct clk *dclk)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+		clk_register(&clk_lookups[i]);
+
+	recalc_root_clocks();
+
+	/* Mark all ancestors of DDR with special flag */
+	if (dclk) {
+		ddr_clk = dclk;
+		mark_ddr_ancestors(dclk);
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 /*
  *	debugfs support to trace clock tree hierarchy and attributes
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 621c17c..6ddcf93 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -19,9 +19,12 @@
 #include <asm/clkdev.h>
 
 /* clk structure flags */
-#define	ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
-#define	RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
-#define	ENABLED_ON_INIT		(1 << 2) /* clocks enabled at init */
+#define ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
+#define RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
+#define ENABLED_ON_INIT		(1 << 2) /* clocks enabled at init */
+/* Only System clocks can call other sytem clocks set rate function */
+#define SYSTEM_CLK		(1 << 3)
+#define DDR_ANCESTOR		(1 << 4) /* ancestor clks of DDR */
 
 /**
  * struct clkops - clock operations
@@ -99,8 +102,9 @@ struct clk {
 	unsigned int *en_reg;
 	u8 en_reg_bit;
 	const struct clkops *ops;
-	int (*recalc) (struct clk *);
-	int (*set_rate) (struct clk *, unsigned long rate);
+	int (*recalc) (struct clk *clk, unsigned long *rate,
+			unsigned long prate);
+	int (*set_rate) (struct clk *clk, unsigned long rate);
 	unsigned long (*calc_rate)(struct clk *, int index);
 	struct rate_config rate_config;
 	unsigned int div_factor;
@@ -223,26 +227,42 @@ struct clcd_rate_tbl {
 	u16 div;
 };
 
+/* ddr min, max clk rate table */
+struct ddr_rate_tbl {
+	unsigned long minrate;
+	unsigned long maxrate;
+};
+
 /* platform specific clock functions */
+/*
+ * must be called from machine clock.c file, dclk is pointer to ddr_clk
+ * strucutre. Which is required by clock framework.
+ *
+ * Actually before changing rate of DDRs ancestor, we must put ddr in refresh
+ * state and then change parent.
+ */
+void clk_init(struct clk_lookup *clk_lookups, u32 count, struct clk *dclk);
 void clk_register(struct clk_lookup *cl);
 void recalc_root_clocks(void);
 
 /* clock recalc & set rate functions */
-int follow_parent(struct clk *clk);
+int follow_parent(struct clk *clk, unsigned long *rate, unsigned long prate);
 unsigned long pll_calc_rate(struct clk *clk, int index);
-int pll_clk_recalc(struct clk *clk);
+int pll_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long bus_calc_rate(struct clk *clk, int index);
-int bus_clk_recalc(struct clk *clk);
+int bus_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+int ahbmult2_clk_recalc(struct clk *clk, unsigned long *rate,
+		unsigned long prate);
 unsigned long gpt_calc_rate(struct clk *clk, int index);
-int gpt_clk_recalc(struct clk *clk);
+int gpt_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long aux_calc_rate(struct clk *clk, int index);
-int aux_clk_recalc(struct clk *clk);
+int aux_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long clcd_calc_rate(struct clk *clk, int index);
-int clcd_clk_recalc(struct clk *clk);
+int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 
 #endif /* __PLAT_CLOCK_H */
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:27 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:27 +0530
Subject: [PATCH V2 67/69] ST SPEAr: Adding devices & clocks
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <37ba474609afa0bc34499291d221064a7ae4b33c.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
---
 arch/arm/mach-spear13xx/clock.c                  |   39 ++++++++
 arch/arm/mach-spear13xx/include/mach/generic.h   |    7 ++
 arch/arm/mach-spear13xx/include/mach/irqs.h      |   10 +-
 arch/arm/mach-spear13xx/include/mach/spear1310.h |   34 +++++++
 arch/arm/mach-spear13xx/spear1310.c              |  107 ++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear1310_evb.c          |   32 +++++++
 arch/arm/mach-spear3xx/spear310_evb.c            |    5 +
 arch/arm/mach-spear3xx/spear320_evb.c            |    6 +
 8 files changed, 235 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 0755e9f..4c5dbfa 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -1025,6 +1025,40 @@ static struct clk gmac_phy4_clk = {
 	.recalc = &follow_parent,
 };
 
+/* uart1 clock */
+static struct clk uart1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_pclk_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart2 clock */
+static struct clk uart2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_pclk_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart3 clock */
+static struct clk uart3_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_pclk_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart4 clock */
+static struct clk uart4_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_pclk_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart5 clock */
+static struct clk uart5_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ras_pclk_clk,
+	.recalc = &follow_parent,
+};
 #endif
 
 static struct clk dummy_apb_pclk;
@@ -1138,6 +1172,11 @@ static struct clk_lookup spear1310_clk_lookups[] = {
 	{.dev_id = "stmmacphy.2",	.clk = &gmac_phy2_clk},
 	{.dev_id = "stmmacphy.3",	.clk = &gmac_phy3_clk},
 	{.dev_id = "stmmacphy.4",	.clk = &gmac_phy4_clk},
+	{.dev_id = "uart1",		.clk = &uart1_clk},
+	{.dev_id = "uart2",		.clk = &uart2_clk},
+	{.dev_id = "uart3",		.clk = &uart3_clk},
+	{.dev_id = "uart4",		.clk = &uart4_clk},
+	{.dev_id = "uart5",		.clk = &uart5_clk},
 };
 #endif
 
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index e005936..e7f1dd6 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -261,8 +261,15 @@ void __init spear1300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 /* spear1310 declarations */
 #ifdef CONFIG_MACH_SPEAR1310
 /* Add spear1310 machine device structure declarations here */
+extern struct amba_device spear1310_uart1_device;
+extern struct amba_device spear1310_uart2_device;
+extern struct amba_device spear1310_uart3_device;
+extern struct amba_device spear1310_uart4_device;
+extern struct amba_device spear1310_uart5_device;
 extern struct platform_device spear1310_can0_device;
 extern struct platform_device spear1310_can1_device;
+extern struct platform_device spear1310_i2c1_device;
+extern struct platform_device spear1310_ras_fsmc_nor_device;
 
 /* Add spear1310 machine function declarations here */
 void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
diff --git a/arch/arm/mach-spear13xx/include/mach/irqs.h b/arch/arm/mach-spear13xx/include/mach/irqs.h
index 1ca70a6..59bf61a 100644
--- a/arch/arm/mach-spear13xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear13xx/include/mach/irqs.h
@@ -97,11 +97,11 @@
 #define IRQ_CCAN1		(IRQ_SHPI_START + 83)
 #define IRQ_TDM0		(IRQ_SHPI_START + 84)
 #define IRQ_TDM1		(IRQ_SHPI_START + 85)
-#define IRQ_UART0		(IRQ_SHPI_START + 86)
-#define IRQ_UART1		(IRQ_SHPI_START + 87)
-#define IRQ_UART2		(IRQ_SHPI_START + 88)
-#define IRQ_UART3		(IRQ_SHPI_START + 89)
-#define IRQ_UART4		(IRQ_SHPI_START + 90)
+#define IRQ_UART1		(IRQ_SHPI_START + 86)
+#define IRQ_UART2		(IRQ_SHPI_START + 87)
+#define IRQ_UART3		(IRQ_SHPI_START + 88)
+#define IRQ_UART4		(IRQ_SHPI_START + 89)
+#define IRQ_UART5		(IRQ_SHPI_START + 90)
 #define IRQ_I2C_CNTR		(IRQ_SHPI_START + 91)
 #define IRQ_GMAC0_SBD		(IRQ_SHPI_START + 92)
 #define IRQ_GMAC0_PMT		(IRQ_SHPI_START + 93)
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310.h b/arch/arm/mach-spear13xx/include/mach/spear1310.h
index e57c99a..4ffd2fa 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear1310.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear1310.h
@@ -16,9 +16,33 @@
 #ifndef __MACH_SPEAR1310_H
 #define __MACH_SPEAR1310_H
 
+#define SPEAR1310_TDM_E1_0_BASE		UL(0x6C200000)
+#define SPEAR1310_TDM_E1_1_BASE		UL(0x6C300000)
+#define SPEAR1310_RS485_0_BASE		UL(0x6C400000)
+#define SPEAR1310_RS485_1_BASE		UL(0x6C500000)
+#define SPEAR1310_RAS_BASE		UL(0x6C800000)
+#define SPEAR1310_GETH1_BASE		UL(0x6D000000)
+#define SPEAR1310_GETH2_BASE		UL(0x6D100000)
+#define SPEAR1310_GETH3_BASE		UL(0x6D200000)
+#define SPEAR1310_GETH4_BASE		UL(0x6D300000)
+#define SPEAR1310_UART1_BASE		UL(0x6D400000)
+#define SPEAR1310_UART2_BASE		UL(0x6D500000)
+#define SPEAR1310_UART3_BASE		UL(0x6D600000)
+#define SPEAR1310_UART4_BASE		UL(0x6D700000)
+#define SPEAR1310_UART5_BASE		UL(0x6D800000)
+#define SPEAR1310_I2C1_BASE		UL(0x6D900000)
 #define SPEAR1310_CAN0_BASE		UL(0x6DA00000)
 #define SPEAR1310_CAN1_BASE		UL(0x6DB00000)
 #define SPEAR1310_RAS_BASE		UL(0x6C800000)
+#define SPEAR1310_GETH1_BASE		UL(0x6D000000)
+#define SPEAR1310_GETH2_BASE		UL(0x6D100000)
+#define SPEAR1310_GETH3_BASE		UL(0x6D200000)
+#define SPEAR1310_GETH4_BASE		UL(0x6D300000)
+#define SPEAR1310_FSMC1_CS0_BASE	UL(0x70000000)
+#define SPEAR1310_FSMC1_CS1_BASE	UL(0x74000000)
+#define SPEAR1310_FSMC1_CS2_BASE	UL(0x78000000)
+#define SPEAR1310_FSMC1_CS3_BASE	UL(0x7C000000)
+#define SPEAR1310_FSMC1_BASE		UL(0x6FF00000)
 
 /* RAS Area Control Register */
 #define SPEAR1310_RAS_CTRL_REG0		(SPEAR1310_RAS_BASE + 0x0)
@@ -26,6 +50,16 @@
 #define SPEAR1310_PHY_CLK_MASK		0xF
 #define SPEAR1310_PHY_CLK_SHIFT		0
 
+#define RAS_FSMC_MODE_MASK		0x3
+#define RAS_FSMC_MODE_NOR		0
+#define RAS_FSMC_MODE_NAND		1
+#define RAS_FSMC_MODE_SRAM		2
+#define RAS_FSMC_WIDTH_MASK		0x30
+#define RAS_FSMC_WIDTH_8		0x00
+#define RAS_FSMC_WIDTH_16		0x10
+#define RAS_FSMC_WIDTH_32		0x20
+#define RAS_FSMC_CS_SPLIT		0x40
+
 #endif /* __MACH_SPEAR1310_H */
 
 #endif /* CONFIG_MACH_SPEAR1310 */
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 375f5b2..05cf8c7 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
+#include <linux/mtd/physmap.h>
 #include <linux/ptrace.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
@@ -355,6 +357,70 @@ struct pmx_dev pmx_can = {
 };
 
 /* Add spear1310 specific devices here */
+/* uart1 device registeration */
+struct amba_device spear1310_uart1_device = {
+	.dev = {
+		.init_name = "uart1",
+	},
+	.res = {
+		.start = SPEAR1310_UART1_BASE,
+		.end = SPEAR1310_UART1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_UART1, NO_IRQ},
+};
+
+/* uart2 device registeration */
+struct amba_device spear1310_uart2_device = {
+	.dev = {
+		.init_name = "uart2",
+	},
+	.res = {
+		.start = SPEAR1310_UART2_BASE,
+		.end = SPEAR1310_UART2_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_UART2, NO_IRQ},
+};
+
+/* uart3 device registeration */
+struct amba_device spear1310_uart3_device = {
+	.dev = {
+		.init_name = "uart3",
+	},
+	.res = {
+		.start = SPEAR1310_UART3_BASE,
+		.end = SPEAR1310_UART3_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_UART3, NO_IRQ},
+};
+
+/* uart4 device registeration */
+struct amba_device spear1310_uart4_device = {
+	.dev = {
+		.init_name = "uart4",
+	},
+	.res = {
+		.start = SPEAR1310_UART4_BASE,
+		.end = SPEAR1310_UART4_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_UART4, NO_IRQ},
+};
+
+/* uart5 device registeration */
+struct amba_device spear1310_uart5_device = {
+	.dev = {
+		.init_name = "uart5",
+	},
+	.res = {
+		.start = SPEAR1310_UART5_BASE,
+		.end = SPEAR1310_UART5_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_UART5, NO_IRQ},
+};
 
 /* CAN device registeration */
 static struct resource can0_resources[] = {
@@ -393,6 +459,47 @@ struct platform_device spear1310_can1_device = {
 	.resource = can1_resources,
 };
 
+/* i2c1 device registeration */
+static struct resource i2c1_resources[] = {
+	{
+		.start = SPEAR1310_I2C1_BASE,
+		.end = SPEAR1310_I2C1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_I2C_CNTR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear1310_i2c1_device = {
+	.name = "i2c_designware",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c1_resources),
+	.resource = i2c1_resources,
+};
+
+/* fsmc nor flash device registeration */
+static struct physmap_flash_data ras_fsmc_norflash_data;
+
+static struct resource ras_fsmc_nor_resources[] = {
+	{
+		.start	= SPEAR1310_FSMC1_CS3_BASE,
+		.end	= SPEAR1310_FSMC1_CS3_BASE + SZ_64M - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear1310_ras_fsmc_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.resource = ras_fsmc_nor_resources,
+	.num_resources = ARRAY_SIZE(ras_fsmc_nor_resources),
+	.dev.platform_data = &ras_fsmc_norflash_data,
+};
+
 void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count)
 {
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index a263b40..e4cf267 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -67,6 +67,13 @@ static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[1],
 	&spear13xx_ssp_device,
 	&spear13xx_uart_device,
+
+	/* spear1310 specific devices */
+	&spear1310_uart1_device,
+	&spear1310_uart2_device,
+	&spear1310_uart3_device,
+	&spear1310_uart4_device,
+	&spear1310_uart5_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
@@ -86,6 +93,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear1310 specific devices */
 	&spear1310_can0_device,
 	&spear1310_can1_device,
+	&spear1310_i2c1_device,
 };
 
 /* keyboard specific platform data */
@@ -129,6 +137,23 @@ int spear1310_pcie_port_is_host(int port)
 }
 #endif
 
+static void  __init ras_fsmc_config(u32 mode, u32 width)
+{
+	u32 val, *address;
+
+	address = ioremap(SPEAR1310_RAS_CTRL_REG0, SZ_16);
+
+	val = readl(address);
+	val &= ~(RAS_FSMC_MODE_MASK | RAS_FSMC_WIDTH_MASK);
+	val |= mode;
+	val |= width;
+	val |= RAS_FSMC_CS_SPLIT;
+
+	writel(val, address);
+
+	iounmap(address);
+}
+
 static void __init spear1310_evb_init(void)
 {
 	unsigned int i;
@@ -153,6 +178,8 @@ static void __init spear1310_evb_init(void)
 	/* initialize fsmc related data in fsmc plat data */
 	fsmc_init_board_info(&spear13xx_fsmc_nor_device, partition_info,
 			ARRAY_SIZE(partition_info), FSMC_FLASH_WIDTH8);
+	fsmc_init_board_info(&spear1310_ras_fsmc_nor_device, NULL,
+			0, FSMC_FLASH_WIDTH16);
 
 	/* Initialize fsmc regiters */
 	fsmc_nor_init(&spear13xx_fsmc_nor_device, SPEAR13XX_FSMC_BASE, 0,
@@ -171,6 +198,11 @@ static void __init spear1310_evb_init(void)
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
 
+	/* ras fsmc init */
+	ras_fsmc_config(RAS_FSMC_MODE_NOR, RAS_FSMC_WIDTH_16);
+	fsmc_nor_init(&spear1310_ras_fsmc_nor_device, SPEAR1310_FSMC1_BASE, 3,
+			FSMC_FLASH_WIDTH16);
+
 	spi_init();
 }
 
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 2c1044d..5cccd2d 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -75,6 +75,11 @@ static struct amba_device *amba_devs[] __initdata = {
 	&spear3xx_wdt_device,
 
 	/* spear310 specific devices */
+	&spear310_uart1_device,
+	&spear310_uart2_device,
+	&spear310_uart3_device,
+	&spear310_uart4_device,
+	&spear310_uart5_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 116dd1b..4446cb1 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -68,11 +68,16 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
 	&spear3xx_uart_device,
 	&spear3xx_wdt_device,
 
 	/* spear320 specific devices */
 	&spear320_clcd_device,
+	&spear320_ssp_device[0],
+	&spear320_ssp_device[1],
+	&spear320_uart1_device,
+	&spear320_uart2_device,
 };
 
 static struct platform_device *plat_devs[] __initdata = {
@@ -87,6 +92,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear320 specific devices */
 	&spear320_can0_device,
 	&spear320_can1_device,
+	&spear320_emi_nor_device,
 	&spear320_i2c1_device,
 	&spear320_nand_device,
 	&spear320_plgpio_device,
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:23 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:23 +0530
Subject: [PATCH V2 63/69] ST SPEAr3xx: Updating plgpio and emi source to make
	it compliant with single image strategy
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <ea27f60aea71a84a2c42e0c8c24144398c7e757b.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/emi.c               |   18 ++++++++++-
 arch/arm/mach-spear3xx/include/mach/emi.h  |   19 ++++++-----
 arch/arm/mach-spear3xx/include/mach/gpio.h |   27 ++++++++--------
 arch/arm/plat-spear/plgpio.c               |   46 ++++++++++++++++++++-------
 4 files changed, 75 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-spear3xx/emi.c b/arch/arm/mach-spear3xx/emi.c
index 7b62ff0..7d7cea7 100644
--- a/arch/arm/mach-spear3xx/emi.c
+++ b/arch/arm/mach-spear3xx/emi.c
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <asm/mach-types.h>
 #include <mach/emi.h>
 
 int __init emi_init(struct platform_device *pdev, unsigned long base,
@@ -23,8 +24,23 @@ int __init emi_init(struct platform_device *pdev, unsigned long base,
 	void __iomem *emi_reg_base;
 	struct clk *clk;
 	int ret;
+	u32 ack_reg, max_banks;
+	/* u32 timeout_reg, irq_reg; */
+
+	/* fixing machine dependent values */
+	if (machine_is_spear310()) {
+		ack_reg = SPEAR310_ACK_REG;
+		max_banks = SPEAR310_EMI_MAX_BANKS;
+		/* timeout_reg = SPEAR310_TIMEOUT_REG; */
+		/* irq_reg = SPEAR310_IRQ_REG; */
+	} else {
+		ack_reg = SPEAR320_ACK_REG;
+		max_banks = SPEAR320_EMI_MAX_BANKS;
+		/* timeout_reg = SPEAR320_TIMEOUT_REG; */
+		/* irq_reg = SPEAR320_IRQ_REG; */
+	}
 
-	if (bank > (EMI_MAX_BANKS - 1))
+	if (bank > (max_banks - 1))
 		return -EINVAL;
 
 	emi_reg_base = ioremap(base, EMI_REG_SIZE);
diff --git a/arch/arm/mach-spear3xx/include/mach/emi.h b/arch/arm/mach-spear3xx/include/mach/emi.h
index b620bf5..59f69c4 100644
--- a/arch/arm/mach-spear3xx/include/mach/emi.h
+++ b/arch/arm/mach-spear3xx/include/mach/emi.h
@@ -33,18 +33,19 @@
 #define CTRL_REG		(0x14)
 
 #if defined(CONFIG_MACH_SPEAR310)
-#define TIMEOUT_REG		(0x90)
-#define ACK_REG			(0x94)
-#define IRQ_REG			(0x98)
+#define SPEAR310_TIMEOUT_REG	(0x90)
+#define SPEAR310_ACK_REG	(0x94)
+#define SPEAR310_IRQ_REG	(0x98)
 
-#define EMI_MAX_BANKS		6
+#define SPEAR310_EMI_MAX_BANKS	6
+#endif
 
-#elif defined(CONFIG_MACH_SPEAR320)
-#define TIMEOUT_REG		(0x60)
-#define ACK_REG			(0x64)
-#define IRQ_REG			(0x68)
+#if defined(CONFIG_MACH_SPEAR320)
+#define SPEAR320_TIMEOUT_REG	(0x60)
+#define SPEAR320_ACK_REG	(0x64)
+#define SPEAR320_IRQ_REG	(0x68)
 
-#define EMI_MAX_BANKS		4
+#define SPEAR320_EMI_MAX_BANKS	4
 
 #endif
 
diff --git a/arch/arm/mach-spear3xx/include/mach/gpio.h b/arch/arm/mach-spear3xx/include/mach/gpio.h
index f15248c..0c13d8c 100644
--- a/arch/arm/mach-spear3xx/include/mach/gpio.h
+++ b/arch/arm/mach-spear3xx/include/mach/gpio.h
@@ -17,20 +17,21 @@
 #include <plat/gpio.h>
 
 #ifdef CONFIG_MACH_SPEAR310
-#define PLGPIO_ENB		0x0010
-#define PLGPIO_WDATA		0x0020
-#define PLGPIO_DIR		0x0030
-#define PLGPIO_IE		0x0040
-#define PLGPIO_RDATA		0x0050
-#define PLGPIO_MIS		0x0060
+#define SPEAR310_PLGPIO_ENB		0x0010
+#define SPEAR310_PLGPIO_WDATA		0x0020
+#define SPEAR310_PLGPIO_DIR		0x0030
+#define SPEAR310_PLGPIO_IE		0x0040
+#define SPEAR310_PLGPIO_RDATA		0x0050
+#define SPEAR310_PLGPIO_MIS		0x0060
+#endif
 
-#elif defined(CONFIG_MACH_SPEAR320)
-#define PLGPIO_ENB		0x0024
-#define PLGPIO_WDATA		0x0034
-#define PLGPIO_DIR		0x0044
-#define PLGPIO_RDATA		0x0054
-#define PLGPIO_IE		0x0064
-#define PLGPIO_MIS		0x0074
+#if defined(CONFIG_MACH_SPEAR320)
+#define SPEAR320_PLGPIO_ENB		0x0024
+#define SPEAR320_PLGPIO_WDATA		0x0034
+#define SPEAR320_PLGPIO_DIR		0x0044
+#define SPEAR320_PLGPIO_RDATA		0x0054
+#define SPEAR320_PLGPIO_IE		0x0064
+#define SPEAR320_PLGPIO_MIS		0x0074
 #endif
 
 #define BASIC_GPIO_0		0
diff --git a/arch/arm/plat-spear/plgpio.c b/arch/arm/plat-spear/plgpio.c
index 3080178..f5220c0 100644
--- a/arch/arm/plat-spear/plgpio.c
+++ b/arch/arm/plat-spear/plgpio.c
@@ -22,12 +22,16 @@
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <asm/mach-types.h>
 
 #define MAX_GPIO_PER_REG		32
 #define PIN_OFFSET(pin)			(pin % MAX_GPIO_PER_REG)
 #define REG_OFFSET(base, reg, pin)	(base + reg + (pin / MAX_GPIO_PER_REG)\
 		* sizeof(int *))
 
+static u32 plgpio_enb, plgpio_wdata, plgpio_dir, plgpio_rdata, plgpio_ie,
+	   plgpio_mis;
+
 /*
  * struct plgpio: plgpio driver specific structure
  *
@@ -96,7 +100,7 @@ static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_set(plgpio->base, offset, PLGPIO_DIR);
+	plgpio_reg_set(plgpio->base, offset, plgpio_dir);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 
 	return 0;
@@ -125,11 +129,11 @@ static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_reset(plgpio->base, dir_offset, PLGPIO_DIR);
+	plgpio_reg_reset(plgpio->base, dir_offset, plgpio_dir);
 	if (value)
-		plgpio_reg_set(plgpio->base, wdata_offset, PLGPIO_WDATA);
+		plgpio_reg_set(plgpio->base, wdata_offset, plgpio_wdata);
 	else
-		plgpio_reg_reset(plgpio->base, wdata_offset, PLGPIO_WDATA);
+		plgpio_reg_reset(plgpio->base, wdata_offset, plgpio_wdata);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 
 	return 0;
@@ -149,7 +153,7 @@ static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
 			return -EINVAL;
 	}
 
-	return is_plgpio_set(plgpio->base, offset, PLGPIO_RDATA);
+	return is_plgpio_set(plgpio->base, offset, plgpio_rdata);
 }
 
 static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
@@ -167,9 +171,9 @@ static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
 	}
 
 	if (value)
-		plgpio_reg_set(plgpio->base, offset, PLGPIO_WDATA);
+		plgpio_reg_set(plgpio->base, offset, plgpio_wdata);
 	else
-		plgpio_reg_reset(plgpio->base, offset, PLGPIO_WDATA);
+		plgpio_reg_reset(plgpio->base, offset, plgpio_wdata);
 }
 
 static int plgpio_request(struct gpio_chip *chip, unsigned offset)
@@ -196,7 +200,7 @@ static int plgpio_request(struct gpio_chip *chip, unsigned offset)
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_set(plgpio->base, offset, PLGPIO_ENB);
+	plgpio_reg_set(plgpio->base, offset, plgpio_enb);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 
 	return 0;
@@ -218,7 +222,7 @@ static void plgpio_free(struct gpio_chip *chip, unsigned offset)
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_reset(plgpio->base, offset, PLGPIO_ENB);
+	plgpio_reg_reset(plgpio->base, offset, plgpio_enb);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 }
 
@@ -247,7 +251,7 @@ static void plgpio_irq_mask(unsigned irq)
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_set(plgpio->base, offset, PLGPIO_IE);
+	plgpio_reg_set(plgpio->base, offset, plgpio_ie);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 }
 
@@ -265,7 +269,7 @@ static void plgpio_irq_unmask(unsigned irq)
 	}
 
 	spin_lock_irqsave(&plgpio->lock, flags);
-	plgpio_reg_reset(plgpio->base, offset, PLGPIO_IE);
+	plgpio_reg_reset(plgpio->base, offset, plgpio_ie);
 	spin_unlock_irqrestore(&plgpio->lock, flags);
 }
 
@@ -298,7 +302,7 @@ static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
 
 	/* check all plgpio MIS registers for a possible interrupt */
 	for (; i < regs_count; i++) {
-		pending = readl(plgpio->base + PLGPIO_MIS + i * sizeof(int *));
+		pending = readl(plgpio->base + plgpio_mis + i * sizeof(int *));
 		if (!pending)
 			continue;
 
@@ -443,6 +447,24 @@ static struct platform_driver plgpio_driver = {
 
 static int __init plgpio_init(void)
 {
+	if (machine_is_spear310()) {
+		plgpio_enb = SPEAR310_PLGPIO_ENB;
+		plgpio_wdata = SPEAR310_PLGPIO_WDATA;
+		plgpio_dir = SPEAR310_PLGPIO_DIR;
+		plgpio_rdata = SPEAR310_PLGPIO_IE;
+		plgpio_ie = SPEAR310_PLGPIO_RDATA;
+		plgpio_mis = SPEAR310_PLGPIO_MIS;
+	} else if (machine_is_spear320()) {
+		plgpio_enb = SPEAR320_PLGPIO_ENB;
+		plgpio_wdata = SPEAR320_PLGPIO_WDATA;
+		plgpio_dir = SPEAR320_PLGPIO_DIR;
+		plgpio_rdata = SPEAR320_PLGPIO_IE;
+		plgpio_ie = SPEAR320_PLGPIO_RDATA;
+		plgpio_mis = SPEAR320_PLGPIO_MIS;
+	} else {
+		return 0;
+	}
+
 	return platform_driver_register(&plgpio_driver);
 }
 subsys_initcall(plgpio_init);
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:20 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:20 +0530
Subject: [PATCH V2 60/69] SPEAr3xx: Rework KConfig to allow all boards to be
	compiled in
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <f8b5dc3a172af01285cbbb4f5dc889bf57d72efe.1285933332.git.viresh.kumar@st.com>

From: Ryan Mallon <ryan at bluewatersys.com>

Now that all three SPEAr3xx platforms can be built into one kernel,
rework KConfig to allow this. Move everything into one KConfig file
while we are here.

Signed-off-by: Ryan Mallon <ryan at bluewatersys.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear3xx/Kconfig                |   30 ++++++++++++++++--------
 arch/arm/mach-spear3xx/Kconfig300             |   17 --------------
 arch/arm/mach-spear3xx/Kconfig310             |   17 --------------
 arch/arm/mach-spear3xx/Kconfig320             |   17 --------------
 arch/arm/mach-spear3xx/include/mach/generic.h |    6 +++-
 5 files changed, 24 insertions(+), 63 deletions(-)
 delete mode 100644 arch/arm/mach-spear3xx/Kconfig300
 delete mode 100644 arch/arm/mach-spear3xx/Kconfig310
 delete mode 100644 arch/arm/mach-spear3xx/Kconfig320

diff --git a/arch/arm/mach-spear3xx/Kconfig b/arch/arm/mach-spear3xx/Kconfig
index 20d1317..2cee6b0 100644
--- a/arch/arm/mach-spear3xx/Kconfig
+++ b/arch/arm/mach-spear3xx/Kconfig
@@ -4,9 +4,26 @@
 
 if ARCH_SPEAR3XX
 
-choice
-	prompt "SPEAr3XX Family"
-	default MACH_SPEAR300
+menu "SPEAr3xx Implementations"
+config BOARD_SPEAR300_EVB
+	bool "SPEAr300 Evaluation Board"
+	select MACH_SPEAR300
+	help
+	  Supports ST SPEAr300 Evaluation Board
+
+config BOARD_SPEAR310_EVB
+	bool "SPEAr310 Evaluation Board"
+	select MACH_SPEAR310
+	help
+	  Supports ST SPEAr310 Evaluation Board
+
+config BOARD_SPEAR320_EVB
+	bool "SPEAr320 Evaluation Board"
+	select MACH_SPEAR320
+	help
+	  Supports ST SPEAr320 Evaluation Board
+
+endmenu
 
 config MACH_SPEAR300
 	bool "SPEAr300"
@@ -23,11 +40,4 @@ config MACH_SPEAR320
 	help
 	  Supports ST SPEAr320 Machine
 
-endchoice
-
-# Adding SPEAr3XX machine specific configuration files
-source "arch/arm/mach-spear3xx/Kconfig300"
-source "arch/arm/mach-spear3xx/Kconfig310"
-source "arch/arm/mach-spear3xx/Kconfig320"
-
 endif #ARCH_SPEAR3XX
diff --git a/arch/arm/mach-spear3xx/Kconfig300 b/arch/arm/mach-spear3xx/Kconfig300
deleted file mode 100644
index c519a05..0000000
--- a/arch/arm/mach-spear3xx/Kconfig300
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# SPEAr300 machine configuration file
-#
-
-if MACH_SPEAR300
-
-choice
-	prompt "SPEAr300 Boards"
-	default BOARD_SPEAR300_EVB
-
-config BOARD_SPEAR300_EVB
-	bool "SPEAr300 Evaluation Board"
-	help
-	  Supports ST SPEAr300 Evaluation Board
-endchoice
-
-endif	#MACH_SPEAR300
diff --git a/arch/arm/mach-spear3xx/Kconfig310 b/arch/arm/mach-spear3xx/Kconfig310
deleted file mode 100644
index 60e7442..0000000
--- a/arch/arm/mach-spear3xx/Kconfig310
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# SPEAr310 machine configuration file
-#
-
-if MACH_SPEAR310
-
-choice
-	prompt "SPEAr310 Boards"
-	default BOARD_SPEAR310_EVB
-
-config BOARD_SPEAR310_EVB
-	bool "SPEAr310 Evaluation Board"
-	help
-	  Supports ST SPEAr310 Evaluation Board
-endchoice
-
-endif	#MACH_SPEAR310
diff --git a/arch/arm/mach-spear3xx/Kconfig320 b/arch/arm/mach-spear3xx/Kconfig320
deleted file mode 100644
index 1c1d438..0000000
--- a/arch/arm/mach-spear3xx/Kconfig320
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# SPEAr320 machine configuration file
-#
-
-if MACH_SPEAR320
-
-choice
-	prompt "SPEAr320 Boards"
-	default BOARD_SPEAR320_EVB
-
-config BOARD_SPEAR320_EVB
-	bool "SPEAr320 Evaluation Board"
-	help
-	  Supports ST SPEAr320 Evaluation Board
-endchoice
-
-endif	#MACH_SPEAR320
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index cef82e8..3138137 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -161,9 +161,10 @@ void sdhci_i2s_mem_enable(u8 mask);
 
 /* Add misc structure declarations here */
 extern struct clcd_board clcd_plat_data;
+#endif
 
 /* spear310 declarations */
-#elif defined(CONFIG_MACH_SPEAR310)
+#if defined(CONFIG_MACH_SPEAR310)
 /* Add spear310 machine device structure declarations here */
 extern struct amba_device uart1_device;
 extern struct amba_device uart2_device;
@@ -188,9 +189,10 @@ extern struct pmx_dev spear310_pmx_tdm0;
 /* Add spear310 machine function declarations here */
 void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count);
+#endif
 
 /* spear320 declarations */
-#elif defined(CONFIG_MACH_SPEAR320)
+#if defined(CONFIG_MACH_SPEAR320)
 /* Add spear320 machine device structure declarations here */
 extern struct amba_device clcd_device;
 extern struct amba_device ssp_device[];
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:46 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:46 +0530
Subject: [PATCH V2 26/69] ST SPEAr: Adding support for serial nor flash in all
	spear platforms
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <76fc3473e51833e5058c5323c5cf50f7b1c8a219.1285933331.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

Adding smi device support and enumerating all serial nor flashes present
in spear(spear3xx/spear6xx/spear13xx) evaluation boards.

Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |    5 ++
 arch/arm/mach-spear13xx/spear13xx.c            |   19 +++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear3xx/spear300_evb.c          |    5 ++
 arch/arm/mach-spear3xx/spear310_evb.c          |    5 ++
 arch/arm/mach-spear3xx/spear320_evb.c          |    5 ++
 arch/arm/mach-spear3xx/spear3xx.c              |   19 +++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c          |    5 ++
 arch/arm/mach-spear6xx/spear6xx.c              |   19 +++++++
 arch/arm/plat-spear/Makefile                   |    2 +-
 arch/arm/plat-spear/include/plat/smi.h         |    3 +
 arch/arm/plat-spear/smi.c                      |   63 ++++++++++++++++++++++++
 14 files changed, 152 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/plat-spear/smi.c

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index f3e6d95..960ff06 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -38,6 +38,7 @@ extern struct platform_device spear13xx_kbd_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
+extern struct platform_device spear13xx_smi_device;
 extern struct sys_timer spear13xx_timer;
 
 /* Add spear1300 machine device structure declarations here */
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 2b2598c..1e637fa 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -17,6 +17,7 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 #include <plat/keyboard.h>
+#include <plat/smi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[0],
@@ -32,6 +33,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
+	&spear13xx_smi_device,
 };
 
 /* keyboard specific platform data */
@@ -56,6 +58,9 @@ static void __init spear1300_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&spear13xx_smi_device);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 2037cd2..f7d30a9 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -241,6 +241,25 @@ struct platform_device spear13xx_rtc_device = {
 	.resource = rtc_resources,
 };
 
+/* smi device registration */
+static struct resource smi_resources[] = {
+	{
+		.start = SPEAR13XX_SMI_CTRL_BASE,
+		.end = SPEAR13XX_SMI_CTRL_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_SMI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear13xx_smi_device = {
+	.name = "smi",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(smi_resources),
+	.resource = smi_resources,
+};
+
 /* Do spear13xx familiy common initialization part here */
 void __init spear13xx_init(void)
 {
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 447de7e..9317af8 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -38,6 +38,7 @@ extern struct platform_device i2c_device;
 extern struct platform_device ohci0_device;
 extern struct platform_device ohci1_device;
 extern struct platform_device rtc_device;
+extern struct platform_device smi_device;
 extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index afb773e..c948289 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -16,6 +16,7 @@
 #include <mach/generic.h>
 #include <mach/spear.h>
 #include <plat/keyboard.h>
+#include <plat/smi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -50,6 +51,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
+	&smi_device,
 
 	/* spear300 specific devices */
 	&kbd_device,
@@ -82,6 +84,9 @@ static void __init spear300_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&smi_device);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index d523040..2a88cd2 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -15,6 +15,7 @@
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/smi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -55,6 +56,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
+	&smi_device,
 
 	/* spear310 specific devices */
 	&plgpio_device,
@@ -75,6 +77,9 @@ static void __init spear310_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&smi_device);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 943eddc..d0cfd96 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -15,6 +15,7 @@
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/smi.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -53,6 +54,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
+	&smi_device,
 
 	/* spear320 specific devices */
 	&i2c1_device,
@@ -72,6 +74,9 @@ static void __init spear320_evb_init(void)
 	/* call spear320 machine init function */
 	spear320_init();
 
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&smi_device);
+
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 61d607b..ff9f6e9 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -175,6 +175,25 @@ struct platform_device rtc_device = {
 	.resource = rtc_resources,
 };
 
+/* smi device registration */
+static struct resource smi_resources[] = {
+	{
+		.start = SPEAR3XX_ICM3_SMI_CTRL_BASE,
+		.end = SPEAR3XX_ICM3_SMI_CTRL_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_BASIC_SMI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device smi_device = {
+	.name = "smi",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(smi_resources),
+	.resource = smi_resources,
+};
+
 /* Do spear3xx familiy common initialization part here */
 void __init spear3xx_init(void)
 {
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 3b15289..8aee3ad 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -38,6 +38,7 @@ extern struct platform_device i2c_device;
 extern struct platform_device ohci0_device;
 extern struct platform_device ohci1_device;
 extern struct platform_device rtc_device;
+extern struct platform_device smi_device;
 extern struct sys_timer spear6xx_timer;
 
 /* Add spear6xx family function declarations here */
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index b4dfd25..bd4be34 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -15,6 +15,7 @@
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <plat/smi.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&clcd_device,
@@ -32,6 +33,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&ohci0_device,
 	&ohci1_device,
 	&rtc_device,
+	&smi_device,
 };
 
 static void __init spear600_evb_init(void)
@@ -44,6 +46,9 @@ static void __init spear600_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_board_devices();
 
+	/* initialize serial nor related data in smi plat data */
+	smi_init_board_info(&smi_device);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index e78c2e5..000b3a8 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -267,6 +267,25 @@ struct platform_device rtc_device = {
 	.resource = rtc_resources,
 };
 
+/* smi device registration */
+static struct resource smi_resources[] = {
+	{
+		.start = SPEAR6XX_ICM3_SMI_CTRL_BASE,
+		.end = SPEAR6XX_ICM3_SMI_CTRL_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_BASIC_SMI,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device smi_device = {
+	.name = "smi",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(smi_resources),
+	.resource = smi_resources,
+};
+
 /* This will add devices, and do machine specific tasks */
 void __init spear6xx_init(void)
 {
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 0e29587..b8a7403 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y	:= clcd.o clock.o time.o
+obj-y	:= clcd.o clock.o time.o smi.o
 
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
diff --git a/arch/arm/plat-spear/include/plat/smi.h b/arch/arm/plat-spear/include/plat/smi.h
index 4c74df7..37dbd5e 100644
--- a/arch/arm/plat-spear/include/plat/smi.h
+++ b/arch/arm/plat-spear/include/plat/smi.h
@@ -65,4 +65,7 @@ static inline void smi_set_plat_data(struct platform_device *pdev,
 	pdev->dev.platform_data = pdata;
 }
 
+/* function used to initialize default smi platform data */
+void smi_init_board_info(struct platform_device *pdev);
+
 #endif /* __PLAT_SMI_H */
diff --git a/arch/arm/plat-spear/smi.c b/arch/arm/plat-spear/smi.c
new file mode 100644
index 0000000..ebdaeec
--- /dev/null
+++ b/arch/arm/plat-spear/smi.c
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/plat-spear/smi.c
+ *
+ * spear smi platform intialization
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/mach-types.h>
+#include <plat/smi.h>
+#include <mach/spear.h>
+
+/*
+ * physical base address of flash/bank mem map base associated with smi
+ * depends on SoC
+ */
+
+#if defined(CONFIG_ARCH_SPEAR13XX)
+#define FLASH_MEM_BASE	SPEAR13XX_SMI_MEM_BASE
+
+#elif defined(CONFIG_ARCH_SPEAR3XX)
+#define FLASH_MEM_BASE	SPEAR3XX_ICM3_SMEM_BASE
+
+#elif defined(CONFIG_ARCH_SPEAR6XX)
+#define FLASH_MEM_BASE	SPEAR6XX_ICM3_SMEM_BASE
+
+#endif
+
+/* serial nor flash specific board data */
+static struct mtd_partition nor_partition_info[] = {
+	DEFINE_PARTS("Xloader", 0x00, 0x10000),
+	DEFINE_PARTS("UBoot", 0x10000, 0x40000),
+	DEFINE_PARTS("Kernel", 0x50000, 0x2C0000),
+	DEFINE_PARTS("Root File System", 0x310000, 0x4F0000),
+};
+
+static struct spear_smi_flash_info nor_flash_info[] = {
+	{
+		.name = "m25p64",
+		.fast_mode = 1,
+		.mem_base = FLASH_MEM_BASE,
+		.size = 8 * 1024 * 1024,
+		.num_parts = ARRAY_SIZE(nor_partition_info),
+		.parts = nor_partition_info,
+	},
+};
+
+/* smi specific board data */
+static struct spear_smi_plat_data smi_plat_data = {
+	.clk_rate = 50000000,	/* 50MHz */
+	.num_flashes = ARRAY_SIZE(nor_flash_info),
+	.board_flash_info = nor_flash_info,
+};
+
+void smi_init_board_info(struct platform_device *pdev)
+{
+	smi_set_plat_data(pdev, &smi_plat_data);
+}
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:50 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:50 +0530
Subject: [PATCH V2 30/69] ST SPEAr: Added PCIE host controller base driver
	support.
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <489a628528173741e54436d54517a1c2cc50dbdd.1285933331.git.viresh.kumar@st.com>

From: Pratyush Anand <pratyush.anand at st.com>

SPEAr13xx family contains Synopsys designware PCIE version 3.30a. This
patch adds support for this PCIE module for spear platform.

Signed-off-by: Pratyush Anand <pratyush.anand at st.com>
Signed-off-by: shiraz hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/Kconfig                                 |    5 +-
 arch/arm/mach-spear13xx/Makefile                 |    1 +
 arch/arm/mach-spear13xx/include/mach/hardware.h  |    7 +
 arch/arm/mach-spear13xx/include/mach/irqs.h      |   25 +-
 arch/arm/mach-spear13xx/include/mach/misc_regs.h |   20 +
 arch/arm/mach-spear13xx/include/mach/pcie.h      |  170 +++++
 arch/arm/mach-spear13xx/pcie.c                   |  861 ++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear1300_evb.c          |   31 +
 arch/arm/mach-spear13xx/spear13xx.c              |   28 +
 arch/arm/plat-spear/Kconfig                      |    1 +
 10 files changed, 1144 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/pcie.h
 create mode 100644 arch/arm/mach-spear13xx/pcie.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 42819a2..158bf06 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1129,7 +1129,9 @@ config ISA_DMA_API
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||\
+	ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||\
+	ARCH_SPEAR13XX
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1156,6 +1158,7 @@ config PCI_HOST_ITE8152
 	select DMABOUNCE
 
 source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index cb5ae9e..4f1cbc5 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -6,6 +6,7 @@
 obj-y					+= spear13xx.o clock.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
+obj-$(CONFIG_PCIEPORTBUS)		+= pcie.o
 
 # spear1300 specific files
 obj-$(CONFIG_MACH_SPEAR1300)		+= spear1300.o
diff --git a/arch/arm/mach-spear13xx/include/mach/hardware.h b/arch/arm/mach-spear13xx/include/mach/hardware.h
index 0047d75..4abc2c0 100644
--- a/arch/arm/mach-spear13xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear13xx/include/mach/hardware.h
@@ -22,4 +22,11 @@
 /* typesafe io address */
 #define __io_address(n)		__io(IO_ADDRESS(n))
 
+#if defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO		0
+#define PCIBIOS_MIN_MEM		0
+#define pcibios_assign_all_busses()	0
+#endif
+
+
 #endif /* __MACH_HARDWARE_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/irqs.h b/arch/arm/mach-spear13xx/include/mach/irqs.h
index 10b64c1..d2bfbb1 100644
--- a/arch/arm/mach-spear13xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear13xx/include/mach/irqs.h
@@ -80,9 +80,9 @@
 #define IRQ_USBH_OHCI0		(IRQ_SHPI_START + 65)
 #define IRQ_USBH_EHCI1		(IRQ_SHPI_START + 66)
 #define IRQ_USBH_OHCI1		(IRQ_SHPI_START + 67)
-#define IRQ_PCIE1		(IRQ_SHPI_START + 68)
-#define IRQ_PCIE2		(IRQ_SHPI_START + 69)
-#define IRQ_PCIE3		(IRQ_SHPI_START + 70)
+#define IRQ_PCIE0		(IRQ_SHPI_START + 68)
+#define IRQ_PCIE1		(IRQ_SHPI_START + 69)
+#define IRQ_PCIE2		(IRQ_SHPI_START + 70)
 
 #define IRQ_GIC_END		(IRQ_SHPI_START + 128)
 
@@ -93,7 +93,24 @@
 #define SPEAR_GPIO1_INT_BASE	(SPEAR_GPIO0_INT_BASE + 8)
 #define SPEAR_GPIO_INT_END	(SPEAR_GPIO1_INT_BASE + 8)
 
-#define VIRQ_END		SPEAR_GPIO_INT_END
+/* PCIE MSI virtual irqs */
+#define SPEAR_NUM_MSI_IRQS	64
+#define SPEAR_MSI0_INT_BASE	(SPEAR_GPIO_INT_END + 0)
+#define SPEAR_MSI0_INT_END	(SPEAR_MSI0_INT_BASE + SPEAR_NUM_MSI_IRQS)
+#define SPEAR_MSI1_INT_BASE	(SPEAR_MSI0_INT_END + 0)
+#define SPEAR_MSI1_INT_END	(SPEAR_MSI1_INT_BASE + SPEAR_NUM_MSI_IRQS)
+#define SPEAR_MSI2_INT_BASE	(SPEAR_MSI1_INT_END + 0)
+#define SPEAR_MSI2_INT_END	(SPEAR_MSI2_INT_BASE + SPEAR_NUM_MSI_IRQS)
+
+#define SPEAR_NUM_INTX_IRQS	4
+#define SPEAR_INTX0_BASE	(SPEAR_MSI2_INT_END + 0)
+#define SPEAR_INTX0_END		(SPEAR_INTX0_BASE + SPEAR_NUM_INTX_IRQS)
+#define SPEAR_INTX1_BASE	(SPEAR_INTX0_END + 0)
+#define SPEAR_INTX1_END		(SPEAR_INTX1_BASE + SPEAR_NUM_INTX_IRQS)
+#define SPEAR_INTX2_BASE	(SPEAR_INTX1_END + 0)
+#define SPEAR_INTX2_END		(SPEAR_INTX2_BASE + SPEAR_NUM_INTX_IRQS)
+
+#define VIRQ_END		SPEAR_INTX2_END
 #define NR_IRQS			VIRQ_END
 
 #endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/misc_regs.h b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
index e6823db..a7ba6cb 100644
--- a/arch/arm/mach-spear13xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear13xx/include/mach/misc_regs.h
@@ -202,6 +202,26 @@
 #define USBPHY_P2_CFG		((unsigned int *)(MISC_BASE + 0x31c))
 #define USBPHY_P3_CFG		((unsigned int *)(MISC_BASE + 0x320))
 #define PCIE_CFG		((unsigned int *)(MISC_BASE + 0x324))
+	/* PCIE CFG MASks */
+	#define PCIE2_CFG_AUX_CLK	(1 << 0)
+	#define PCIE1_CFG_AUX_CLK	(1 << 1)
+	#define PCIE0_CFG_AUX_CLK	(1 << 2)
+	#define PCIE2_CFG_CORE_CLK	(1 << 3)
+	#define PCIE1_CFG_CORE_CLK	(1 << 4)
+	#define PCIE0_CFG_CORE_CLK	(1 << 5)
+	#define PCIE2_CFG_POWERUP_RESET	(1 << 6)
+	#define PCIE1_CFG_POWERUP_RESET	(1 << 7)
+	#define PCIE0_CFG_POWERUP_RESET	(1 << 8)
+	#define PCIE2_CFG_DEVICE_PRESENT	(1 << 9)
+	#define PCIE1_CFG_DEVICE_PRESENT	(1 << 10)
+	#define PCIE0_CFG_DEVICE_PRESENT	(1 << 11)
+	#define PCIE0_CFG_VAL	(PCIE0_CFG_AUX_CLK | PCIE0_CFG_CORE_CLK \
+			| PCIE0_CFG_POWERUP_RESET | PCIE0_CFG_DEVICE_PRESENT)
+	#define PCIE1_CFG_VAL	(PCIE1_CFG_AUX_CLK | PCIE1_CFG_CORE_CLK \
+			| PCIE1_CFG_POWERUP_RESET | PCIE1_CFG_DEVICE_PRESENT)
+	#define PCIE2_CFG_VAL	(PCIE2_CFG_AUX_CLK | PCIE2_CFG_CORE_CLK \
+			| PCIE2_CFG_POWERUP_RESET | PCIE2_CFG_DEVICE_PRESENT)
+
 #define PCIE_MIPHY_CFG		((unsigned int *)(MISC_BASE + 0x328))
 #define PERIP_CFG		((unsigned int *)(MISC_BASE + 0x32c))
 	#define MCIF_SEL_SHIFT	3
diff --git a/arch/arm/mach-spear13xx/include/mach/pcie.h b/arch/arm/mach-spear13xx/include/mach/pcie.h
new file mode 100644
index 0000000..fa302e5
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/pcie.h
@@ -0,0 +1,170 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/pcie.h
+ *
+ * Spear SoC PCIe handling.
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Pratyush Anand <pratyush.anand at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_PCIE_H
+#define __MACH_PCIE_H
+
+extern int (*pcie_port_is_host)(int port);
+extern int enable_pcie0_clk(void);
+
+
+struct pcie_port {
+	u8			port;
+	u8			root_bus_nr;
+	void __iomem		*base;
+	void __iomem		*app_base;
+	void __iomem		*va_app_base;
+	void __iomem		*va_dbi_base;
+	void __iomem		*va_cfg0_base;
+	spinlock_t		conf_lock;
+	char			mem_space_name[16];
+	char			io_space_name[16];
+	struct resource		res[2];
+};
+
+struct pcie_app_reg {
+	u32	app_ctrl_0;		/*cr0*/
+	u32	app_ctrl_1;		/*cr1*/
+	u32	app_status_0;		/*cr2*/
+	u32	app_status_1;		/*cr3*/
+	u32	msg_status;		/*cr4*/
+	u32	msg_payload;		/*cr5*/
+	u32	int_sts;		/*cr6*/
+	u32	int_clr;		/*cr7*/
+	u32	int_mask;		/*cr8*/
+	u32	mst_bmisc;		/*cr9*/
+	u32	phy_ctrl;		/*cr10*/
+	u32	phy_status;		/*cr11*/
+	u32	cxpl_debug_info_0;	/*cr12*/
+	u32	cxpl_debug_info_1;	/*cr13*/
+	u32	ven_msg_ctrl_0;		/*cr14*/
+	u32	ven_msg_ctrl_1;		/*cr15*/
+	u32	ven_msg_data_0;		/*cr16*/
+	u32	ven_msg_data_1;		/*cr17*/
+	u32	ven_msi_0;		/*cr18*/
+	u32	ven_msi_1;		/*cr19*/
+	u32	mst_rmisc;		/*cr 20*/
+	u32	slv_awmisc;		/*cr 21*/
+	u32	slv_armisc;		/*cr 22*/
+	u32	pom0_mem_addr_start;	/*cr23*/
+	u32	pom1_mem_addr_start;	/*cr24*/
+	u32	pom_io_addr_start;	/*cr25*/
+	u32	pom_cfg0_addr_start;	/*cr26*/
+	u32	pom_cfg1_addr_start;	/*cr27*/
+	u32	in0_mem_addr_start;	/*cr28*/
+	u32	in1_mem_addr_start;	/*cr29*/
+	u32	in_io_addr_start;	/*cr30*/
+	u32	in_cfg0_addr_start;	/*cr31*/
+	u32	in_cfg1_addr_start;	/*cr32*/
+	u32	in_msg_addr_start;	/*cr33*/
+	u32	in0_mem_addr_limit;	/*cr34*/
+	u32	in1_mem_addr_limit;	/*cr35*/
+	u32	in_io_addr_limit;	/*cr36*/
+	u32	in_cfg0_addr_limit;	/*cr37*/
+	u32	in_cfg1_addr_limit;	/*cr38*/
+	u32	in_msg_addr_limit;	/*cr39*/
+	u32	mem0_addr_offset_limit;	/*cr40*/
+	u32	pim0_mem_addr_start;	/*cr41*/
+	u32	pim1_mem_addr_start;	/*cr42*/
+	u32	pim_io_addr_start;	/*cr43*/
+	u32	pim_rom_addr_start;	/*cr44*/
+};
+
+/*CR0 ID*/
+#define RX_LANE_FLIP_EN_ID	0
+#define TX_LANE_FLIP_EN_ID	1
+#define SYS_AUX_PWR_DET_ID	2
+#define APP_LTSSM_ENABLE_ID	3
+#define SYS_ATTEN_BUTTON_PRESSED_ID	4
+#define SYS_MRL_SENSOR_STATE_ID 5
+#define SYS_PWR_FAULT_DET_ID	6
+#define SYS_MRL_SENSOR_CHGED_ID 7
+#define SYS_PRE_DET_CHGED_ID	8
+#define SYS_CMD_CPLED_INT_ID	9
+#define APP_INIT_RST_0_ID	11
+#define APP_REQ_ENTR_L1_ID	12
+#define APP_READY_ENTR_L23_ID	13
+#define APP_REQ_EXIT_L1_ID	14
+#define DEVICE_TYPE_EP		(0 << 25)
+#define DEVICE_TYPE_LEP		(1 << 25)
+#define DEVICE_TYPE_RC		(4 << 25)
+#define SYS_INT_ID		29
+#define MISCTRL_EN_ID		30
+#define REG_TRANSLATION_ENABLE	31
+
+/*CR1 ID*/
+#define APPS_PM_XMT_TURNOFF_ID	2
+#define APPS_PM_XMT_PME_ID	5
+
+/*CR3 ID*/
+#define XMLH_LTSSM_STATE_ID	0
+#define XMLH_LTSSM_STATE_L0	((u32)0x11 << XMLH_LTSSM_STATE_ID)
+#define XMLH_LTSSM_STATE_MASK	((u32)0x1F << XMLH_LTSSM_STATE_ID)
+#define XMLH_LINK_UP_ID	5
+
+/*CR4 ID*/
+#define CFG_MSI_EN_ID	18
+
+/*CR6*/
+#define INTA_CTRL_INT	(1 << 7)
+#define INTB_CTRL_INT	(1 << 8)
+#define INTC_CTRL_INT	(1 << 9)
+#define INTD_CTRL_INT	(1 << 10)
+#define MSI_CTRL_INT	(1 << 26)
+
+/*CR19 ID*/
+#define VEN_MSI_REQ_ID	11
+#define VEN_MSI_FUN_NUM_ID	8
+#define VEN_MSI_TC_ID	5
+#define VEN_MSI_VECTOR_ID	0
+#define VEN_MSI_REQ_EN	((u32)0x1 << VEN_MSI_REQ_ID)
+#define VEN_MSI_FUN_NUM_MASK	((u32)0x7 << VEN_MSI_FUN_NUM_ID)
+#define VEN_MSI_TC_MASK	((u32)0x7 << VEN_MSI_TC_ID)
+#define VEN_MSI_VECTOR_MASK	((u32)0x1F << VEN_MSI_VECTOR_ID)
+#endif
+
+/*CE21-22 ID*/
+/*ID definitio of ARMISC*/
+#define AXI_OP_TYPE_ID	0
+#define AXI_OP_BCM_ID	5
+#define AXI_OP_EP_ID	6
+#define AXI_OP_TD_ID	7
+#define AXI_OP_ATTRIBUTE_ID	8
+#define AXI_OP_TC_ID	10
+#define AXI_OP_MSG_CODE_ID	13
+#define AXI_OP_DBI_ACCESS_ID	21
+#define AXI_OP_TYPE_MASK	0x1F
+#define AXI_OP_TYPE_MEM_RDRW	0
+#define AXI_OP_TYPE_MEM_RDRW_LOCKED	1
+#define AXI_OP_TYPE_IO_RDRW	2
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE0	4
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE1	5
+#define AXI_OP_TYPE_MSG_REQ	16
+#define AXI_OP_TYPE_COMPLETION	10
+#define AXI_OP_TYPE_COMPLETION_LOCKED	11
+#define AXI_OP_TYPE_DBI_ELBI_ENABLE	1
+
+/* synopsis specific PCIE configuration registers*/
+#define PCIE_MSI_ADDR_LO	0x820	/* 32 bits */
+#define PCIE_MSI_ADDR_HI	0x824	/* 32 bits */
+#define PCIE_MSI_INTR0_ENABLE	0x828	/* 32 bits */
+#define PCIE_MSI_INTR0_MASK	0x82C	/* 32 bits */
+#define PCIE_MSI_INTR0_STATUS	0x830	/* 32 bits */
+
+/*BAR MASK registers*/
+#define PCIE_BAR0_MASK_REG	0x1010
+
+static inline void pcie_init(int (*fptr)(int port))
+{
+	pcie_port_is_host = fptr;
+}
diff --git a/arch/arm/mach-spear13xx/pcie.c b/arch/arm/mach-spear13xx/pcie.c
new file mode 100644
index 0000000..955f1d2
--- /dev/null
+++ b/arch/arm/mach-spear13xx/pcie.c
@@ -0,0 +1,861 @@
+/*
+ * arch/arm/mach-spear13xx/pcie.c
+ *
+ * PCIe functions for SPEAr 13xx SoCs
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Pratyush Anand <pratyush.anand at st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/msi.h>
+#include <linux/mbus.h>
+#include <linux/sched.h>
+#include <asm/irq.h>
+#include <asm/mach/pci.h>
+#include <asm/mach/irq.h>
+#include <mach/pcie.h>
+#include <mach/irqs.h>
+#include <mach/misc_regs.h>
+
+#define NUM_PCIE_PORTS	3
+
+/* Sum of all these space can maximum be 256MB*/
+#define IN0_MEM_SIZE	(200 * 1024 * 1024 - 1)
+/* In current implementation address translation is done using IN0 only.
+ * So IN1 start address and IN0 end address has been kept same
+*/
+#define IN1_MEM_SIZE	(0 * 1024 * 1024 - 1)
+#define IN_IO_SIZE	(20 * 1024 * 1024 - 1)
+#define IN_CFG0_SIZE	(1 * 1024 * 1024 - 1)
+#define IN_CFG1_SIZE	(1 * 1024 * 1024 - 1)
+#define IN_MSG_SIZE	(1 * 1024 * 1024 - 1)
+
+#define MAX_LINK_UP_WAIT_JIFFIES	10
+
+int (*pcie_port_is_host)(int port);
+static struct pcie_port pcie_port[NUM_PCIE_PORTS];
+static u32 spr_pcie_base[NUM_PCIE_PORTS] = {
+	SPEAR13XX_PCIE0_BASE,
+	SPEAR13XX_PCIE1_BASE,
+	SPEAR13XX_PCIE2_BASE,
+};
+static u32 spr_pcie_app_base[NUM_PCIE_PORTS] = {
+	SPEAR13XX_PCIE0_APP_BASE,
+	SPEAR13XX_PCIE1_APP_BASE,
+	SPEAR13XX_PCIE2_APP_BASE,
+};
+
+/* Keeping all DDR area of 256MB accesible for inbound transaction */
+#define INBOUND_ADDR_MASK	0xFFFFFFF
+
+#ifdef CONFIG_PCI_MSI
+static DECLARE_BITMAP(msi_irq_in_use[NUM_PCIE_PORTS], SPEAR_NUM_MSI_IRQS);
+static unsigned int spear_msi_data[NUM_PCIE_PORTS];
+
+static void spear13xx_msi_init(struct pcie_port *pp);
+#endif
+
+static void spear_pcie_int_handler(unsigned int irq, struct irq_desc *desc);
+
+static void enable_dbi_access(struct pcie_app_reg *app_reg)
+{
+	/* Enable DBI access */
+	writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void disable_dbi_access(struct pcie_app_reg *app_reg)
+{
+	/* disable DBI access */
+	writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void spear_dbi_read_reg(struct pcie_port *pp, int where, int size,
+		u32 *val)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base;
+	u32 va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (u32)pp->va_dbi_base + (where & ~0x3);
+
+	*val = readl(va_address);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+static void spear_dbi_write_reg(struct pcie_port *pp, int where, int size,
+		u32 val)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base;
+	u32 va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (u32)pp->va_dbi_base + (where & ~0x3);
+
+	if (size == 4)
+		writel(val, va_address);
+	else if (size == 2)
+		writew(val, va_address + (where & 2));
+	else if (size == 1)
+		writeb(val, va_address + (where & 3));
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+static int spear13xx_pcie_link_up(void __iomem *va_app_base)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *) va_app_base;
+	unsigned long deadline = jiffies + MAX_LINK_UP_WAIT_JIFFIES;
+
+	do {
+		if (readl(&app_reg->app_status_1) &
+				((u32)1 << XMLH_LINK_UP_ID))
+			return 1;
+
+		cond_resched();
+	} while (!time_after_eq(jiffies, deadline));
+
+	return 0;
+}
+
+static void spear13xx_pcie_host_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *)pp->va_app_base;
+
+	/*setup registers for outbound translation */
+
+	writel(pp->base, &app_reg->in0_mem_addr_start);
+	writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
+			&app_reg->in0_mem_addr_limit);
+	writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
+			&app_reg->in1_mem_addr_limit);
+	writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
+	writel(app_reg->in_io_addr_start + IN_IO_SIZE,
+			&app_reg->in_io_addr_limit);
+	writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
+	writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
+			&app_reg->in_cfg0_addr_limit);
+	writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
+	writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
+			&app_reg->in_cfg1_addr_limit);
+	writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
+	writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
+			&app_reg->in_msg_addr_limit);
+
+	writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
+	writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
+
+	/*setup registers for inbound translation */
+
+	writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
+	writel(0, &app_reg->pim0_mem_addr_start);
+	writel(0, &app_reg->pim1_mem_addr_start);
+	spear_dbi_write_reg(pp, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
+	spear_dbi_write_reg(pp, PCI_BASE_ADDRESS_0, 4, 0);
+
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_rom_addr_start);
+
+	writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
+			| (1 << APP_LTSSM_ENABLE_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+}
+
+static void __init spear13xx_pcie_preinit(void)
+{
+	int i;
+	struct pcie_port *pp;
+	struct pcie_app_reg *app_reg;
+
+	for (i = 0; i < NUM_PCIE_PORTS; i++) {
+		pp = pcie_port + i;
+		app_reg = (struct pcie_app_reg *) (pp->va_app_base);
+
+		if (!(*pcie_port_is_host)(i))
+			continue;
+		snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+			"PCIe %d MEM", pp->port);
+		pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+		pp->res[0].name = pp->mem_space_name;
+		pp->res[0].start = app_reg->in0_mem_addr_start;
+		pp->res[0].end = app_reg->in0_mem_addr_limit;
+		pp->res[0].flags = IORESOURCE_MEM;
+
+		snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+			"PCIe %d I/O", pp->port);
+		pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+		pp->res[1].name = pp->io_space_name;
+		pp->res[1].start = app_reg->in_io_addr_start;
+		pp->res[1].end = app_reg->in_io_addr_limit;
+		pp->res[1].flags = IORESOURCE_IO;
+
+		if (request_resource(&iomem_resource, &pp->res[0]))
+			panic("can't allocate PCIe I/O space");
+		if (request_resource(&iomem_resource, &pp->res[1]))
+			panic("can't allocate PCIe MEM space");
+	}
+}
+
+static int __init spear13xx_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct pcie_port *pp;
+	u32 val = 0;
+
+	if (nr >= NUM_PCIE_PORTS)
+		return 0;
+
+	if (!(*pcie_port_is_host)(nr))
+		return 0;
+
+	pp = &pcie_port[nr];
+	if (!spear13xx_pcie_link_up((void __iomem *)pp->va_app_base))
+		return 0;
+	pp->root_bus_nr = sys->busnr;
+
+	/* Generic PCIe unit setup.*/
+
+	/* Enable own BME. It is necessary to enable own BME to do a
+	 * memory transaction on a downstream device
+	 */
+	spear_dbi_read_reg(pp, PCI_COMMAND, 2, &val);
+	val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER
+			| PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+	spear_dbi_write_reg(pp, PCI_COMMAND, 2, val);
+
+	/* Need to come back here*/
+
+	sys->resource[0] = &pp->res[0];
+	sys->resource[1] = &pp->res[1];
+	sys->resource[2] = NULL;
+
+	return 1;
+}
+
+static struct pcie_port *bus_to_port(int bus)
+{
+	int i;
+
+	for (i = NUM_PCIE_PORTS - 1; i >= 0; i--) {
+		int rbus = pcie_port[i].root_bus_nr;
+		if (!(*pcie_port_is_host)(i))
+			continue;
+		if (rbus != -1 && rbus <= bus)
+			break;
+	}
+
+	return i >= 0 ? pcie_port + i : NULL;
+}
+
+static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
+{
+	/*If there is no link, then there is no device*/
+	if (!spear13xx_pcie_link_up((void __iomem *)pp->va_app_base))
+		return 0;
+	/*
+	 * Don't go out when trying to access nonexisting devices
+	 * on the local bus.
+	 * we have only one slot on each root port.
+	 */
+	if (bus == pp->root_bus_nr && dev > 0)
+		return 0;
+	return 1;
+}
+
+static int spear13xx_pcie_rd_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 *val)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base;
+	u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16)
+		| (where & 0xFFFC);
+
+	writel((bus->number << 24) | (PCI_SLOT(devfn) << 19),
+			&app_reg->pom_cfg0_addr_start);
+	writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_armisc) | AXI_OP_TYPE_CONFIG_RDRW_TYPE0,
+			&app_reg->slv_armisc);
+
+	*val = readl(address);
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	writel(readl(&app_reg->slv_armisc) & ~(AXI_OP_TYPE_MASK),
+			&app_reg->slv_armisc);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+			int size, u32 *val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	ret = spear13xx_pcie_rd_conf(pp, bus, devfn, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static int spear13xx_pcie_wr_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *) pp->va_app_base;
+	u32 address = (u32)pp->va_cfg0_base | (PCI_FUNC(devfn) << 16)
+			| (where & 0xFFFC);
+
+	writel((bus->number << 24) | (PCI_SLOT(devfn) << 19),
+			&app_reg->pom_cfg0_addr_start);
+	writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK),
+			&app_reg->slv_awmisc);
+	writel(readl(&app_reg->slv_awmisc) | AXI_OP_TYPE_CONFIG_RDRW_TYPE0,
+			&app_reg->slv_awmisc);
+	if (size == 4)
+		writel(val, address);
+	else if (size == 2)
+		writew(val, address + (where & 2));
+	else if (size == 1)
+		writeb(val, address + (where & 3));
+	else
+		ret = PCIBIOS_BAD_REGISTER_NUMBER;
+	writel(readl(&app_reg->slv_awmisc) & ~(AXI_OP_TYPE_MASK),
+			&app_reg->slv_awmisc);
+	return ret;
+}
+
+static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+			int where, int size, u32 val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	ret = spear13xx_pcie_wr_conf(pp, bus, devfn, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static struct pci_ops pcie_ops = {
+	.read = pcie_rd_conf,
+	.write = pcie_wr_conf,
+};
+
+static struct pci_bus __init *
+spear13xx_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	struct pci_bus *bus;
+
+	if ((nr < NUM_PCIE_PORTS) && (*pcie_port_is_host)(nr)) {
+		bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
+	} else {
+		bus = NULL;
+		BUG();
+	}
+
+	return bus;
+}
+
+static int __init spear13xx_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct pcie_port *pp = bus_to_port(dev->bus->number);
+	int irq = (SPEAR_INTX0_BASE + pp->port * SPEAR_NUM_INTX_IRQS + pin - 1);
+
+	return irq;
+}
+
+static struct hw_pci spear13xx_pci __initdata = {
+	.nr_controllers	= NUM_PCIE_PORTS,
+	.preinit	= spear13xx_pcie_preinit,
+	.swizzle	= pci_std_swizzle,
+	.setup		= spear13xx_pcie_setup,
+	.scan		= spear13xx_pcie_scan_bus,
+	.map_irq	= spear13xx_pcie_map_irq,
+};
+
+void mask_intx_irq(unsigned int irq)
+{
+	int irq_offset = (irq - SPEAR_INTX0_BASE) % SPEAR_NUM_INTX_IRQS;
+	int port = (irq - SPEAR_INTX0_BASE) / SPEAR_NUM_INTX_IRQS;
+	struct pcie_port *pp = &pcie_port[port];
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *)pp->va_app_base;
+
+	switch (irq_offset) {
+	case 0:
+		writel(readl(&app_reg->int_mask) & ~INTA_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 1:
+		writel(readl(&app_reg->int_mask) & ~INTB_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 2:
+		writel(readl(&app_reg->int_mask) & ~INTC_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 3:
+		writel(readl(&app_reg->int_mask) & ~INTD_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	}
+}
+
+void unmask_intx_irq(unsigned int irq)
+{
+	int irq_offset = (irq - SPEAR_INTX0_BASE) % SPEAR_NUM_INTX_IRQS;
+	int port = (irq - SPEAR_INTX0_BASE) / SPEAR_NUM_INTX_IRQS;
+	struct pcie_port *pp = &pcie_port[port];
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *)pp->va_app_base;
+
+	switch (irq_offset) {
+	case 0:
+		writel(readl(&app_reg->int_mask) | INTA_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 1:
+		writel(readl(&app_reg->int_mask) | INTB_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 2:
+		writel(readl(&app_reg->int_mask) | INTC_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	case 3:
+		writel(readl(&app_reg->int_mask) | INTD_CTRL_INT,
+				&app_reg->int_mask);
+		break;
+	}
+}
+
+static struct irq_chip spear13xx_intx_chip = {
+	.name = "PCI-INTX",
+	.mask = mask_intx_irq,
+	.unmask = unmask_intx_irq,
+};
+
+static void spear13xx_int_init(struct pcie_port *pp)
+{
+	int i, irq;
+	struct pcie_app_reg *app_reg;
+
+	set_irq_chained_handler(IRQ_PCIE0 + pp->port, spear_pcie_int_handler);
+
+#ifdef CONFIG_PCI_MSI
+	spear13xx_msi_init(pp);
+#endif
+	/* Enbale INTX interrupt*/
+	app_reg = (struct pcie_app_reg *)pp->va_app_base;
+	writel(readl(&app_reg->int_mask) | INTA_CTRL_INT
+			| INTB_CTRL_INT	| INTC_CTRL_INT
+			| INTD_CTRL_INT, &app_reg->int_mask);
+
+	/* initilize INTX chip here only. MSI chip will be
+	 * initilized dynamically.*/
+	irq = (SPEAR_INTX0_BASE + pp->port * SPEAR_NUM_INTX_IRQS);
+	for (i = 0; i < SPEAR_NUM_INTX_IRQS; i++) {
+		set_irq_chip_and_handler(irq + i, &spear13xx_intx_chip,
+				handle_simple_irq);
+		set_irq_flags(irq + i, IRQF_VALID);
+	}
+}
+
+static void __init add_pcie_port(int port, u32 base, u32 app_base)
+{
+	struct pcie_port *pp = &pcie_port[port];
+	struct pcie_app_reg *app_reg;
+
+	pp->port = port;
+	pp->root_bus_nr = -1;
+	pp->base = (void __iomem *)base;
+	pp->app_base = (void __iomem *)app_base;
+	pp->va_app_base = (void __iomem *) ioremap(app_base, 0x200);
+	if (!pp->va_app_base) {
+		pr_err("error with ioremap in function %s\n", __func__);
+		return;
+	}
+	pp->va_dbi_base = (void __iomem *) ioremap(base, 0x2000);
+	if (!pp->va_dbi_base) {
+		pr_err("error with ioremap in function %s\n", __func__);
+		return;
+	}
+	spin_lock_init(&pp->conf_lock);
+	memset(pp->res, 0, sizeof(pp->res));
+	pr_info("spear13xx PCIe port %d\n", port);
+	if (spear13xx_pcie_link_up((void __iomem *)pp->va_app_base)) {
+		pr_info("link up in bios\n");
+	} else {
+		pr_info("link down in bios\n");
+		spear13xx_pcie_host_init(pp);
+		spear13xx_int_init(pp);
+		app_reg = (struct pcie_app_reg *)pp->va_app_base;
+		pp->va_cfg0_base = (void __iomem *)
+			ioremap(app_reg->in_cfg0_addr_start, IN_CFG0_SIZE);
+		if (!pp->va_cfg0_base) {
+			pr_err("error with ioremap in function %s\n", __func__);
+			return;
+		}
+
+	}
+}
+
+static int __init spear13xx_pcie_init(void)
+{
+	int port;
+	struct clk *clk;
+
+	for (port = 0; port < NUM_PCIE_PORTS; port++) {
+		/* do not enable clock if it is PCIE0. Ideally , all controller
+		 * should have been independent from others with respect to
+		 * clock. But PCIE1 and 2 depends on PCIE0.So PCIE0 clk
+		 * is provided during board init.*/
+		if (port == 1) {
+			/* Ideally CFG Clock should have been also enabled
+			 * here. But it is done currently during board
+			 * init routne*/
+			clk = clk_get_sys("pcie1", NULL);
+			if (!clk) {
+				pr_err("%s:couldn't get clk for pcie1\n",
+						__func__);
+				continue;
+			}
+			if (clk_enable(clk)) {
+				pr_err("%s:couldn't enable clk for pcie1\n",
+						__func__);
+				continue;
+			}
+		} else if (port == 2) {
+			/* Ideally CFG Clock should have been also enabled
+			 * here. But it is done currently during board
+			 * init routne*/
+			clk = clk_get_sys("pcie2", NULL);
+			if (!clk) {
+				pr_err("%s:couldn't get clk for pcie2\n",
+						__func__);
+				continue;
+			}
+			if (clk_enable(clk)) {
+				pr_err("%s:couldn't enable clk for pcie2\n",
+						__func__);
+				continue;
+			}
+		}
+
+		if ((*pcie_port_is_host)(port))
+			add_pcie_port(port, spr_pcie_base[port],
+					spr_pcie_app_base[port]);
+	}
+
+	pci_common_init(&spear13xx_pci);
+
+	return 0;
+}
+subsys_initcall(spear13xx_pcie_init);
+
+#ifdef CONFIG_PCI_MSI
+/* MSI int handler
+ */
+static void handle_msi(struct pcie_port *pp)
+{
+	unsigned long val;
+	int i, pos;
+
+	for (i = 0; i < 8; i++) {
+		spear_dbi_read_reg(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
+				(u32 *)&val);
+		if (val) {
+			pos = 0;
+			while ((pos = find_next_bit(&val, 32, pos)) != 32) {
+				generic_handle_irq(SPEAR_MSI0_INT_BASE
+					+ pp->port * SPEAR_NUM_MSI_IRQS
+					+ (i * 32) + pos);
+				pos++;
+			}
+		}
+		spear_dbi_write_reg(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val);
+	}
+}
+#else
+static void handle_msi(struct pcie_port *pp)
+{
+}
+#endif
+
+static void spear_pcie_int_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pcie_port *pp = &pcie_port[irq - IRQ_PCIE0];
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *)pp->va_app_base;
+	unsigned int status;
+
+	status = readl(&app_reg->int_sts);
+
+	desc->chip->ack(irq);
+
+	if (status & MSI_CTRL_INT) {
+		handle_msi(pp);
+		writel(MSI_CTRL_INT, &app_reg->int_clr);
+	} else if (status & INTA_CTRL_INT)
+		generic_handle_irq(SPEAR_INTX0_BASE
+				+ pp->port * SPEAR_NUM_INTX_IRQS);
+	else if (status & INTB_CTRL_INT)
+		generic_handle_irq(SPEAR_INTX0_BASE
+				+ pp->port * SPEAR_NUM_INTX_IRQS + 1);
+	else if (status & INTC_CTRL_INT)
+		generic_handle_irq(SPEAR_INTX0_BASE
+				+ pp->port * SPEAR_NUM_INTX_IRQS + 2);
+	else if (status & INTD_CTRL_INT)
+		generic_handle_irq(SPEAR_INTX0_BASE
+				+ pp->port * SPEAR_NUM_INTX_IRQS + 3);
+	else
+		writel(status, &app_reg->int_clr);
+
+	desc->chip->unmask(irq);
+}
+
+#ifdef CONFIG_PCI_MSI
+static int find_valid_pos0(int port, int nvec, int pos, int *pos0)
+{
+	int flag = 1;
+	do {
+		pos = find_next_zero_bit(msi_irq_in_use[port],
+				SPEAR_NUM_MSI_IRQS, pos);
+		/*if you have reached to the end then get out from here.*/
+		if (pos == SPEAR_NUM_MSI_IRQS)
+			return -ENOSPC;
+		/* Check if this position is at correct offset.nvec is always a
+		 * power of two. pos0 must be nvec bit alligned.
+		 */
+		if (pos % nvec)
+			pos += nvec - (pos % nvec);
+		else
+			flag = 0;
+	} while (flag);
+
+	*pos0 = pos;
+	return 0;
+}
+
+static void spear13xx_msi_nop(unsigned int irq)
+{
+	return;
+}
+
+static struct irq_chip spear13xx_msi_chip = {
+	.name = "PCI-MSI",
+	.ack = spear13xx_msi_nop,
+	.enable = unmask_msi_irq,
+	.disable = mask_msi_irq,
+	.mask = mask_msi_irq,
+	.unmask = unmask_msi_irq,
+};
+
+/*
+ * Dynamic irq allocate and deallocation
+ */
+static int get_irq(int nvec, struct msi_desc *desc, int *pos)
+{
+	int res, bit, irq, pos0, pos1, i;
+	u32 val;
+	struct pcie_port *pp = bus_to_port(desc->dev->bus->number);
+
+	pos0 = find_first_zero_bit(msi_irq_in_use[pp->port],
+			SPEAR_NUM_MSI_IRQS);
+	if (pos0 % nvec) {
+		if (find_valid_pos0(pp->port, nvec, pos0, &pos0))
+			goto no_valid_irq;
+	}
+	if (nvec > 1) {
+		pos1 = find_next_bit(msi_irq_in_use[pp->port],
+				SPEAR_NUM_MSI_IRQS, pos0);
+		/* there must be nvec number of consecutive free bits */
+		while ((pos1 - pos0) < nvec) {
+			if (find_valid_pos0(pp->port, nvec, pos1, &pos0))
+				goto no_valid_irq;
+			pos1 = find_next_bit(msi_irq_in_use[pp->port],
+					SPEAR_NUM_MSI_IRQS, pos0);
+		}
+	}
+
+	irq = (SPEAR_MSI0_INT_BASE + (pp->port * SPEAR_NUM_MSI_IRQS)) + pos0;;
+
+	if ((irq + nvec) > (SPEAR_MSI0_INT_END
+				+ (pp->port * SPEAR_NUM_MSI_IRQS)))
+		goto no_valid_irq;
+
+	i = 0;
+	while (i < nvec) {
+		set_bit(pos0 + i, msi_irq_in_use[pp->port]);
+		dynamic_irq_init(irq + i);
+		set_irq_msi(irq + i, desc);
+		set_irq_chip_and_handler(irq + i, &spear13xx_msi_chip,
+				handle_simple_irq);
+
+		/* Enable corresponding interrupt on MSI interrupt
+		 * controller.
+		 */
+		res = ((pos0 + i) / 32) * 12;
+		bit = (pos0 + i) % 32;
+		spear_dbi_read_reg(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+		val |= 1 << bit;
+		spear_dbi_write_reg(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+
+		i++;
+	}
+
+	*pos = pos0;
+	return irq;
+no_valid_irq:
+	*pos = pos0;
+	return -ENOSPC;
+}
+
+static void clean_irq(unsigned int irq)
+{
+	int res, bit, val, pos;
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct pcie_port *pp = bus_to_port(desc->msi_desc->dev->bus->number);
+
+	pos = irq - (SPEAR_MSI0_INT_BASE + (pp->port * SPEAR_NUM_MSI_IRQS));
+
+	dynamic_irq_cleanup(irq);
+
+	clear_bit(pos, msi_irq_in_use[pp->port]);
+
+	/* Disable corresponding interrupt on MSI interrupt
+	 * controller.
+	 */
+	res = (pos / 32) * 12;
+	bit = pos % 32;
+	spear_dbi_read_reg(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val &= ~(1 << bit);
+	spear_dbi_write_reg(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+
+}
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	int cvec, rvec, irq, pos;
+	struct msi_msg msg;
+	uint16_t control;
+	struct pcie_port *pp = bus_to_port(pdev->bus->number);
+
+	/*
+	 * Read the MSI config to figure out how many IRQs this device
+	 * wants.Most devices only want 1, which will give
+	 * configured_private_bits and request_private_bits equal 0.
+	 */
+	pci_read_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+			&control);
+
+	/*
+	 * If the number of private bits has been configured then use
+	 * that value instead of the requested number. This gives the
+	 * driver the chance to override the number of interrupts
+	 * before calling pci_enable_msi().
+	 */
+
+	cvec = (control & PCI_MSI_FLAGS_QSIZE) >> 4;
+
+	if (cvec == 0) {
+		/* Nothing is configured, so use the hardware requested size */
+		rvec = (control & PCI_MSI_FLAGS_QMASK) >> 1;
+	} else {
+		/*
+		 * Use the number of configured bits, assuming the
+		 * driver wanted to override the hardware request
+		 * value.
+		 */
+		rvec = cvec;
+	}
+
+	/*
+	 * The PCI 2.3 spec mandates that there are at most 32
+	 * interrupts. If this device asks for more, only give it one.
+	 */
+	if (rvec > 5)
+		rvec = 0;
+
+	irq = get_irq((1 << rvec), desc, &pos);
+
+	 if (irq < 0)
+		return irq;
+
+	 /* Update the number of IRQs the device has available to it */
+	 control &= ~PCI_MSI_FLAGS_QSIZE;
+	 control |= rvec << 4;
+	 pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
+			 control);
+	 desc->msi_attrib.multiple = rvec;
+
+	/* An EP will modify lower 8 bits(max) of msi data while
+	 * sending any msi interrupt
+	 */
+	msg.address_hi = 0x0;
+	msg.address_lo = __virt_to_phys((u32)(&spear_msi_data[pp->port]));
+	msg.data = pos;
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	clean_irq(irq);
+}
+
+static void spear13xx_msi_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = (struct pcie_app_reg *)pp->va_app_base;
+
+	spear_dbi_write_reg(pp, PCIE_MSI_ADDR_LO, 4,
+			__virt_to_phys((u32)(&spear_msi_data[pp->port])));
+	spear_dbi_write_reg(pp, PCIE_MSI_ADDR_HI, 4, 0);
+	/* Enbale MSI interrupt*/
+	writel(readl(&app_reg->int_mask) | MSI_CTRL_INT,
+			&app_reg->int_mask);
+}
+#endif
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 56a4294..d8698e0 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -18,6 +18,7 @@
 #include <asm/mach-types.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
+#include <mach/pcie.h>
 #include <plat/keyboard.h>
 #include <plat/fsmc.h>
 #include <plat/smi.h>
@@ -49,6 +50,30 @@ static struct kbd_platform_data kbd_data = {
 	.rep = 1,
 };
 
+#ifdef CONFIG_PCIEPORTBUS
+/* this function is needed for PCIE host and device driver. Same
+ * controller can not be programmed as host as well as device. So host
+ * driver must call this function and if this function returns 1 then
+ * only host should add that particular port as RC.
+ * A port to be added as device, one must also add device's information
+ * in plat_devs array defined in this file.
+ * it is the responsibility of calling function to not send port number
+ * greter than max no of controller(3)
+ */
+static int spear1300_pcie_port_is_host(int port)
+{
+	switch (port) {
+	case 0:
+		return 0;
+	case 1:
+		return 1;
+	case 2:
+		return 1;
+	}
+	return -EINVAL;
+}
+#endif
+
 static void __init spear1300_evb_init(void)
 {
 	unsigned int i;
@@ -70,6 +95,12 @@ static void __init spear1300_evb_init(void)
 	/* initialize serial nor related data in smi plat data */
 	smi_init_board_info(&spear13xx_smi_device);
 
+#ifdef CONFIG_PCIEPORTBUS
+	/* Enable PCIE0 clk */
+	enable_pcie0_clk();
+	pcie_init(&spear1300_pcie_port_is_host);
+#endif
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 55d654f..25a1964 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -318,6 +318,34 @@ struct platform_device spear13xx_smi_device = {
 	.resource = smi_resources,
 };
 
+#ifdef CONFIG_PCIEPORTBUS
+/* PCIE0 clock always needs to be enabled if any of the three PCIE port
+ * have to be used. So call this function from the board initilization
+ * file. Ideally , all controller should have been independent from
+ * others with respect to clock.
+ */
+int enable_pcie0_clk(void)
+{
+	struct clk *clk;
+	/*Enable all CLK in CFG registers here only. Idealy only PCIE0
+	 * should have been enabled. But Controler does not work
+	 * properly if PCIE1 and PCIE2's CFG CLK is enabled in stages.
+	 */
+	writel(PCIE0_CFG_VAL | PCIE1_CFG_VAL | PCIE2_CFG_VAL, PCIE_CFG);
+	clk = clk_get_sys("pcie0", NULL);
+	if (!clk) {
+		pr_err("%s:couldn't get clk for pcie0\n", __func__);
+		return -ENODEV;
+	}
+	if (clk_enable(clk)) {
+		pr_err("%s:couldn't enable clk for pcie0\n", __func__);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+#endif
+
 /* Do spear13xx familiy common initialization part here */
 void __init spear13xx_init(void)
 {
diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig
index 80f402b..b8e4988 100644
--- a/arch/arm/plat-spear/Kconfig
+++ b/arch/arm/plat-spear/Kconfig
@@ -12,6 +12,7 @@ config ARCH_SPEAR13XX
 	bool "SPEAr13XX"
 	select ARM_GIC
 	select CPU_V7
+	select ARCH_SUPPORTS_MSI
 	help
 	  Supports for ARM's SPEAR13XX family
 
-- 
1.7.2.2



From vapier at gentoo.org  Fri Oct  1 13:10:30 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 13:10:30 -0400
Subject: [PATCH] mkfs.jffs2: convert to xalloc.h helpers
Message-ID: <1285953030-19539-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 mkfs.jffs2.c |   13 +++----------
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/mkfs.jffs2.c b/mkfs.jffs2.c
index 85a8564..256eec4 100644
--- a/mkfs.jffs2.c
+++ b/mkfs.jffs2.c
@@ -381,7 +381,7 @@ static struct filesystem_entry *recursive_add_host_directory(
 #define GETCWD_SIZE 0
 #else
 #define SCANF_PREFIX "511"
-#define SCANF_STRING(s) (s = malloc(512))
+#define SCANF_STRING(s) (s = xmalloc(512))
 #define GETCWD_SIZE -1
 inline int snprintf(char *str, size_t n, const char *fmt, ...)
 {
@@ -1540,14 +1540,7 @@ void process_buffer(int inp_size) {
 void parse_image(){
 	int ret;
 
-	file_buffer = malloc(erase_block_size);
-
-	if (!file_buffer) {
-		perror("out of memory");
-		close (in_fd);
-		close (out_fd);
-		exit(1);
-	}
+	file_buffer = xmalloc(erase_block_size);
 
 	while ((ret = load_next_block())) {
 		process_buffer(ret);
@@ -1721,7 +1714,7 @@ int main(int argc, char **argv)
 					  jffs2_compression_check_set(1);
 					  break;
 			case 'y':
-					  compr_name = malloc(strlen(optarg));
+					  compr_name = xmalloc(strlen(optarg));
 					  sscanf(optarg,"%d:%s",&compr_prior,compr_name);
 					  if ((compr_prior>=0)&&(compr_name)) {
 						  if (jffs2_set_compressor_priority(compr_name, compr_prior))
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 13:11:27 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 13:11:27 -0400
Subject: [PATCH 1/2] sumtool: convert to common.h helpers
Message-ID: <1285953088-19593-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 sumtool.c |  237 ++++++++++++++++++++----------------------------------------
 1 files changed, 79 insertions(+), 158 deletions(-)

diff --git a/sumtool.c b/sumtool.c
index d0e2a7b..51e4173 100644
--- a/sumtool.c
+++ b/sumtool.c
@@ -48,6 +48,7 @@
 #include <getopt.h>
 #include <crc32.h>
 #include "summary.h"
+#include "common.h"
 
 #define PAD(x) (((x)+3)&~3)
 
@@ -119,48 +120,6 @@ static unsigned char ffbuf[16] = {
 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 };
 
-static void verror_msg(const char *s, va_list p)
-{
-	fflush(stdout);
-	fprintf(stderr, "%s: ", PROGRAM_NAME);
-	vfprintf(stderr, s, p);
-}
-
-static void error_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	verror_msg(s, p);
-	va_end(p);
-	putc('\n', stderr);
-	exit(EXIT_FAILURE);
-}
-
-static void vperror_msg(const char *s, va_list p)
-{
-	int err = errno;
-
-	if (s == 0)
-		s = "";
-	verror_msg(s, p);
-	if (*s)
-		s = ": ";
-	fprintf(stderr, "%s%s\n", s, strerror(err));
-}
-
-static void perror_msg_and_die(const char *s, ...)
-{
-	va_list p;
-
-	va_start(p, s);
-	vperror_msg(s, p);
-	va_end(p);
-	exit(EXIT_FAILURE);
-}
-
-
-
 static void full_write(void *target_buff, const void *buf, int len);
 
 void setup_cleanmarker()
@@ -179,18 +138,18 @@ void process_options (int argc, char **argv)
 		switch (opt) {
 			case 'o':
 				if (out_fd != -1)
-					error_msg_and_die("output filename specified more than once");
+					errmsg_die("output filename specified more than once");
 				out_fd = open(optarg, O_CREAT | O_TRUNC | O_RDWR, 0644);
 				if (out_fd == -1)
-					perror_msg_and_die("open output file");
+					sys_errmsg_die("open output file");
 				break;
 
 			case 'i':
 				if (in_fd != -1)
-					error_msg_and_die("input filename specified more than once");
+					errmsg_die("input filename specified more than once");
 				in_fd = open(optarg, O_RDONLY);
 				if (in_fd == -1)
-					perror_msg_and_die("open input file");
+					sys_errmsg_die("open input file");
 				break;
 			case 'b':
 				target_endian = __BIG_ENDIAN;
@@ -200,13 +159,13 @@ void process_options (int argc, char **argv)
 				break;
 			case 'h':
 			case '?':
-				error_msg_and_die(helptext);
+				errmsg_die("%s", helptext);
 			case 'v':
 				verbose = 1;
 				break;
 
 			case 'V':
-				error_msg_and_die("revision %.*s\n",
+				errmsg_die("revision %.*s\n",
 						(int) strlen(revtext) - 13, revtext + 11);
 
 			case 'e': {
@@ -214,7 +173,7 @@ void process_options (int argc, char **argv)
 						  unsigned units = 0;
 						  erase_block_size = strtol(optarg, &next, 0);
 						  if (!erase_block_size)
-							  error_msg_and_die("Unrecognisable erase size\n");
+							  errmsg_die("Unrecognisable erase size\n");
 
 						  if (*next) {
 							  if (!strcmp(next, "KiB")) {
@@ -222,7 +181,7 @@ void process_options (int argc, char **argv)
 							  } else if (!strcmp(next, "MiB")) {
 								  units = 1024 * 1024;
 							  } else {
-								  error_msg_and_die("Unknown units in erasesize\n");
+								  errmsg_die("Unknown units in erasesize\n");
 							  }
 						  } else {
 							  if (erase_block_size < 0x1000)
@@ -234,8 +193,8 @@ void process_options (int argc, char **argv)
 
 						  /* If it's less than 8KiB, they're not allowed */
 						  if (erase_block_size < 0x2000) {
-							  fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
-									  erase_block_size);
+							  warnmsg("Erase size 0x%x too small. Increasing to 8KiB minimum\n",
+									erase_block_size);
 							  erase_block_size = 0x2000;
 						  }
 						  break;
@@ -248,10 +207,10 @@ void process_options (int argc, char **argv)
 					  cleanmarker_size = strtol(optarg, NULL, 0);
 
 					  if (cleanmarker_size < sizeof(cleanmarker)) {
-						  error_msg_and_die("cleanmarker size must be >= 12");
+						  errmsg_die("cleanmarker size must be >= 12");
 					  }
 					  if (cleanmarker_size >= erase_block_size) {
-						  error_msg_and_die("cleanmarker size must be < eraseblock size");
+						  errmsg_die("cleanmarker size must be < eraseblock size");
 					  }
 
 					  use_input_cleanmarker_size = 0;
@@ -269,41 +228,19 @@ void process_options (int argc, char **argv)
 
 void init_buffers()
 {
-	data_buffer = malloc(erase_block_size);
-
-	if (!data_buffer) {
-		perror("out of memory");
-		close (in_fd);
-		close (out_fd);
-		exit(1);
-	}
-
-	file_buffer = malloc(erase_block_size);
-
-	if (!file_buffer) {
-		perror("out of memory");
-		close (in_fd);
-		close (out_fd);
-		exit(1);
-	}
+	data_buffer = xmalloc(erase_block_size);
+	file_buffer = xmalloc(erase_block_size);
 }
 
 void init_sumlist()
 {
-	sum_collected = (struct jffs2_summary *) malloc (sizeof(struct jffs2_summary));
-
-	if (!sum_collected)
-		error_msg_and_die("Can't allocate memory for jffs2_summary!\n");
-
-	memset(sum_collected, 0, sizeof(struct jffs2_summary));
+	sum_collected = xzalloc(sizeof(*sum_collected));
 }
 
 void clean_buffers()
 {
-	if (data_buffer)
-		free(data_buffer);
-	if (file_buffer)
-		free(file_buffer);
+	free(data_buffer);
+	free(file_buffer);
 }
 
 void clean_sumlist()
@@ -320,7 +257,7 @@ void clean_sumlist()
 		}
 
 		if (sum_collected->sum_num != 0)
-			printf("Ooops, something wrong happened! sum_num != 0, but sum_list = null ???");
+			warnmsg("Ooops, something wrong happened! sum_num != 0, but sum_list = null ???");
 
 		free(sum_collected);
 	}
@@ -332,8 +269,7 @@ int load_next_block()
 	ret = read(in_fd, file_buffer, erase_block_size);
 	file_ofs = 0;
 
-	if (verbose)
-		printf("Load next block : %d bytes read\n",ret);
+	bareverbose(verbose, "Load next block : %d bytes read\n", ret);
 
 	return ret;
 }
@@ -350,10 +286,10 @@ void write_buff_to_file()
 		ret = write(out_fd, buf, len);
 
 		if (ret < 0)
-			perror_msg_and_die("write");
+			sys_errmsg_die("write");
 
 		if (ret == 0)
-			perror_msg_and_die("write returned zero");
+			sys_errmsg_die("write returned zero");
 
 		len -= ret;
 		buf += ret;
@@ -383,10 +319,7 @@ void dump_sum_records()
 	infosize += padsize; datasize += padsize;
 	offset = cpu_to_je32(data_ofs);
 
-	tpage = (jint32_t *) malloc(datasize);
-
-	if(!tpage)
-		error_msg_and_die("Can't allocate memory to dump summary information!\n");
+	tpage = xmalloc(datasize);
 
 	memset(tpage, 0xff, datasize);
 	memset(&isum, 0, sizeof(isum));
@@ -465,7 +398,7 @@ void dump_sum_records()
 									  }
 
 			default : {
-						  printf("Unknown node type!\n");
+						  warnmsg("Unknown node type!\n");
 					  }
 		}
 
@@ -610,17 +543,14 @@ int add_sum_mem(union jffs2_sum_mem *item)
 			break;
 
 		default:
-			error_msg_and_die("__jffs2_add_sum_mem(): UNKNOWN node type %d\n", je16_to_cpu(item->u.nodetype));
+			errmsg_die("__jffs2_add_sum_mem(): UNKNOWN node type %d\n", je16_to_cpu(item->u.nodetype));
 	}
 	return 0;
 }
 
 void add_sum_inode_mem(union jffs2_node_union *node)
 {
-	struct jffs2_sum_inode_mem *temp = (struct jffs2_sum_inode_mem *) malloc(sizeof(struct jffs2_sum_inode_mem));
-
-	if (!temp)
-		error_msg_and_die("Can't allocate memory for summary information!\n");
+	struct jffs2_sum_inode_mem *temp = xmalloc(sizeof(*temp));
 
 	temp->nodetype = node->i.nodetype;
 	temp->inode = node->i.ino;
@@ -634,11 +564,7 @@ void add_sum_inode_mem(union jffs2_node_union *node)
 
 void add_sum_dirent_mem(union jffs2_node_union *node)
 {
-	struct jffs2_sum_dirent_mem *temp = (struct jffs2_sum_dirent_mem *)
-		malloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize);
-
-	if (!temp)
-		error_msg_and_die("Can't allocate memory for summary information!\n");
+	struct jffs2_sum_dirent_mem *temp = xmalloc(sizeof(*temp) + node->d.nsize);
 
 	temp->nodetype = node->d.nodetype;
 	temp->totlen = node->d.totlen;
@@ -656,10 +582,7 @@ void add_sum_dirent_mem(union jffs2_node_union *node)
 
 void add_sum_xattr_mem(union jffs2_node_union *node)
 {
-	struct jffs2_sum_xattr_mem *temp = (struct jffs2_sum_xattr_mem *)
-		malloc(sizeof(struct jffs2_sum_xattr_mem));
-	if (!temp)
-		error_msg_and_die("Can't allocate memory for summary information!\n");
+	struct jffs2_sum_xattr_mem *temp = xmalloc(sizeof(*temp));
 
 	temp->nodetype = node->x.nodetype;
 	temp->xid = node->x.xid;
@@ -673,10 +596,7 @@ void add_sum_xattr_mem(union jffs2_node_union *node)
 
 void add_sum_xref_mem(union jffs2_node_union *node)
 {
-	struct jffs2_sum_xref_mem *temp = (struct jffs2_sum_xref_mem *)
-		malloc(sizeof(struct jffs2_sum_xref_mem));
-	if (!temp)
-		error_msg_and_die("Can't allocate memory for summary information!\n");
+	struct jffs2_sum_xref_mem *temp = xmalloc(sizeof(*temp));
 
 	temp->nodetype = node->r.nodetype;
 	temp->offset = cpu_to_je32(data_ofs);
@@ -740,7 +660,8 @@ void create_summed_image(int inp_size)
 
 		if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) {
 			if (!bitchbitmask++)
-				printf ("Wrong bitmask  at  0x%08zx, 0x%04x\n", p - file_buffer, je16_to_cpu (node->u.magic));
+				warnmsg("Wrong bitmask  at  0x%08zx, 0x%04x\n",
+					p - file_buffer, je16_to_cpu (node->u.magic));
 			p += 4;
 			continue;
 		}
@@ -759,30 +680,33 @@ void create_summed_image(int inp_size)
 
 		crc = mtd_crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4);
 		if (crc != je32_to_cpu (node->u.hdr_crc)) {
-			printf ("Wrong hdr_crc  at  0x%08zx, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->u.hdr_crc), crc);
+			warnmsg("Wrong hdr_crc  at  0x%08zx, 0x%08x instead of 0x%08x\n",
+				p - file_buffer, je32_to_cpu (node->u.hdr_crc), crc);
 			p += 4;
 			continue;
 		}
 
 		switch(je16_to_cpu(node->u.nodetype)) {
 			case JFFS2_NODETYPE_INODE:
-				if (verbose)
-					printf ("%8s Inode      node at 0x%08zx, totlen 0x%08x, #ino  %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino),
-							je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize),
-							je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset));
+				bareverbose(verbose,
+					"%8s Inode      node at 0x%08zx, totlen 0x%08x, #ino  %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino),
+					je32_to_cpu (node->i.version), je32_to_cpu (node->i.isize),
+					je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset));
 
 				crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_inode) - 8);
 				if (crc != je32_to_cpu (node->i.node_crc)) {
-					printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->i.node_crc), crc);
+					warnmsg("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n",
+						p - file_buffer, je32_to_cpu (node->i.node_crc), crc);
 					p += PAD(je32_to_cpu (node->i.totlen));
 					continue;
 				}
 
 				crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_inode), je32_to_cpu(node->i.csize));
 				if (crc != je32_to_cpu(node->i.data_crc)) {
-					printf ("Wrong data_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->i.data_crc), crc);
+					warnmsg("Wrong data_crc at  0x%08zx, 0x%08x instead of 0x%08x\n",
+						p - file_buffer, je32_to_cpu (node->i.data_crc), crc);
 					p += PAD(je32_to_cpu (node->i.totlen));
 					continue;
 				}
@@ -796,23 +720,25 @@ void create_summed_image(int inp_size)
 				memcpy (name, node->d.name, node->d.nsize);
 				name [node->d.nsize] = 0x0;
 
-				if (verbose)
-					printf ("%8s Dirent     node at 0x%08zx, totlen 0x%08x, #pino %5d, version %5d, #ino  %8d, nsize %8d, name %s\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino),
-							je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino),
-							node->d.nsize, name);
+				bareverbose(verbose,
+					"%8s Dirent     node at 0x%08zx, totlen 0x%08x, #pino %5d, version %5d, #ino  %8d, nsize %8d, name %s\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino),
+					je32_to_cpu (node->d.version), je32_to_cpu (node->d.ino),
+					node->d.nsize, name);
 
 				crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_dirent) - 8);
 				if (crc != je32_to_cpu (node->d.node_crc)) {
-					printf ("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->d.node_crc), crc);
+					warnmsg("Wrong node_crc at  0x%08zx, 0x%08x instead of 0x%08x\n",
+						p - file_buffer, je32_to_cpu (node->d.node_crc), crc);
 					p += PAD(je32_to_cpu (node->d.totlen));
 					continue;
 				}
 
 				crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize);
 				if (crc != je32_to_cpu(node->d.name_crc)) {
-					printf ("Wrong name_crc at  0x%08zx, 0x%08x instead of 0x%08x\n", p - file_buffer, je32_to_cpu (node->d.name_crc), crc);
+					warnmsg("Wrong name_crc at  0x%08zx, 0x%08x instead of 0x%08x\n",
+						p - file_buffer, je32_to_cpu (node->d.name_crc), crc);
 					p += PAD(je32_to_cpu (node->d.totlen));
 					continue;
 				}
@@ -825,15 +751,14 @@ void create_summed_image(int inp_size)
 			case JFFS2_NODETYPE_XATTR:
 				if (je32_to_cpu(node->x.node_crc) == 0xffffffff)
 					obsolete = 1;
-				if (verbose)
-					printf("%8s Xdatum     node at 0x%08zx, totlen 0x%08x, "
-							"#xid  %5u, version %5u\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->x.totlen),
-							je32_to_cpu(node->x.xid), je32_to_cpu(node->x.version));
+				bareverbose(verbose,
+					"%8s Xdatum     node at 0x%08zx, totlen 0x%08x, #xid  %5u, version %5u\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->x.totlen),
+					je32_to_cpu(node->x.xid), je32_to_cpu(node->x.version));
 				crc = mtd_crc32(0, node, sizeof (struct jffs2_raw_xattr) - 4);
 				if (crc != je32_to_cpu(node->x.node_crc)) {
-					printf("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
+					warnmsg("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
 							p - file_buffer, je32_to_cpu(node->x.node_crc), crc);
 					p += PAD(je32_to_cpu (node->x.totlen));
 					continue;
@@ -841,7 +766,7 @@ void create_summed_image(int inp_size)
 				length = node->x.name_len + 1 + je16_to_cpu(node->x.value_len);
 				crc = mtd_crc32(0, node->x.data, length);
 				if (crc != je32_to_cpu(node->x.data_crc)) {
-					printf("Wrong data_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
+					warnmsg("Wrong data_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
 							p - file_buffer, je32_to_cpu(node->x.data_crc), crc);
 					p += PAD(je32_to_cpu (node->x.totlen));
 					continue;
@@ -854,15 +779,14 @@ void create_summed_image(int inp_size)
 			case JFFS2_NODETYPE_XREF:
 				if (je32_to_cpu(node->r.node_crc) == 0xffffffff)
 					obsolete = 1;
-				if (verbose)
-					printf("%8s Xref       node at 0x%08zx, totlen 0x%08x, "
-							"#ino  %5u, xid     %5u\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu(node->r.totlen),
-							je32_to_cpu(node->r.ino), je32_to_cpu(node->r.xid));
+				bareverbose(verbose,
+					"%8s Xref       node at 0x%08zx, totlen 0x%08x, #ino  %5u, xid     %5u\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu(node->r.totlen),
+					je32_to_cpu(node->r.ino), je32_to_cpu(node->r.xid));
 				crc = mtd_crc32(0, node, sizeof (struct jffs2_raw_xref) - 4);
 				if (crc != je32_to_cpu(node->r.node_crc)) {
-					printf("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
+					warnmsg("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n",
 							p - file_buffer, je32_to_cpu(node->r.node_crc), crc);
 					p += PAD(je32_to_cpu (node->r.totlen));
 					continue;
@@ -873,11 +797,10 @@ void create_summed_image(int inp_size)
 				break;
 
 			case JFFS2_NODETYPE_CLEANMARKER:
-				if (verbose) {
-					printf ("%8s Cleanmarker     at 0x%08zx, totlen 0x%08x\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->u.totlen));
-				}
+				bareverbose(verbose,
+					"%8s Cleanmarker     at 0x%08zx, totlen 0x%08x\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->u.totlen));
 
 				if (!found_cleanmarkers) {
 					found_cleanmarkers = 1;
@@ -892,11 +815,10 @@ void create_summed_image(int inp_size)
 				break;
 
 			case JFFS2_NODETYPE_PADDING:
-				if (verbose) {
-					printf ("%8s Padding    node at 0x%08zx, totlen 0x%08x\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->u.totlen));
-				}
+				bareverbose(verbose,
+					"%8s Padding    node at 0x%08zx, totlen 0x%08x\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->u.totlen));
 				p += PAD(je32_to_cpu (node->u.totlen));
 				break;
 
@@ -905,11 +827,10 @@ void create_summed_image(int inp_size)
 				break;
 
 			default:
-				if (verbose) {
-					printf ("%8s Unknown    node at 0x%08zx, totlen 0x%08x\n",
-							obsolete ? "Obsolete" : "",
-							p - file_buffer, je32_to_cpu (node->u.totlen));
-				}
+				bareverbose(verbose,
+					"%8s Unknown    node at 0x%08zx, totlen 0x%08x\n",
+					obsolete ? "Obsolete" : "",
+					p - file_buffer, je32_to_cpu (node->u.totlen));
 
 				p += PAD(je32_to_cpu (node->u.totlen));
 		}
@@ -928,7 +849,7 @@ int main(int argc, char **argv)
 		if(out_fd != -1)
 			close(out_fd);
 		fprintf(stderr, "%s", helptext);
-		error_msg_and_die("You must specify input and output files!\n");
+		errmsg_die("You must specify input and output files!\n");
 	}
 
 	init_buffers();
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 13:11:28 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 13:11:28 -0400
Subject: [PATCH 2/2] sumtool/libfec: convert "()" to "(void)" in func defs
In-Reply-To: <1285953088-19593-1-git-send-email-vapier@gentoo.org>
References: <1285953088-19593-1-git-send-email-vapier@gentoo.org>
Message-ID: <1285953088-19593-2-git-send-email-vapier@gentoo.org>

Since these functions take no parameters, declare them as such.  The
subtle difference here is that gcc allows (without warning) people to
accidentally call funcs declared with "()" with arguments.  Using void
makes sure that gcc will reject such typos at compile time.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 lib/libfec.c |    6 +++---
 sumtool.c    |   20 ++++++++++----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/lib/libfec.c b/lib/libfec.c
index b19ed6e..c89a180 100644
--- a/lib/libfec.c
+++ b/lib/libfec.c
@@ -185,7 +185,7 @@ static gf gf_mul_table[GF_SIZE + 1][GF_SIZE + 1];
 #define GF_ADDMULC(dst, x) dst ^= __gf_mulc_[x]
 
 static void
-init_mul_table()
+init_mul_table(void)
 {
     int i, j;
     for (i=0; i< GF_SIZE+1; i++)
@@ -603,7 +603,7 @@ invert_vdm(gf *src, int k)
 
 static int fec_initialized = 0 ;
 static void
-init_fec()
+init_fec(void)
 {
     TICK(ticks[0]);
     generate_gf();
@@ -882,7 +882,7 @@ fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz)
 
 #if (TEST || DEBUG)
 void
-test_gf()
+test_gf(void)
 {
     int i ;
     /*
diff --git a/sumtool.c b/sumtool.c
index 51e4173..886b545 100644
--- a/sumtool.c
+++ b/sumtool.c
@@ -122,7 +122,7 @@ static unsigned char ffbuf[16] = {
 
 static void full_write(void *target_buff, const void *buf, int len);
 
-void setup_cleanmarker()
+void setup_cleanmarker(void)
 {
 	cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
@@ -226,24 +226,24 @@ void process_options (int argc, char **argv)
 }
 
 
-void init_buffers()
+void init_buffers(void)
 {
 	data_buffer = xmalloc(erase_block_size);
 	file_buffer = xmalloc(erase_block_size);
 }
 
-void init_sumlist()
+void init_sumlist(void)
 {
 	sum_collected = xzalloc(sizeof(*sum_collected));
 }
 
-void clean_buffers()
+void clean_buffers(void)
 {
 	free(data_buffer);
 	free(file_buffer);
 }
 
-void clean_sumlist()
+void clean_sumlist(void)
 {
 	union jffs2_sum_mem *temp;
 
@@ -263,7 +263,7 @@ void clean_sumlist()
 	}
 }
 
-int load_next_block()
+int load_next_block(void)
 {
 	int ret;
 	ret = read(in_fd, file_buffer, erase_block_size);
@@ -274,7 +274,7 @@ int load_next_block()
 	return ret;
 }
 
-void write_buff_to_file()
+void write_buff_to_file(void)
 {
 	int ret;
 	int len = data_ofs;
@@ -298,7 +298,7 @@ void write_buff_to_file()
 	data_ofs = 0;
 }
 
-void dump_sum_records()
+void dump_sum_records(void)
 {
 
 	struct jffs2_raw_summary isum;
@@ -447,7 +447,7 @@ static void pad(int req)
 	}
 }
 
-static inline void padword()
+static inline void padword(void)
 {
 	if (data_ofs % 4)
 		full_write(data_buffer + data_ofs, ffbuf, 4 - (data_ofs % 4));
@@ -474,7 +474,7 @@ static inline void pad_block_if_less_than(int req,int plus)
 	}
 }
 
-void flush_buffers()
+void flush_buffers(void)
 {
 
 	if ((add_cleanmarkers == 1) && (found_cleanmarkers == 1)) { /* CLEANMARKER */
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 13:13:10 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 13:13:10 -0400
Subject: [PATCH] libmtd: make malloc failures fatal
Message-ID: <1285953190-19669-1-git-send-email-vapier@gentoo.org>

This converts libmtd to the common xalloc helpers and in doing so, makes
memory allocation failures fatal rather than returning an error to the
caller.  I think this is acceptable behavior.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 lib/libmtd.c        |   26 ++++++--------------------
 lib/libmtd_legacy.c |    8 +-------
 2 files changed, 7 insertions(+), 27 deletions(-)

diff --git a/lib/libmtd.c b/lib/libmtd.c
index 83ae812..e0c0934 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -48,14 +48,10 @@
 static char *mkpath(const char *path, const char *name)
 {
 	char *n;
-	int len1 = strlen(path);
-	int len2 = strlen(name);
+	size_t len1 = strlen(path);
+	size_t len2 = strlen(name);
 
-	n = malloc(len1 + len2 + 2);
-	if (!n) {
-		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
-		return NULL;
-	}
+	n = xmalloc(len1 + len2 + 2);
 
 	memcpy(n, path, len1);
 	if (n[len1 - 1] != '/')
@@ -556,9 +552,7 @@ libmtd_t libmtd_open(void)
 {
 	struct libmtd *lib;
 
-	lib = calloc(1, sizeof(struct libmtd));
-	if (!lib)
-		return NULL;
+	lib = xzalloc(sizeof(*lib));
 
 	lib->offs64_ioctls = OFFS64_IOCTLS_UNKNOWN;
 
@@ -917,11 +911,7 @@ int mtd_torture(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 	normsg("run torture test for PEB %d", eb);
 	patt_count = ARRAY_SIZE(patterns);
 
-	buf = malloc(mtd->eb_size);
-	if (!buf) {
-		errmsg("cannot allocate %d bytes of memory", mtd->eb_size);
-		return -1;
-	}
+	buf = xmalloc(mtd->eb_size);
 
 	for (i = 0; i < patt_count; i++) {
 		err = mtd_erase(desc, mtd, fd, eb);
@@ -1240,11 +1230,7 @@ int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
 		goto out_close;
 	}
 
-	buf = malloc(mtd->eb_size);
-	if (!buf) {
-		sys_errmsg("cannot allocate %d bytes of memory", mtd->eb_size);
-		goto out_close;
-	}
+	buf = xmalloc(mtd->eb_size);
 
 	while (written < len) {
 		int rd = 0;
diff --git a/lib/libmtd_legacy.c b/lib/libmtd_legacy.c
index 3d129c1..7488275 100644
--- a/lib/libmtd_legacy.c
+++ b/lib/libmtd_legacy.c
@@ -75,12 +75,7 @@ static int proc_parse_start(struct proc_parse_info *pi)
 	if (fd == -1)
 		return -1;
 
-	pi->buf = malloc(PROC_MTD_MAX_LEN);
-	if (!pi->buf) {
-		sys_errmsg("cannot allocate %d bytes of memory",
-			   PROC_MTD_MAX_LEN);
-		goto out_close;
-	}
+	pi->buf = xmalloc(PROC_MTD_MAX_LEN);
 
 	ret = read(fd, pi->buf, PROC_MTD_MAX_LEN);
 	if (ret == -1) {
@@ -103,7 +98,6 @@ static int proc_parse_start(struct proc_parse_info *pi)
 
 out_free:
 	free(pi->buf);
-out_close:
 	close(fd);
 	return -1;
 }
-- 
1.7.3.1



From vapier at gentoo.org  Fri Oct  1 13:14:06 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri,  1 Oct 2010 13:14:06 -0400
Subject: [PATCH] jffs2reader: convert to common.h helpers
Message-ID: <1285953246-19729-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 jffs2reader.c |   70 +++++++++++++++++---------------------------------------
 1 files changed, 21 insertions(+), 49 deletions(-)

diff --git a/jffs2reader.c b/jffs2reader.c
index 0cdff19..8326971 100644
--- a/jffs2reader.c
+++ b/jffs2reader.c
@@ -136,10 +136,8 @@ void putblock(char *b, size_t bsize, size_t * rsize,
 {
 	uLongf dlen = n->dsize;
 
-	if (n->isize > bsize || (n->offset + dlen) > bsize) {
-		fprintf(stderr, "File does not fit into buffer!\n");
-		exit(EXIT_FAILURE);
-	}
+	if (n->isize > bsize || (n->offset + dlen) > bsize)
+		errmsg("File does not fit into buffer!");
 
 	if (*rsize < n->isize)
 		bzero(b + *rsize, n->isize - *rsize);
@@ -163,8 +161,7 @@ void putblock(char *b, size_t bsize, size_t * rsize,
 			/* [DYN]RUBIN support required! */
 
 		default:
-			fprintf(stderr, "Unsupported compression method!\n");
-			exit(EXIT_FAILURE);
+			errmsg("Unsupported compression method!");
 	}
 
 	*rsize = n->isize;
@@ -188,7 +185,7 @@ struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n)
 
 	if (n->ino) {
 		if (dd == NULL) {
-			d = malloc(sizeof(struct dir));
+			d = xmalloc(sizeof(struct dir));
 			d->type = n->type;
 			memcpy(d->name, n->name, n->nsize);
 			d->nsize = n->nsize;
@@ -208,7 +205,7 @@ struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n)
 			}
 
 			if (dd->next == NULL) {
-				dd->next = malloc(sizeof(struct dir));
+				dd->next = xmalloc(sizeof(struct dir));
 				dd->next->type = n->type;
 				memcpy(dd->next->name, n->name, n->nsize);
 				dd->next->nsize = n->nsize;
@@ -344,7 +341,7 @@ void printdir(char *o, size_t size, struct dir *d, char *path, int recurse)
 		}
 		ri = find_raw_inode(o, size, d->ino);
 		if (!ri) {
-			fprintf(stderr, "bug: raw_inode missing!\n");
+			warnmsg("bug: raw_inode missing!");
 			d = d->next;
 			continue;
 		}
@@ -379,11 +376,7 @@ void printdir(char *o, size_t size, struct dir *d, char *path, int recurse)
 
 		if (d->type == DT_DIR && recurse) {
 			char *tmp;
-			tmp = malloc(BUFSIZ);
-			if (!tmp) {
-				fprintf(stderr, "memory exhausted\n");
-				exit(EXIT_FAILURE);
-			}
+			tmp = xmalloc(BUFSIZ);
 			sprintf(tmp, "%s/%s", path, d->name);
 			lsdir(o, size, tmp, recurse);		/* Go recursive */
 			free(tmp);
@@ -817,11 +810,8 @@ void lsdir(char *o, size_t size, char *path, int recurse)
 	dd = resolvepath(o, size, 1, path, &ino);
 
 	if (ino == 0 ||
-			(dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR)) {
-		fprintf(stderr, "%s: %s: No such file or directory\n",
-				PROGRAM_NAME, path);
-		exit(EXIT_FAILURE);
-	}
+			(dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR))
+		errmsg_dir("%s: No such file or directory", path);
 
 	d = collectdir(o, size, ino, d);
 	printdir(o, size, d, path, recurse);
@@ -848,15 +838,11 @@ void catfile(char *o, size_t size, char *path, char *b, size_t bsize,
 
 	dd = resolvepath(o, size, 1, path, &ino);
 
-	if (ino == 0) {
-		fprintf(stderr, "%s: No such file or directory\n", path);
-		exit(EXIT_FAILURE);
-	}
+	if (ino == 0)
+		errmsg_die("%s: No such file or directory", path);
 
-	if (dd == NULL || dd->type != DT_REG) {
-		fprintf(stderr, "%s: Not a regular file\n", path);
-		exit(EXIT_FAILURE);
-	}
+	if (dd == NULL || dd->type != DT_REG)
+		errmsg_die("%s: Not a regular file", path);
 
 	ri = find_raw_inode(o, size, ino);
 	putblock(b, bsize, rsize, ri);
@@ -896,36 +882,22 @@ int main(int argc, char **argv)
 	}
 
 	fd = open(argv[optind], O_RDONLY);
-	if (fd == -1) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(2);
-	}
+	if (fd == -1)
+		sys_errmsg_die("%s", argv[optind]);
 
-	if (fstat(fd, &st)) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(3);
-	}
+	if (fstat(fd, &st))
+		sys_errmsg_die("%s", argv[optind]);
 
-	buf = malloc((size_t) st.st_size);
-	if (buf == NULL) {
-		fprintf(stderr, "%s: memory exhausted\n", argv[optind]);
-		exit(4);
-	}
+	buf = xmalloc((size_t) st.st_size);
 
-	if (read(fd, buf, st.st_size) != (ssize_t) st.st_size) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(5);
-	}
+	if (read(fd, buf, st.st_size) != (ssize_t) st.st_size)
+		sys_errmsg_die("%s", argv[optind]);
 
 	if (dir)
 		lsdir(buf, st.st_size, dir, recurse);
 
 	if (file) {
-		scratch = malloc(SCRATCH_SIZE);
-		if (scratch == NULL) {
-			fprintf(stderr, "%s: memory exhausted\n", argv[optind]);
-			exit(6);
-		}
+		scratch = xmalloc(SCRATCH_SIZE);
 
 		catfile(buf, st.st_size, file, scratch, SCRATCH_SIZE, &ssize);
 		free(scratch);
-- 
1.7.3.1



From viresh.kumar at st.com  Fri Oct  1 07:56:28 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:28 +0530
Subject: [PATCH V2 68/69] ST SPEAr: Adding information in Documentation/ and
	MAINTAINERS
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <ffb4a467d09710964cb451eb1ccefc597985fbef.1285933332.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 Documentation/arm/SPEAr/overview.txt |   34 +++++++++++++++++++++++-----------
 MAINTAINERS                          |    6 ++++++
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/Documentation/arm/SPEAr/overview.txt b/Documentation/arm/SPEAr/overview.txt
index 253a35c..4e510061 100644
--- a/Documentation/arm/SPEAr/overview.txt
+++ b/Documentation/arm/SPEAr/overview.txt
@@ -9,8 +9,9 @@ Introduction
 
   The ST Microelectronics SPEAr range of ARM9/CortexA9 System-on-Chip CPUs are
   supported by the 'spear' platform of ARM Linux. Currently SPEAr300,
-  SPEAr310, SPEAr320 and SPEAr600 SOCs are supported. Support for the SPEAr13XX
-  series is in progress.
+  SPEAr310, SPEAr320, SPEAr600, SPEAr1300 and SPEAr1310 SOCs are supported.
+  SPEAr3XX and SPEAr6XX are based on ARM9 whereas SPEAr13XX is based on latest
+  ARM Cortex A9 CPUs.
 
   Hierarchy in SPEAr is as follows:
 
@@ -27,16 +28,25 @@ Introduction
 			- SPEAr600_EVB (Evaluation Board)
 	- SPEAr13XX (13XX SOC series, based on ARM CORTEXA9)
 		- SPEAr1300 (SOC)
+			- SPEAr1300_EVB (Evaluation Board)
+		- SPEAr1310 (SOC)
+			- SPEAr1310_EVB (Evaluation Board)
 
   Configuration
   -------------
 
-  A generic configuration is provided for each machine, and can be used as the
+  A generic configuration is provided for each machine family, and can be used as the
   default by
-	make spear600_defconfig
-	make spear300_defconfig
-	make spear310_defconfig
-	make spear320_defconfig
+	#make ARCH=arm spear13xx_defconfig
+	#make ARCH=arm spear3xx_defconfig
+	#make ARCH=arm spear6xx_defconfig
+
+  Compilation
+  -----------
+
+  After applying default configuration, Linux kernel for SPEAr architecture
+  can be compiled as
+	#make ARCH=arm CROSS_COMPILE=arm-linux- uImage
 
   Layout
   ------
@@ -48,13 +58,15 @@ Introduction
   Each machine series have a directory with name arch/arm/mach-spear followed by
   series name. Like mach-spear3xx, mach-spear6xx and mach-spear13xx.
 
-  Common file for machines of spear3xx family is mach-spear3xx/spear3xx.c and for
-  spear6xx is mach-spear6xx/spear6xx.c. mach-spear* also contain soc/machine
+  Common file for machines of spear3xx family is mach-spear3xx/spear3xx.c, for
+  spear6xx is mach-spear6xx/spear6xx.c and similarly for spear13xx is
+  mach-spear13xx/spear13xx.c. mach-spear* also contain soc/machine
   specific files, like spear300.c, spear310.c, spear320.c and spear600.c.
-  mach-spear* also contains board specific files for each machine type.
+  Board specific files for each machine type is also contained in mach-spear*
+  folder.
 
 
   Document Author
   ---------------
 
-  Viresh Kumar, (c) 2010 ST Microelectronics
+  Viresh Kumar, Shiraz Hashim (c) 2010 ST Microelectronics
diff --git a/MAINTAINERS b/MAINTAINERS
index 668682d..97520d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5462,6 +5462,12 @@ W:	http://www.st.com/spear
 S:	Maintained
 F:	arch/arm/plat-spear/
 
+SPEAR13XX MACHINE SUPPORT
+M:	Shiraz Hashim <shiraz.hashim at st.com>
+W:	http://www.st.com/spear
+S:	Maintained
+F:	arch/arm/mach-spear13xx/
+
 SPEAR3XX MACHINE SUPPORT
 M:	Viresh Kumar <viresh.kumar at st.com>
 W:	http://www.st.com/spear
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:55:55 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:25:55 +0530
Subject: [PATCH V2 35/69] SPEAr: defines base addresses as ulong.
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <fff80c0d4113f421bda085a308fff187fd73e423.1285933332.git.viresh.kumar@st.com>

From: Shiraz Hashim <shiraz.hashim at st.com>

This patch defines base addresses as ulong.

Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
---
 arch/arm/mach-spear13xx/include/mach/spear.h   |   91 ++++++------
 arch/arm/mach-spear3xx/include/mach/spear.h    |  134 +++++-------------
 arch/arm/mach-spear3xx/include/mach/spear300.h |   59 ++------
 arch/arm/mach-spear3xx/include/mach/spear310.h |   34 ++---
 arch/arm/mach-spear3xx/include/mach/spear320.h |   68 +++-------
 arch/arm/mach-spear6xx/include/mach/spear.h    |  174 ++++++-----------------
 6 files changed, 172 insertions(+), 388 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 282ef2f..1a1af72 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -14,12 +14,13 @@
 #ifndef __MACH_SPEAR13XX_H
 #define __MACH_SPEAR13XX_H
 
+#include <asm/memory.h>
 #include <mach/spear1300.h>
 
-#define SPEAR13XX_L2CC_BASE		0xED000000
+#define SPEAR13XX_L2CC_BASE		UL(0xED000000)
 
 /* ARM9SMP peripheral base address */
-#define SPEAR13XX_A9SM_PERIP_BASE	0xEC800000
+#define SPEAR13XX_A9SM_PERIP_BASE	UL(0xEC800000)
 #define VA_SPEAR13XX_A9SM_PERIP_BASE	IO_ADDRESS(SPEAR13XX_A9SM_PERIP_BASE)
 /* A9SM peripheral offsets */
 #define SPEAR13XX_SCU_BASE		(SPEAR13XX_A9SM_PERIP_BASE + 0x00)
@@ -29,26 +30,26 @@
 #define SPEAR13XX_WDT_BASE		(SPEAR13XX_A9SM_PERIP_BASE + 0x620)
 #define SPEAR13XX_GIC_DIST_BASE		(SPEAR13XX_A9SM_PERIP_BASE + 0x1000)
 
-#define SPEAR13XX_UART_BASE		0xE0000000
+#define SPEAR13XX_UART_BASE		UL(0xE0000000)
 #define VA_SPEAR13XX_UART_BASE		IO_ADDRESS(SPEAR13XX_UART_BASE)
 
-#define SPEAR13XX_ADC_BASE		0xE0080000
-#define SPEAR13XX_SSP_BASE		0xE0100000
-#define SPEAR13XX_I2S0_BASE		0xE0180000
-#define SPEAR13XX_I2S1_BASE		0xE0200000
-#define SPEAR13XX_I2C_BASE		0xE0280000
-#define SPEAR13XX_KBD_BASE		0xE0300000
-#define SPEAR13XX_GPT0_BASE		0xE0380000
-#define SPEAR13XX_GPT1_BASE		0xE0400000
-#define SPEAR13XX_GPT2_BASE		0xE0480000
-#define SPEAR13XX_GPT3_BASE		0xE0500000
-#define SPEAR13XX_RTC_BASE		0xE0580000
-#define SPEAR13XX_GPIO0_BASE		0xE0600000
-#define SPEAR13XX_GPIO1_BASE		0xE0680000
-#define SPEAR13XX_MISC_BASE		0xE0700000
+#define SPEAR13XX_ADC_BASE		UL(0xE0080000)
+#define SPEAR13XX_SSP_BASE		UL(0xE0100000)
+#define SPEAR13XX_I2S0_BASE		UL(0xE0180000)
+#define SPEAR13XX_I2S1_BASE		UL(0xE0200000)
+#define SPEAR13XX_I2C_BASE		UL(0xE0280000)
+#define SPEAR13XX_KBD_BASE		UL(0xE0300000)
+#define SPEAR13XX_GPT0_BASE		UL(0xE0380000)
+#define SPEAR13XX_GPT1_BASE		UL(0xE0400000)
+#define SPEAR13XX_GPT2_BASE		UL(0xE0480000)
+#define SPEAR13XX_GPT3_BASE		UL(0xE0500000)
+#define SPEAR13XX_RTC_BASE		UL(0xE0580000)
+#define SPEAR13XX_GPIO0_BASE		UL(0xE0600000)
+#define SPEAR13XX_GPIO1_BASE		UL(0xE0680000)
+#define SPEAR13XX_MISC_BASE		UL(0xE0700000)
 #define VA_SPEAR13XX_MISC_BASE		IO_ADDRESS(SPEAR13XX_MISC_BASE)
 
-#define SPEAR13XX_SYSRAM0_BASE		0xB3800000
+#define SPEAR13XX_SYSRAM0_BASE		UL(0xB3800000)
 #define SPEAR13XX_SYSRAM0_SIZE		0x00800000
 
 /*
@@ -57,34 +58,34 @@
  */
 #define SPEAR13XX_SYS_LOCATION		(SPEAR13XX_SYSRAM0_BASE + 0x600)
 
-#define SPEAR13XX_SYSRAM1_BASE		0xE0800000
+#define SPEAR13XX_SYSRAM1_BASE		UL(0xE0800000)
 #define SPEAR13XX_SYSRAM1_SIZE		0x00800000
-#define SPEAR13XX_CLCD_BASE		0xE1000000
-#define SPEAR13XX_C3_BASE		0xE1800000
-#define SPEAR13XX_GETH_BASE		0xE2000000
-#define SPEAR13XX_UPD_BASE		0xE2800000
-#define SPEAR13XX_UDC_BASE		0xE3800000
-#define SPEAR13XX_UHC0_OHCI_BASE	0xE4000000
-#define SPEAR13XX_UHC0_EHCI_BASE	0xE4800000
-#define SPEAR13XX_UHC1_OHCI_BASE	0xE5000000
-#define SPEAR13XX_UHC1_EHCI_BASE	0xE5800000
-#define SPEAR13XX_SMI_MEM_BASE		0xE6000000
-#define SPEAR13XX_SMI_CTRL_BASE		0xEA000000
-#define SPEAR13XX_DMAC0_BASE		0xEA800000
-#define SPEAR13XX_DMAC1_BASE		0xEB000000
-#define SPEAR13XX_MII_PHY_BASE		0xEB800000
-#define SPEAR13XX_MPMC_BASE		0xEC000000
-#define SPEAR13XX_PCIE0_BASE		0x80000000
-#define SPEAR13XX_PCIE1_BASE		0x90000000
-#define SPEAR13XX_PCIE2_BASE		0xC0000000
-#define SPEAR13XX_PCIE0_APP_BASE	0xB1000000
-#define SPEAR13XX_PCIE1_APP_BASE	0xB1800000
-#define SPEAR13XX_PCIE2_APP_BASE	0xB4000000
-#define SPEAR13XX_FSMC_MEM_BASE		0xA0000000
-#define SPEAR13XX_FSMC_BASE		0xB0000000
-#define SPEAR13XX_JPEG_BASE		0xB2000000
-#define SPEAR13XX_MCIF_CF_BASE		0xB2800000
-#define SPEAR13XX_MCIF_SDHCI_BASE	0xB3000000
+#define SPEAR13XX_CLCD_BASE		UL(0xE1000000)
+#define SPEAR13XX_C3_BASE		UL(0xE1800000)
+#define SPEAR13XX_GETH_BASE		UL(0xE2000000)
+#define SPEAR13XX_UPD_BASE		UL(0xE2800000)
+#define SPEAR13XX_UDC_BASE		UL(0xE3800000)
+#define SPEAR13XX_UHC0_OHCI_BASE	UL(0xE4000000)
+#define SPEAR13XX_UHC0_EHCI_BASE	UL(0xE4800000)
+#define SPEAR13XX_UHC1_OHCI_BASE	UL(0xE5000000)
+#define SPEAR13XX_UHC1_EHCI_BASE	UL(0xE5800000)
+#define SPEAR13XX_SMI_MEM_BASE		UL(0xE6000000)
+#define SPEAR13XX_SMI_CTRL_BASE		UL(0xEA000000)
+#define SPEAR13XX_DMAC0_BASE		UL(0xEA800000)
+#define SPEAR13XX_DMAC1_BASE		UL(0xEB000000)
+#define SPEAR13XX_MII_PHY_BASE		UL(0xEB800000)
+#define SPEAR13XX_MPMC_BASE		UL(0xEC000000)
+#define SPEAR13XX_PCIE0_BASE		UL(0x80000000)
+#define SPEAR13XX_PCIE1_BASE		UL(0x90000000)
+#define SPEAR13XX_PCIE2_BASE		UL(0xC0000000)
+#define SPEAR13XX_PCIE0_APP_BASE	UL(0xB1000000)
+#define SPEAR13XX_PCIE1_APP_BASE	UL(0xB1800000)
+#define SPEAR13XX_PCIE2_APP_BASE	UL(0xB4000000)
+#define SPEAR13XX_FSMC_MEM_BASE		UL(0xA0000000)
+#define SPEAR13XX_FSMC_BASE		UL(0xB0000000)
+#define SPEAR13XX_JPEG_BASE		UL(0xB2000000)
+#define SPEAR13XX_MCIF_CF_BASE		UL(0xB2800000)
+#define SPEAR13XX_MCIF_SDHCI_BASE	UL(0xB3000000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR13XX_UART_BASE
diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h
index dcca856..00828bb 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear.h
@@ -14,124 +14,62 @@
 #ifndef __MACH_SPEAR3XX_H
 #define __MACH_SPEAR3XX_H
 
+#include <asm/memory.h>
 #include <mach/hardware.h>
 #include <mach/spear300.h>
 #include <mach/spear310.h>
 #include <mach/spear320.h>
 
-#define SPEAR3XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR3XX_ML_SDRAM_SIZE		0x40000000
+#define SPEAR3XX_ML_SDRAM_BASE		UL(0x00000000)
 
-#define SPEAR3XX_ICM9_BASE		0xC0000000
-#define SPEAR3XX_ICM9_SIZE		0x10000000
+#define SPEAR3XX_ICM9_BASE		UL(0xC0000000)
 
 /* ICM1 - Low speed connection */
-#define SPEAR3XX_ICM1_2_BASE		0xD0000000
-#define SPEAR3XX_ICM1_2_SIZE		0x10000000
-
-#define SPEAR3XX_ICM1_UART_BASE		0xD0000000
+#define SPEAR3XX_ICM1_2_BASE		UL(0xD0000000)
+#define SPEAR3XX_ICM1_UART_BASE		UL(0xD0000000)
 #define VA_SPEAR3XX_ICM1_UART_BASE	IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE)
-#define SPEAR3XX_ICM1_UART_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_ADC_BASE		0xD0080000
-#define SPEAR3XX_ICM1_ADC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SSP_BASE		0xD0100000
-#define SPEAR3XX_ICM1_SSP_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_I2C_BASE		0xD0180000
-#define SPEAR3XX_ICM1_I2C_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR3XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR3XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR3XX_ICM1_IRDA_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR3XX_ICM1_SRAM_SIZE		0x05800000
+#define SPEAR3XX_ICM1_ADC_BASE		UL(0xD0080000)
+#define SPEAR3XX_ICM1_SSP_BASE		UL(0xD0100000)
+#define SPEAR3XX_ICM1_I2C_BASE		UL(0xD0180000)
+#define SPEAR3XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR3XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR3XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR3XX_ICM2_HWACCEL0_BASE	0xD8800000
-#define SPEAR3XX_ICM2_HWACCEL0_SIZE	0x00800000
-
-#define SPEAR3XX_ICM2_HWACCEL1_BASE	0xD9000000
-#define SPEAR3XX_ICM2_HWACCEL1_SIZE	0x00800000
+#define SPEAR3XX_ICM2_HWACCEL0_BASE	UL(0xD8800000)
+#define SPEAR3XX_ICM2_HWACCEL1_BASE	UL(0xD9000000)
 
 /* ICM4 - High Speed Connection */
-#define SPEAR3XX_ICM4_BASE		0xE0000000
-#define SPEAR3XX_ICM4_SIZE		0x08000000
-
-#define SPEAR3XX_ICM4_MII_BASE		0xE0800000
-#define SPEAR3XX_ICM4_MII_SIZE		0x00800000
-
-#define SPEAR3XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR3XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR3XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR3XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	0xE1800000
-#define SPEAR3XX_ICM4_USB_EHCI0_1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR3XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR3XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR3XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR3XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR3XX_ICM4_MII_BASE		UL(0xE0800000)
+#define SPEAR3XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR3XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR3XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	UL(0xE1800000)
+#define SPEAR3XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR3XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR3XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* ML1 - Multi Layer CPU Subsystem */
-#define SPEAR3XX_ICM3_ML1_2_BASE	0xF0000000
-#define SPEAR3XX_ICM3_ML1_2_SIZE	0x0F000000
-
-#define SPEAR3XX_ML1_TMR_BASE		0xF0000000
-#define SPEAR3XX_ML1_TMR_SIZE		0x00100000
-
-#define SPEAR3XX_ML1_VIC_BASE		0xF1100000
+#define SPEAR3XX_ICM3_ML1_2_BASE	UL(0xF0000000)
+#define SPEAR3XX_ML1_TMR_BASE		UL(0xF0000000)
+#define SPEAR3XX_ML1_VIC_BASE		UL(0xF1100000)
 #define VA_SPEAR3XX_ML1_VIC_BASE	IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE)
-#define SPEAR3XX_ML1_VIC_SIZE		0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR3XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR3XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR3XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR3XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR3XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR3XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_TMR0_BASE		0xFC800000
-#define SPEAR3XX_ICM3_TMR0_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR3XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR3XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR3XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR3XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR3XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR3XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR3XX_ICM3_TMR0_BASE		UL(0xFC800000)
+#define SPEAR3XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR3XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR3XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR3XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR3XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR3XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR3XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE)
-#define SPEAR3XX_ICM3_MISC_REG_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_TMR1_BASE		0xFCB00000
-#define SPEAR3XX_ICM3_TMR1_SIZE		0x00080000
+#define SPEAR3XX_ICM3_TMR1_BASE		UL(0xFCB00000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR3XX_ICM1_UART_BASE
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index 1059d5a..c723515 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -17,11 +17,9 @@
 #define __MACH_SPEAR300_H
 
 /* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE		0x50000000
-#define SPEAR300_TELECOM_SIZE		0x10000000
+#define SPEAR300_TELECOM_BASE		UL(0x50000000)
 
 /* Interrupt registers offsets and masks */
-#define SPEAR300_TELECOM_REG_SIZE	0x00010000
 #define INT_ENB_MASK_REG		0x54
 #define INT_STS_MASK_REG		0x58
 #define IT_PERS_S_IRQ_MASK		(1 << 0)
@@ -36,47 +34,20 @@
 
 #define SHIRQ_RAS1_MASK			0x1FF
 
-#define SPEAR300_CLCD_BASE		0x60000000
-#define SPEAR300_CLCD_SIZE		0x10000000
-
-#define SPEAR300_SDHCI_BASE		0x70000000
-#define SPEAR300_SDHCI_SIZE		0x10000000
-
-#define SPEAR300_NAND_0_BASE		0x80000000
-#define SPEAR300_NAND_0_SIZE		0x04000000
-
-#define SPEAR300_NAND_1_BASE		0x84000000
-#define SPEAR300_NAND_1_SIZE		0x04000000
-
-#define SPEAR300_NAND_2_BASE		0x88000000
-#define SPEAR300_NAND_2_SIZE		0x04000000
-
-#define SPEAR300_NAND_3_BASE		0x8c000000
-#define SPEAR300_NAND_3_SIZE		0x04000000
-
-#define SPEAR300_NOR_0_BASE		0x90000000
-#define SPEAR300_NOR_0_SIZE		0x01000000
-
-#define SPEAR300_NOR_1_BASE		0x91000000
-#define SPEAR300_NOR_1_SIZE		0x01000000
-
-#define SPEAR300_NOR_2_BASE		0x92000000
-#define SPEAR300_NOR_2_SIZE		0x01000000
-
-#define SPEAR300_NOR_3_BASE		0x93000000
-#define SPEAR300_NOR_3_SIZE		0x01000000
-
-#define SPEAR300_FSMC_BASE		0x94000000
-#define SPEAR300_FSMC_SIZE		0x05000000
-
-#define SPEAR300_SOC_CONFIG_BASE	0x99000000
-#define SPEAR300_SOC_CONFIG_SIZE	0x00000008
-
-#define SPEAR300_KEYBOARD_BASE		0xA0000000
-#define SPEAR300_KEYBOARD_SIZE		0x09000000
-
-#define SPEAR300_GPIO_BASE		0xA9000000
-#define SPEAR300_GPIO_SIZE		0x07000000
+#define SPEAR300_CLCD_BASE		UL(0x60000000)
+#define SPEAR300_SDHCI_BASE		UL(0x70000000)
+#define SPEAR300_NAND_0_BASE		UL(0x80000000)
+#define SPEAR300_NAND_1_BASE		UL(0x84000000)
+#define SPEAR300_NAND_2_BASE		UL(0x88000000)
+#define SPEAR300_NAND_3_BASE		UL(0x8c000000)
+#define SPEAR300_NOR_0_BASE		UL(0x90000000)
+#define SPEAR300_NOR_1_BASE		UL(0x91000000)
+#define SPEAR300_NOR_2_BASE		UL(0x92000000)
+#define SPEAR300_NOR_3_BASE		UL(0x93000000)
+#define SPEAR300_FSMC_BASE		UL(0x94000000)
+#define SPEAR300_SOC_CONFIG_BASE	UL(0x99000000)
+#define SPEAR300_KEYBOARD_BASE		UL(0xA0000000)
+#define SPEAR300_GPIO_BASE		UL(0xA9000000)
 
 #endif /* __MACH_SPEAR300_H */
 
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index b27bb8a..1e85347 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -16,30 +16,18 @@
 #ifndef __MACH_SPEAR310_H
 #define __MACH_SPEAR310_H
 
-#define SPEAR310_NAND_BASE		0x40000000
-#define SPEAR310_NAND_SIZE		0x04000000
+#define SPEAR310_NAND_BASE		UL(0x40000000)
+#define SPEAR310_FSMC_BASE		UL(0x44000000)
+#define SPEAR310_UART1_BASE		UL(0xB2000000)
+#define SPEAR310_UART2_BASE		UL(0xB2080000)
+#define SPEAR310_UART3_BASE		UL(0xB2100000)
+#define SPEAR310_UART4_BASE		UL(0xB2180000)
+#define SPEAR310_UART5_BASE		UL(0xB2200000)
+#define SPEAR310_HDLC_BASE		UL(0xB2800000)
+#define SPEAR310_RS485_0_BASE		UL(0xB3000000)
+#define SPEAR310_RS485_1_BASE		UL(0xB3800000)
+#define SPEAR310_SOC_CONFIG_BASE	UL(0xB4000000)
 
-#define SPEAR310_FSMC_BASE		0x44000000
-#define SPEAR310_FSMC_SIZE		0x01000000
-
-#define SPEAR310_UART1_BASE		0xB2000000
-#define SPEAR310_UART2_BASE		0xB2080000
-#define SPEAR310_UART3_BASE		0xB2100000
-#define SPEAR310_UART4_BASE		0xB2180000
-#define SPEAR310_UART5_BASE		0xB2200000
-#define SPEAR310_UART_SIZE		0x00080000
-
-#define SPEAR310_HDLC_BASE		0xB2800000
-#define SPEAR310_HDLC_SIZE		0x00800000
-
-#define SPEAR310_RS485_0_BASE		0xB3000000
-#define SPEAR310_RS485_0_SIZE		0x00800000
-
-#define SPEAR310_RS485_1_BASE		0xB3800000
-#define SPEAR310_RS485_1_SIZE		0x00800000
-
-#define SPEAR310_SOC_CONFIG_BASE	0xB4000000
-#define SPEAR310_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define SMII0_IRQ_MASK			(1 << 0)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 89f5bfb..940f0d8 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -16,57 +16,25 @@
 #ifndef __MACH_SPEAR320_H
 #define __MACH_SPEAR320_H
 
-#define SPEAR320_EMI_CTRL_BASE		0x40000000
-#define SPEAR320_EMI_CTRL_SIZE		0x08000000
+#define SPEAR320_EMI_CTRL_BASE		UL(0x40000000)
+#define SPEAR320_FSMC_BASE		UL(0x4C000000)
+#define SPEAR320_NAND_BASE		UL(0x50000000)
+#define SPEAR320_I2S_BASE		UL(0x60000000)
+#define SPEAR320_SDHCI_BASE		UL(0x70000000)
+#define SPEAR320_CLCD_BASE		UL(0x90000000)
+#define SPEAR320_PAR_PORT_BASE		UL(0xA0000000)
+#define SPEAR320_CAN0_BASE		UL(0xA1000000)
+#define SPEAR320_CAN1_BASE		UL(0xA2000000)
+#define SPEAR320_UART1_BASE		UL(0xA3000000)
+#define SPEAR320_UART2_BASE		UL(0xA4000000)
+#define SPEAR320_SSP0_BASE		UL(0xA5000000)
+#define SPEAR320_SSP1_BASE		UL(0xA6000000)
+#define SPEAR320_I2C_BASE		UL(0xA7000000)
+#define SPEAR320_PWM_BASE		UL(0xA8000000)
+#define SPEAR320_SMII0_BASE		UL(0xAA000000)
+#define SPEAR320_SMII1_BASE		UL(0xAB000000)
+#define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
 
-#define SPEAR320_FSMC_BASE		0x4C000000
-#define SPEAR320_FSMC_SIZE		0x01000000
-
-#define SPEAR320_NAND_BASE		0x50000000
-#define SPEAR320_NAND_SIZE		0x04000000
-
-#define SPEAR320_I2S_BASE		0x60000000
-#define SPEAR320_I2S_SIZE		0x10000000
-
-#define SPEAR320_SDHCI_BASE		0x70000000
-#define SPEAR320_SDHCI_SIZE		0x10000000
-
-#define SPEAR320_CLCD_BASE		0x90000000
-#define SPEAR320_CLCD_SIZE		0x10000000
-
-#define SPEAR320_PAR_PORT_BASE		0xA0000000
-#define SPEAR320_PAR_PORT_SIZE		0x01000000
-
-#define SPEAR320_CAN0_BASE		0xA1000000
-#define SPEAR320_CAN0_SIZE		0x01000000
-
-#define SPEAR320_CAN1_BASE		0xA2000000
-#define SPEAR320_CAN1_SIZE		0x01000000
-
-#define SPEAR320_UART1_BASE		0xA3000000
-#define SPEAR320_UART2_BASE		0xA4000000
-#define SPEAR320_UART_SIZE		0x01000000
-
-#define SPEAR320_SSP0_BASE		0xA5000000
-#define SPEAR320_SSP0_SIZE		0x01000000
-
-#define SPEAR320_SSP1_BASE		0xA6000000
-#define SPEAR320_SSP1_SIZE		0x01000000
-
-#define SPEAR320_I2C_BASE		0xA7000000
-#define SPEAR320_I2C_SIZE		0x01000000
-
-#define SPEAR320_PWM_BASE		0xA8000000
-#define SPEAR320_PWM_SIZE		0x01000000
-
-#define SPEAR320_SMII0_BASE		0xAA000000
-#define SPEAR320_SMII0_SIZE		0x01000000
-
-#define SPEAR320_SMII1_BASE		0xAB000000
-#define SPEAR320_SMII1_SIZE		0x01000000
-
-#define SPEAR320_SOC_CONFIG_BASE	0xB3000000
-#define SPEAR320_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define INT_CLR_MASK_REG		0x04
diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h
index 31486e5..4a2ecc7 100644
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ b/arch/arm/mach-spear6xx/include/mach/spear.h
@@ -14,153 +14,71 @@
 #ifndef __MACH_SPEAR6XX_H
 #define __MACH_SPEAR6XX_H
 
+#include <asm/memory.h>
 #include <mach/hardware.h>
 #include <mach/spear600.h>
 
-#define SPEAR6XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR6XX_ML_SDRAM_SIZE		0x40000000
-
+#define SPEAR6XX_ML_SDRAM_BASE		UL(0x00000000)
 /* ICM1 - Low speed connection */
-#define SPEAR6XX_ICM1_BASE		0xD0000000
-#define SPEAR6XX_ICM1_SIZE		0x08000000
+#define SPEAR6XX_ICM1_BASE		UL(0xD0000000)
 
-#define SPEAR6XX_ICM1_UART0_BASE	0xD0000000
+#define SPEAR6XX_ICM1_UART0_BASE	UL(0xD0000000)
 #define VA_SPEAR6XX_ICM1_UART0_BASE	IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE)
-#define SPEAR6XX_ICM1_UART0_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_UART1_BASE	0xD0080000
-#define SPEAR6XX_ICM1_UART1_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_SSP0_BASE		0xD0100000
-#define SPEAR6XX_ICM1_SSP0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_SSP1_BASE		0xD0180000
-#define SPEAR6XX_ICM1_SSP1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_I2C_BASE		0xD0200000
-#define SPEAR6XX_ICM1_I2C_SIZE		0x00080000
 
-#define SPEAR6XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR6XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR6XX_ICM1_IRDA_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_FSMC_BASE		0xD1800000
-#define SPEAR6XX_ICM1_FSMC_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_NAND_BASE		0xD2000000
-#define SPEAR6XX_ICM1_NAND_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR6XX_ICM1_SRAM_SIZE		0x00800000
+#define SPEAR6XX_ICM1_UART1_BASE	UL(0xD0080000)
+#define SPEAR6XX_ICM1_SSP0_BASE		UL(0xD0100000)
+#define SPEAR6XX_ICM1_SSP1_BASE		UL(0xD0180000)
+#define SPEAR6XX_ICM1_I2C_BASE		UL(0xD0200000)
+#define SPEAR6XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR6XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR6XX_ICM1_FSMC_BASE		UL(0xD1800000)
+#define SPEAR6XX_ICM1_NAND_BASE		UL(0xD2000000)
+#define SPEAR6XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR6XX_ICM2_BASE		0xD8000000
-#define SPEAR6XX_ICM2_SIZE		0x08000000
-
-#define SPEAR6XX_ICM2_TMR0_BASE		0xD8000000
-#define SPEAR6XX_ICM2_TMR0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_TMR1_BASE		0xD8080000
-#define SPEAR6XX_ICM2_TMR1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_GPIO_BASE		0xD8100000
-#define SPEAR6XX_ICM2_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_SSP2_BASE		0xD8180000
-#define SPEAR6XX_ICM2_SSP2_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_ADC_BASE		0xD8200000
-#define SPEAR6XX_ICM2_ADC_SIZE		0x00080000
+#define SPEAR6XX_ICM2_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR0_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR1_BASE		UL(0xD8080000)
+#define SPEAR6XX_ICM2_GPIO_BASE		UL(0xD8100000)
+#define SPEAR6XX_ICM2_SSP2_BASE		UL(0xD8180000)
+#define SPEAR6XX_ICM2_ADC_BASE		UL(0xD8200000)
 
 /* ML-1, 2 - Multi Layer CPU Subsystem */
-#define SPEAR6XX_ML_CPU_BASE		0xF0000000
-#define SPEAR6XX_ML_CPU_SIZE		0x08000000
-
-#define SPEAR6XX_CPU_TMR_BASE		0xF0000000
-#define SPEAR6XX_CPU_TMR_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_GPIO_BASE		0xF0100000
-#define SPEAR6XX_CPU_GPIO_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_VIC_SEC_BASE	0xF1000000
+#define SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_TMR_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_GPIO_BASE		UL(0xF0100000)
+#define SPEAR6XX_CPU_VIC_SEC_BASE	UL(0xF1000000)
 #define VA_SPEAR6XX_CPU_VIC_SEC_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE)
-#define SPEAR6XX_CPU_VIC_SEC_SIZE	0x00100000
-
-#define SPEAR6XX_CPU_VIC_PRI_BASE	0xF1100000
+#define SPEAR6XX_CPU_VIC_PRI_BASE	UL(0xF1100000)
 #define VA_SPEAR6XX_CPU_VIC_PRI_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE)
-#define SPEAR6XX_CPU_VIC_PRI_SIZE	0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR6XX_ICM3_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SIZE		0x08000000
-
-#define SPEAR6XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR6XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR6XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_CLCD_BASE		0xFC200000
-#define SPEAR6XX_ICM3_CLCD_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR6XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR6XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_TMR_BASE		0xFC800000
-#define SPEAR6XX_ICM3_TMR_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR6XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR6XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR6XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR6XX_ICM3_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR6XX_ICM3_CLCD_BASE		UL(0xFC200000)
+#define SPEAR6XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR6XX_ICM3_TMR_BASE		UL(0xFC800000)
+#define SPEAR6XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR6XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR6XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR6XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR6XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR6XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR6XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR6XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE)
-#define SPEAR6XX_ICM3_MISC_REG_SIZE	0x00080000
 
 /* ICM4 - High Speed Connection */
-#define SPEAR6XX_ICM4_BASE		0xE0000000
-#define SPEAR6XX_ICM4_SIZE		0x08000000
-
-#define SPEAR6XX_ICM4_GMAC_BASE		0xE0800000
-#define SPEAR6XX_ICM4_GMAC_SIZE		0x00800000
-
-#define SPEAR6XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR6XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR6XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR6XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI0_BASE	0xE1800000
-#define SPEAR6XX_ICM4_USB_EHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR6XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI1_BASE	0xE2000000
-#define SPEAR6XX_ICM4_USB_EHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR6XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR6XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR6XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR6XX_ICM4_GMAC_BASE		UL(0xE0800000)
+#define SPEAR6XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR6XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR6XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR6XX_ICM4_USB_EHCI0_BASE	UL(0xE1800000)
+#define SPEAR6XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR6XX_ICM4_USB_EHCI1_BASE	UL(0xE2000000)
+#define SPEAR6XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR6XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR6XX_ICM1_UART0_BASE
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:24 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:24 +0530
Subject: [PATCH V2 64/69] SPEAr6xx: Rework Kconfig for single image solution
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <f40cb25833510d716dfbb55460654050373d2278.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
---
 arch/arm/mach-spear6xx/Kconfig    |   15 ++++++++-------
 arch/arm/mach-spear6xx/Kconfig600 |   17 -----------------
 2 files changed, 8 insertions(+), 24 deletions(-)
 delete mode 100644 arch/arm/mach-spear6xx/Kconfig600

diff --git a/arch/arm/mach-spear6xx/Kconfig b/arch/arm/mach-spear6xx/Kconfig
index bddba03..ff4ae5b 100644
--- a/arch/arm/mach-spear6xx/Kconfig
+++ b/arch/arm/mach-spear6xx/Kconfig
@@ -4,17 +4,18 @@
 
 if ARCH_SPEAR6XX
 
-choice
-	prompt "SPEAr6XX Family"
-	default MACH_SPEAR600
+menu "SPEAr6xx Implementations"
+config BOARD_SPEAR600_EVB
+	bool "SPEAr600 Evaluation Board"
+	select MACH_SPEAR600
+	help
+	  Supports ST SPEAr600 Evaluation Board
+
+endmenu
 
 config MACH_SPEAR600
 	bool "SPEAr600"
 	help
 	  Supports ST SPEAr600 Machine
-endchoice
-
-# Adding SPEAr6XX machine specific configuration files
-source "arch/arm/mach-spear6xx/Kconfig600"
 
 endif #ARCH_SPEAR6XX
diff --git a/arch/arm/mach-spear6xx/Kconfig600 b/arch/arm/mach-spear6xx/Kconfig600
deleted file mode 100644
index 9e19f65..0000000
--- a/arch/arm/mach-spear6xx/Kconfig600
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# SPEAr600 machine configuration file
-#
-
-if MACH_SPEAR600
-
-choice
-	prompt "SPEAr600 Boards"
-	default BOARD_SPEAR600_EVB
-
-config	BOARD_SPEAR600_EVB
-	bool "SPEAr600 Evaluation Board"
-	help
-	  Supports ST SPEAr600 Evaluation Board
-endchoice
-
-endif	#MACH_SPEAR600
-- 
1.7.2.2



From viresh.kumar at st.com  Fri Oct  1 07:56:25 2010
From: viresh.kumar at st.com (Viresh KUMAR)
Date: Fri,  1 Oct 2010 17:26:25 +0530
Subject: [PATCH V2 65/69] ST SPEAR6xx: renaming spear600_defconfig as
	spear6xx_defconfig
In-Reply-To: <cover.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
Message-ID: <9c685d931c33e6b5d549519d6cec8da6c3fdbab7.1285933332.git.viresh.kumar@st.com>

Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar at st.com>
---
 .../{spear600_defconfig => spear6xx_defconfig}     |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
 rename arch/arm/configs/{spear600_defconfig => spear6xx_defconfig} (97%)

diff --git a/arch/arm/configs/spear600_defconfig b/arch/arm/configs/spear6xx_defconfig
similarity index 97%
rename from arch/arm/configs/spear600_defconfig
rename to arch/arm/configs/spear6xx_defconfig
index 6777c11..cef2e83 100644
--- a/arch/arm/configs/spear600_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -8,6 +8,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR6XX=y
+CONFIG_BOARD_SPEAR600_EVB=y
 CONFIG_BINFMT_MISC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
@@ -22,7 +23,6 @@ CONFIG_MAX_RAW_DEVS=8192
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
-- 
1.7.2.2



From bigeasy at linutronix.de  Fri Oct  1 15:37:37 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Fri, 1 Oct 2010 21:37:37 +0200
Subject: [PATCH v2] mtd/nand: introduce NAND_CREATE_EMPTY_BBT
In-Reply-To: <1285959468.32172.2.camel@brekeke>
References: <1285782234-32509-1-git-send-email-bigeasy@linutronix.de>
	<1285782234-32509-5-git-send-email-bigeasy@linutronix.de>
	<1285959468.32172.2.camel@brekeke>
Message-ID: <20101001193737.GA28639@www.tglx.de>

it will create an empty BBT table without considering vendor's BBT
information. Vendor's information may be unavailable if the NAND
controller has a different DATA & OOB layout or this information may be
allready purged.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 drivers/mtd/nand/nand_bbt.c |    3 ++-
 include/linux/mtd/bbm.h     |    2 +-
 include/linux/mtd/nand.h    |    2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b7b63cf..a27984c 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -999,7 +999,8 @@ static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
 			continue;
 
 		/* Create the table in memory by scanning the chip(s) */
-		create_bbt(mtd, buf, bd, chipsel);
+		if (!(this->options & NAND_CREATE_EMPTY_BBT))
+			create_bbt(mtd, buf, bd, chipsel);
 
 		td->version[i] = 1;
 		if (md)
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index ba15b52..57cc0e6 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -84,7 +84,7 @@ struct nand_bbt_descr {
 #define NAND_BBT_PERCHIP	0x00000080
 /* bbt has a version counter at offset veroffs */
 #define NAND_BBT_VERSION	0x00000100
-/* Create a bbt if none axists */
+/* Create a bbt if none exists */
 #define NAND_BBT_CREATE		0x00000200
 /* Search good / bad pattern through all pages of a block */
 #define NAND_BBT_SCANALLPAGES	0x00000400
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 27e3d0a..d34b912 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -223,6 +223,8 @@ typedef enum {
  * the OOB area
  */
 #define NAND_USE_FLASH_BBT_NO_OOB	0x00100000
+/* Create an empty BBT with no vendor information if the BBT is available */
+#define NAND_CREATE_EMPTY_BBT		0x00200000
 
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Oct  1 15:29:06 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 22:29:06 +0300
Subject: [PATCH 15/18] mtd: Fix endianness issues from device tree
In-Reply-To: <1285916771-18033-16-git-send-email-imunsie@au1.ibm.com>
References: <1285916771-18033-1-git-send-email-imunsie@au1.ibm.com>
	<1285916771-18033-16-git-send-email-imunsie@au1.ibm.com>
Message-ID: <1285961346.32172.10.camel@brekeke>

On Fri, 2010-10-01 at 17:06 +1000, Ian Munsie wrote:
> From: Ian Munsie <imunsie at au1.ibm.com>
> 
> This patch adds the appropriate conversions to correct the endianness
> issues in the MTD driver whenever it accesses the device tree (which is
> always big endian).
> 
> Signed-off-by: Ian Munsie <imunsie at au1.ibm.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Oct  1 16:00:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 23:00:48 +0300
Subject: [PATCH v2] mtd/nand: introduce NAND_CREATE_EMPTY_BBT
In-Reply-To: <20101001193737.GA28639@www.tglx.de>
References: <1285782234-32509-1-git-send-email-bigeasy@linutronix.de>
	<1285782234-32509-5-git-send-email-bigeasy@linutronix.de>
	<1285959468.32172.2.camel@brekeke> <20101001193737.GA28639@www.tglx.de>
Message-ID: <1285963248.32172.11.camel@brekeke>

On Fri, 2010-10-01 at 21:37 +0200, Sebastian Andrzej Siewior wrote:
> it will create an empty BBT table without considering vendor's BBT
> information. Vendor's information may be unavailable if the NAND
> controller has a different DATA & OOB layout or this information may be
> allready purged.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

Pushed to l2-mtd-2.6.git, and the nandsim patch as well.

git.infradead.org is down now for some reasons, but when it is up, I'll
push my tree out.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Oct  1 15:06:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 22:06:15 +0300
Subject: [PATCH] mtd: nand: fix MTD_MODE_RAW writes
In-Reply-To: <1285846894-4479-1-git-send-email-jon.povey@racelogic.co.uk>
References: <1285846894-4479-1-git-send-email-jon.povey@racelogic.co.uk>
Message-ID: <1285959975.32172.9.camel@brekeke>

On Thu, 2010-09-30 at 20:41 +0900, Jon Povey wrote:
> RAW writes were broken by 782ce79a45b3b850b108896fcf7da26754061c8f
> which introduced a check of ops->ooboffs in nand_do_write_ops().
> 
> When writing in RAW mode this is called with an ops struct on the stack
> of mtdchar.c:mtd_write() which does not initialise ops->ooboffs, so it
> is garbage and fails this test.
> 
> This test does not make sense if ops->oobbuf is NULL, which it is in the
> RAW write path, so include that in the test.
> 
> Signed-off-by: Jon Povey <jon.povey at racelogic.co.uk>
> CC: Maxim Levitsky <maximlevitsky at gmail.com>
> CC: David Woodhouse <David.Woodhouse at intel.com>
> ---
> I am not sure this is the right way to fix this, as I don't really understand
> what the test was trying to fix/prevent.
> 
> This is really just me showing my shotgun debugging solution that seems to
> work for me, and see what people have to say about it / how to fix properly.
> 
> This was an unpleasant regression for me: I use MTD_MODE_RAW to write a
> bootloader, and this got close to being a field update bricker..

I already have something similar in my l2-mtd-2.6.git / for-2.6.36 and I
was bugging David to send it upstream.

But I've pushed your patch to the same branch and added Cc: stable
<stable at kernel.org>

But I think ideally these 2 patches should be folded into one patch.
I'll leave this for David to do and possibly decide who would be the
author of the resulting patch :-)

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Oct  1 15:00:56 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 22:00:56 +0300
Subject: [PATCH] MTD: m25p80.c: Add support for S25FL032P spi-nor flash
	devices.
In-Reply-To: <1285845962-29597-1-git-send-email-david.jander@protonic.nl>
References: <1285845962-29597-1-git-send-email-david.jander@protonic.nl>
Message-ID: <1285959656.32172.3.camel@brekeke>

On Thu, 2010-09-30 at 13:26 +0200, David Jander wrote:
> From: David Jander <david at protonic.nl>
> 
> Signed-off-by: David Jander <david at protonic.nl>
> ---
>  drivers/mtd/devices/m25p80.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier at gentoo.org  Fri Oct  1 14:57:07 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri, 1 Oct 2010 14:57:07 -0400
Subject: [PATCH] jffs2reader: convert to common.h helpers
In-Reply-To: <1285953246-19729-1-git-send-email-vapier@gentoo.org>
References: <1285953246-19729-1-git-send-email-vapier@gentoo.org>
Message-ID: <AANLkTik7_vDDReL8Zk5m0WFL+ptMWG_-Cyt_svAYQKCC@mail.gmail.com>

On Fri, Oct 1, 2010 at 13:14, Mike Frysinger wrote:
> --- a/jffs2reader.c
> +++ b/jffs2reader.c
> @@ -136,10 +136,8 @@ void putblock(char *b, size_t bsize, size_t * rsize,
> ?{
> ? ? ? ?uLongf dlen = n->dsize;
>
> - ? ? ? if (n->isize > bsize || (n->offset + dlen) > bsize) {
> - ? ? ? ? ? ? ? fprintf(stderr, "File does not fit into buffer!\n");
> - ? ? ? ? ? ? ? exit(EXIT_FAILURE);
> - ? ? ? }
> + ? ? ? if (n->isize > bsize || (n->offset + dlen) > bsize)
> + ? ? ? ? ? ? ? errmsg("File does not fit into buffer!");

ugh, dont merge this one.  on a second review, i see that i used
"errmsg" when i should have used "errmsg_die".
-mike


From dedekind1 at gmail.com  Fri Oct  1 14:57:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 21:57:48 +0300
Subject: [PATCH 4/5] mtd/nand: introduce NAND_CREATE_EMPTY_BBT
In-Reply-To: <1285782234-32509-5-git-send-email-bigeasy@linutronix.de>
References: <1285782234-32509-1-git-send-email-bigeasy@linutronix.de>
	<1285782234-32509-5-git-send-email-bigeasy@linutronix.de>
Message-ID: <1285959468.32172.2.camel@brekeke>

On Wed, 2010-09-29 at 19:43 +0200, Sebastian Andrzej Siewior wrote:
> it will create an empty BBT table without considering vendor's BBT
> information. Vendor's information may be unavailable if the NAND
> controller has a different DATA & OOB layout or if this information is
> allready purged.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

This one does not apply on top of your patch 3/5 v2, could you please
refresh it and resend?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Oct  1 14:56:50 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 01 Oct 2010 21:56:50 +0300
Subject: [PATCH v2] mtd/nand: add support for BBT without OOB
In-Reply-To: <20100930192800.GA17730@Chamillionaire.breakpoint.cc>
References: <1285782234-32509-1-git-send-email-bigeasy@linutronix.de>
	<1285782234-32509-4-git-send-email-bigeasy@linutronix.de>
	<1285791064.1776.35.camel@brekeke>
	<20100930085111.GA12354@Chamillionaire.breakpoint.cc>
	<1285838065.11684.57.camel@localhost>
	<20100930192800.GA17730@Chamillionaire.breakpoint.cc>
Message-ID: <1285959410.32172.1.camel@brekeke>

On Thu, 2010-09-30 at 21:28 +0200, Sebastian Andrzej Siewior wrote:
> The first (sixt) byte in the OOB area contains vendor's bad block
> information. During identification of the NAND chip this information is
> collected by scanning the complete chip.
> The option NAND_USE_FLASH_BBT is used to store this information in a sector so
> we don't have to scan the complete flash. Unfortunately the code stores
> a marker in order to recognize the BBT in the OOB area. This will fail
> if the OOB area is completely used for ECC.
> This patch introduces the option NAND_USE_FLASH_BBT_NO_OOB which has to be
> used with NAND_USE_FLASH_BBT. It will then store BBT on flash without
> touching the OOB area. The BBT format on flash remains same except the
> first page starts with the recognition pattern followed by the version byte.
> This change was tested in nandsim and it looks good so far :)
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From akpm at linux-foundation.org  Fri Oct  1 17:16:27 2010
From: akpm at linux-foundation.org (akpm at linux-foundation.org)
Date: Fri, 01 Oct 2010 14:16:27 -0700
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
Message-ID: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>

From: Sudhakar Rajashekhara <sudhakar.raj at ti.com>

Implement a memory accessor interface in the MTD layer which enables the
kernel to access flash data.

This patch adds two new members to the mtd_partition structure, a function
handler which will be called during setup of the partition and an argument
to be passed to this setup function.

Example:
+static struct mtd_partition spi_flash_partitions[] = {
+       [0] = {
+               .name       = "U-Boot",
+               .offset     = 0,
+               .size       = SZ_256K,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       [1] = {
+               .name       = "U-Boot Environment",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_64K,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       [2] = {
+               .name       = "Linux",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_7M,
+               .mask_flags = 0,
+       },
+       [3] = {
+               .name       = "MAC Address",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_64K,
+               .mask_flags = 0,
+               .setup      = davinci_get_mac_addr,
+               .context    = (void *)0,
+       },
+};

The davinci_get_mac_addr function reads the MAC address from
offset ZERO of last MTD partition.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj at ti.com>
Acked-by: Kevin Hilman <khilman at deeprootsystems.com>
Cc: David Brownell <david-b at pacbell.net>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Anton Vorontsov <cbouatmailru at gmail.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
---

 drivers/mtd/mtdpart.c          |   40 +++++++++++++++++++++++++++++++
 include/linux/mtd/partitions.h |    3 ++
 2 files changed, 43 insertions(+)

diff -puN drivers/mtd/mtdpart.c~mtdpart-memory-accessor-interface-for-mtd-layer drivers/mtd/mtdpart.c
--- a/drivers/mtd/mtdpart.c~mtdpart-memory-accessor-interface-for-mtd-layer
+++ a/drivers/mtd/mtdpart.c
@@ -37,6 +37,7 @@ static LIST_HEAD(mtd_partitions);
 struct mtd_part {
 	struct mtd_info mtd;
 	struct mtd_info *master;
+	struct memory_accessor macc;
 	uint64_t offset;
 	struct list_head list;
 };
@@ -346,6 +347,39 @@ int del_mtd_partitions(struct mtd_info *
 }
 EXPORT_SYMBOL(del_mtd_partitions);
 
+/*
+ * This lets other kernel code access the flash data. For example, it
+ * might hold a board's Ethernet address, or board-specific calibration
+ * data generated on the manufacturing floor.
+ */
+static ssize_t mtd_macc_read(struct memory_accessor *macc, char *buf,
+			off_t offset, size_t count)
+{
+	struct mtd_part *part = container_of(macc, struct mtd_part, macc);
+	ssize_t ret = -EIO;
+	size_t retlen;
+
+	if (part_read((struct mtd_info *)part, offset, count,
+			&retlen, buf) == 0)
+		ret = retlen;
+
+	return ret;
+}
+
+static ssize_t mtd_macc_write(struct memory_accessor *macc, const char *buf,
+			off_t offset, size_t count)
+{
+	struct mtd_part *part = container_of(macc, struct mtd_part, macc);
+	ssize_t ret = -EIO;
+	size_t retlen;
+
+	if (part_write((struct mtd_info *)part, offset, count,
+			&retlen, buf) == 0)
+		ret = retlen;
+
+	return ret;
+}
+
 static struct mtd_part *add_one_partition(struct mtd_info *master,
 		const struct mtd_partition *part, int partno,
 		uint64_t cur_offset)
@@ -383,6 +417,9 @@ static struct mtd_part *add_one_partitio
 	slave->mtd.read = part_read;
 	slave->mtd.write = part_write;
 
+	slave->macc.read = mtd_macc_read;
+	slave->macc.write = mtd_macc_write;
+
 	if (master->panic_write)
 		slave->mtd.panic_write = part_panic_write;
 
@@ -449,6 +486,9 @@ static struct mtd_part *add_one_partitio
 	printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
 		(unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
 
+	if (part->setup)
+		part->setup(&slave->macc, (void *)part->context);
+
 	/* let's do some sanity checks */
 	if (slave->offset >= master->size) {
 		/* let's register it anyway to preserve ordering */
diff -puN include/linux/mtd/partitions.h~mtdpart-memory-accessor-interface-for-mtd-layer include/linux/mtd/partitions.h
--- a/include/linux/mtd/partitions.h~mtdpart-memory-accessor-interface-for-mtd-layer
+++ a/include/linux/mtd/partitions.h
@@ -10,6 +10,7 @@
 #define MTD_PARTITIONS_H
 
 #include <linux/types.h>
+#include <linux/memory.h>
 
 
 /*
@@ -40,6 +41,8 @@ struct mtd_partition {
 	uint64_t offset;		/* offset within the master MTD space */
 	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */
 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only)*/
+	void (*setup)(struct memory_accessor *, void *context);
+	void *context;
 };
 
 #define MTDPART_OFS_NXTBLK	(-2)
_


From akpm at linux-foundation.org  Fri Oct  1 17:16:28 2010
From: akpm at linux-foundation.org (akpm at linux-foundation.org)
Date: Fri, 01 Oct 2010 14:16:28 -0700
Subject: [patch 2/2] jffs2: use cond_resched() instead of yield()
Message-ID: <201010012116.o91LGSlt021122@imap1.linux-foundation.org>

From: Wolfram Sang <w.sang at pengutronix.de>

yield() has different semantics meanwhile and even causes RT-kernels to
BUG.  Replace the only appearance left in jffs2.

Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
Cc: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Cc: Ingo Molnar <mingo at elte.hu>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Artem Bityutskiy <dedekind at infradead.org>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
---

 fs/jffs2/erase.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -puN fs/jffs2/erase.c~jffs2-use-cond_resched-instead-of-yield fs/jffs2/erase.c
--- a/fs/jffs2/erase.c~jffs2-use-cond_resched-instead-of-yield
+++ a/fs/jffs2/erase.c
@@ -151,7 +151,7 @@ int jffs2_erase_pending_blocks(struct jf
 		}
 
 		/* Be nice */
-		yield();
+		cond_resched();
 		mutex_lock(&c->erase_free_sem);
 		spin_lock(&c->erase_completion_lock);
 	}
_


From r61911 at freescale.com  Sat Oct  2 08:36:27 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Sat, 2 Oct 2010 20:36:27 +0800
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
	flash partitions
In-Reply-To: <20100920131907.GA2184@oksana.dev.rtsoft.ru>
References: <1284706869-12555-1-git-send-email-tie-fei.zang@freescale.com>
	<1284706869-12555-2-git-send-email-tie-fei.zang@freescale.com>
	<20100920131907.GA2184@oksana.dev.rtsoft.ru>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A256099@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Monday, September 20, 2010 21:19 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org; dedekind1 at gmail.com;
> akpm at linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> B11780; linuxppc-dev at ozlabs.org
> Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
> flash partitions
> 
> On Fri, Sep 17, 2010 at 03:01:08PM +0800, Roy Zang wrote:
> [...]
> > +static struct mutex fsl_elbc_nand_mutex;
> > +
> > +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
> >  {
> > -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > +	struct fsl_lbc_regs __iomem *lbc;
> >  	struct fsl_elbc_mtd *priv;
> >  	struct resource res;
> > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> 
> No need for = NULL.
Any harm? Or just personal habit or style? Can you explain about why?
Thanks.
Roy

From dedekind1 at gmail.com  Sat Oct  2 10:07:55 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:07:55 +0300
Subject: [patch 2/2] jffs2: use cond_resched() instead of yield()
In-Reply-To: <201010012116.o91LGSlt021122@imap1.linux-foundation.org>
References: <201010012116.o91LGSlt021122@imap1.linux-foundation.org>
Message-ID: <1286028475.32172.12.camel@brekeke>

On Fri, 2010-10-01 at 14:16 -0700, akpm at linux-foundation.org wrote:
> From: Wolfram Sang <w.sang at pengutronix.de>
> 
> yield() has different semantics meanwhile and even causes RT-kernels to
> BUG.  Replace the only appearance left in jffs2.
> 

This patch is also in my l2-mtd-2.6.git tree.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct  2 10:09:52 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:09:52 +0300
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
In-Reply-To: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>
References: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>
Message-ID: <1286028592.32172.14.camel@brekeke>

On Fri, 2010-10-01 at 14:16 -0700, akpm at linux-foundation.org wrote:
> From: Sudhakar Rajashekhara <sudhakar.raj at ti.com>
> 
> Implement a memory accessor interface in the MTD layer which enables the
> kernel to access flash data.
> 
> This patch adds two new members to the mtd_partition structure, a function
> handler which will be called during setup of the partition and an argument
> to be passed to this setup function.

This patch does not apply to my l2-mtd-2.6.git tree - many confilicts.
Sudhakar, you can refresh your patch against my tree and re-send:

http://git.infradead.org/users/dedekind/l2-mtd-2.6.git

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct  2 10:14:38 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:14:38 +0300
Subject: [PATCH] mkfs.jffs2: convert to xalloc.h helpers
In-Reply-To: <1285953030-19539-1-git-send-email-vapier@gentoo.org>
References: <1285953030-19539-1-git-send-email-vapier@gentoo.org>
Message-ID: <1286028878.32172.19.camel@brekeke>

On Fri, 2010-10-01 at 13:10 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  mkfs.jffs2.c |   13 +++----------
>  1 files changed, 3 insertions(+), 10 deletions(-)

Pushed to mtd-utils.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct  2 10:16:11 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:16:11 +0300
Subject: [PATCH 1/2] sumtool: convert to common.h helpers
In-Reply-To: <1285953088-19593-1-git-send-email-vapier@gentoo.org>
References: <1285953088-19593-1-git-send-email-vapier@gentoo.org>
Message-ID: <1286028971.32172.20.camel@brekeke>

On Fri, 2010-10-01 at 13:11 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  sumtool.c |  237 ++++++++++++++++++++----------------------------------------
>  1 files changed, 79 insertions(+), 158 deletions(-)
> 
> diff --git a/sumtool.c b/sumtool.c
> index d0e2a7b..51e4173 100644
> --- a/sumtool.c
> +++ b/sumtool.c

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct  2 10:17:02 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:17:02 +0300
Subject: [PATCH 2/2] sumtool/libfec: convert "()" to "(void)" in func defs
In-Reply-To: <1285953088-19593-2-git-send-email-vapier@gentoo.org>
References: <1285953088-19593-1-git-send-email-vapier@gentoo.org>
	<1285953088-19593-2-git-send-email-vapier@gentoo.org>
Message-ID: <1286029022.32172.21.camel@brekeke>

On Fri, 2010-10-01 at 13:11 -0400, Mike Frysinger wrote:
> Since these functions take no parameters, declare them as such.  The
> subtle difference here is that gcc allows (without warning) people to
> accidentally call funcs declared with "()" with arguments.  Using void
> makes sure that gcc will reject such typos at compile time.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct  2 10:19:58 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 02 Oct 2010 17:19:58 +0300
Subject: [PATCH] libmtd: make malloc failures fatal
In-Reply-To: <1285953190-19669-1-git-send-email-vapier@gentoo.org>
References: <1285953190-19669-1-git-send-email-vapier@gentoo.org>
Message-ID: <1286029198.32172.23.camel@brekeke>

On Fri, 2010-10-01 at 13:13 -0400, Mike Frysinger wrote:
> This converts libmtd to the common xalloc helpers and in doing so, makes
> memory allocation failures fatal rather than returning an error to the
> caller.  I think this is acceptable behavior.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  lib/libmtd.c        |   26 ++++++--------------------
>  lib/libmtd_legacy.c |    8 +-------
>  2 files changed, 7 insertions(+), 27 deletions(-)

I am not 100% sure this is a good idea, but probably for allocations it
is ok - they are so unlikely to fail, and if they do, we are screwed
anyway. But for other situation we should return errors, I think.

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dwmw2 at infradead.org  Sat Oct  2 10:44:32 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Sat, 02 Oct 2010 23:44:32 +0900
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
In-Reply-To: <1286028592.32172.14.camel@brekeke>
References: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>
	<1286028592.32172.14.camel@brekeke>
Message-ID: <1286030672.26080.2.camel@macbook.infradead.org>

On Sat, 2010-10-02 at 17:09 +0300, Artem Bityutskiy wrote:
> 
> > Implement a memory accessor interface in the MTD layer which enables
> the
> > kernel to access flash data.
> > 
> > This patch adds two new members to the mtd_partition structure, a
> function
> > handler which will be called during setup of the partition and an
> argument
> > to be passed to this setup function.
> 
> This patch does not apply to my l2-mtd-2.6.git tree

Wasn't there going to be a much nicer version of this patch coming
anyway?

-- 
dwmw2



From vapier at gentoo.org  Sat Oct  2 13:29:52 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 2 Oct 2010 13:29:52 -0400
Subject: [PATCH] libmtd: make malloc failures fatal
In-Reply-To: <1286029198.32172.23.camel@brekeke>
References: <1285953190-19669-1-git-send-email-vapier@gentoo.org>
	<1286029198.32172.23.camel@brekeke>
Message-ID: <AANLkTim8DMm6dYpW6Ot4yrR+m4XaywyTrk1m_n6k6ovX@mail.gmail.com>

On Sat, Oct 2, 2010 at 10:19, Artem Bityutskiy wrote:
> On Fri, 2010-10-01 at 13:13 -0400, Mike Frysinger wrote:
>> This converts libmtd to the common xalloc helpers and in doing so, makes
>> memory allocation failures fatal rather than returning an error to the
>> caller. ?I think this is acceptable behavior.
>>
>> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>> ---
>> ?lib/libmtd.c ? ? ? ?| ? 26 ++++++--------------------
>> ?lib/libmtd_legacy.c | ? ?8 +-------
>> ?2 files changed, 7 insertions(+), 27 deletions(-)
>
> I am not 100% sure this is a good idea, but probably for allocations it
> is ok - they are so unlikely to fail, and if they do, we are screwed
> anyway. But for other situation we should return errors, I think.

right, i'm only thinking of OOM errors should we simply die.  all
other errors should return.
-mike


From vapier at gentoo.org  Sat Oct  2 14:58:09 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat,  2 Oct 2010 14:58:09 -0400
Subject: [PATCH v2] jffs2reader: convert to common.h helpers
In-Reply-To: <1285953246-19729-1-git-send-email-vapier@gentoo.org>
References: <1285953246-19729-1-git-send-email-vapier@gentoo.org>
Message-ID: <1286045889-25811-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- fix a few thinkos in previous patch

 jffs2reader.c |   71 +++++++++++++++++---------------------------------------
 1 files changed, 22 insertions(+), 49 deletions(-)

diff --git a/jffs2reader.c b/jffs2reader.c
index 0cdff19..d5a3d95 100644
--- a/jffs2reader.c
+++ b/jffs2reader.c
@@ -77,6 +77,7 @@ BUGS:
 #include <sys/param.h>
 #include <dirent.h>
 #include <linux/jffs2.h>
+#include "common.h"
 
 #define SCRATCH_SIZE (5*1024*1024)
 
@@ -136,10 +137,8 @@ void putblock(char *b, size_t bsize, size_t * rsize,
 {
 	uLongf dlen = n->dsize;
 
-	if (n->isize > bsize || (n->offset + dlen) > bsize) {
-		fprintf(stderr, "File does not fit into buffer!\n");
-		exit(EXIT_FAILURE);
-	}
+	if (n->isize > bsize || (n->offset + dlen) > bsize)
+		errmsg_die("File does not fit into buffer!");
 
 	if (*rsize < n->isize)
 		bzero(b + *rsize, n->isize - *rsize);
@@ -163,8 +162,7 @@ void putblock(char *b, size_t bsize, size_t * rsize,
 			/* [DYN]RUBIN support required! */
 
 		default:
-			fprintf(stderr, "Unsupported compression method!\n");
-			exit(EXIT_FAILURE);
+			errmsg_die("Unsupported compression method!");
 	}
 
 	*rsize = n->isize;
@@ -188,7 +186,7 @@ struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n)
 
 	if (n->ino) {
 		if (dd == NULL) {
-			d = malloc(sizeof(struct dir));
+			d = xmalloc(sizeof(struct dir));
 			d->type = n->type;
 			memcpy(d->name, n->name, n->nsize);
 			d->nsize = n->nsize;
@@ -208,7 +206,7 @@ struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n)
 			}
 
 			if (dd->next == NULL) {
-				dd->next = malloc(sizeof(struct dir));
+				dd->next = xmalloc(sizeof(struct dir));
 				dd->next->type = n->type;
 				memcpy(dd->next->name, n->name, n->nsize);
 				dd->next->nsize = n->nsize;
@@ -344,7 +342,7 @@ void printdir(char *o, size_t size, struct dir *d, char *path, int recurse)
 		}
 		ri = find_raw_inode(o, size, d->ino);
 		if (!ri) {
-			fprintf(stderr, "bug: raw_inode missing!\n");
+			warnmsg("bug: raw_inode missing!");
 			d = d->next;
 			continue;
 		}
@@ -379,11 +377,7 @@ void printdir(char *o, size_t size, struct dir *d, char *path, int recurse)
 
 		if (d->type == DT_DIR && recurse) {
 			char *tmp;
-			tmp = malloc(BUFSIZ);
-			if (!tmp) {
-				fprintf(stderr, "memory exhausted\n");
-				exit(EXIT_FAILURE);
-			}
+			tmp = xmalloc(BUFSIZ);
 			sprintf(tmp, "%s/%s", path, d->name);
 			lsdir(o, size, tmp, recurse);		/* Go recursive */
 			free(tmp);
@@ -817,11 +811,8 @@ void lsdir(char *o, size_t size, char *path, int recurse)
 	dd = resolvepath(o, size, 1, path, &ino);
 
 	if (ino == 0 ||
-			(dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR)) {
-		fprintf(stderr, "%s: %s: No such file or directory\n",
-				PROGRAM_NAME, path);
-		exit(EXIT_FAILURE);
-	}
+			(dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR))
+		errmsg_die("%s: No such file or directory", path);
 
 	d = collectdir(o, size, ino, d);
 	printdir(o, size, d, path, recurse);
@@ -848,15 +839,11 @@ void catfile(char *o, size_t size, char *path, char *b, size_t bsize,
 
 	dd = resolvepath(o, size, 1, path, &ino);
 
-	if (ino == 0) {
-		fprintf(stderr, "%s: No such file or directory\n", path);
-		exit(EXIT_FAILURE);
-	}
+	if (ino == 0)
+		errmsg_die("%s: No such file or directory", path);
 
-	if (dd == NULL || dd->type != DT_REG) {
-		fprintf(stderr, "%s: Not a regular file\n", path);
-		exit(EXIT_FAILURE);
-	}
+	if (dd == NULL || dd->type != DT_REG)
+		errmsg_die("%s: Not a regular file", path);
 
 	ri = find_raw_inode(o, size, ino);
 	putblock(b, bsize, rsize, ri);
@@ -896,36 +883,22 @@ int main(int argc, char **argv)
 	}
 
 	fd = open(argv[optind], O_RDONLY);
-	if (fd == -1) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(2);
-	}
+	if (fd == -1)
+		sys_errmsg_die("%s", argv[optind]);
 
-	if (fstat(fd, &st)) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(3);
-	}
+	if (fstat(fd, &st))
+		sys_errmsg_die("%s", argv[optind]);
 
-	buf = malloc((size_t) st.st_size);
-	if (buf == NULL) {
-		fprintf(stderr, "%s: memory exhausted\n", argv[optind]);
-		exit(4);
-	}
+	buf = xmalloc((size_t) st.st_size);
 
-	if (read(fd, buf, st.st_size) != (ssize_t) st.st_size) {
-		fprintf(stderr, "%s: %s\n", argv[optind], strerror(errno));
-		exit(5);
-	}
+	if (read(fd, buf, st.st_size) != (ssize_t) st.st_size)
+		sys_errmsg_die("%s", argv[optind]);
 
 	if (dir)
 		lsdir(buf, st.st_size, dir, recurse);
 
 	if (file) {
-		scratch = malloc(SCRATCH_SIZE);
-		if (scratch == NULL) {
-			fprintf(stderr, "%s: memory exhausted\n", argv[optind]);
-			exit(6);
-		}
+		scratch = xmalloc(SCRATCH_SIZE);
 
 		catfile(buf, st.st_size, file, scratch, SCRATCH_SIZE, &ssize);
 		free(scratch);
-- 
1.7.3.1



From akpm at linux-foundation.org  Sat Oct  2 15:09:52 2010
From: akpm at linux-foundation.org (Andrew Morton)
Date: Sat, 2 Oct 2010 12:09:52 -0700
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
In-Reply-To: <1286028592.32172.14.camel@brekeke>
References: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>
	<1286028592.32172.14.camel@brekeke>
Message-ID: <20101002120952.e34b6d65.akpm@linux-foundation.org>

On Sat, 02 Oct 2010 17:09:52 +0300 Artem Bityutskiy <dedekind1 at gmail.com> wrote:

> On Fri, 2010-10-01 at 14:16 -0700, akpm at linux-foundation.org wrote:
> > From: Sudhakar Rajashekhara <sudhakar.raj at ti.com>
> > 
> > Implement a memory accessor interface in the MTD layer which enables the
> > kernel to access flash data.
> > 
> > This patch adds two new members to the mtd_partition structure, a function
> > handler which will be called during setup of the partition and an argument
> > to be passed to this setup function.
> 
> This patch does not apply to my l2-mtd-2.6.git tree - many confilicts.

It applies against linux-next.

For heavens sake guys, please fix this.



From akpm at linux-foundation.org  Sat Oct  2 15:10:39 2010
From: akpm at linux-foundation.org (Andrew Morton)
Date: Sat, 2 Oct 2010 12:10:39 -0700
Subject: [patch 2/2] jffs2: use cond_resched() instead of yield()
In-Reply-To: <1286028475.32172.12.camel@brekeke>
References: <201010012116.o91LGSlt021122@imap1.linux-foundation.org>
	<1286028475.32172.12.camel@brekeke>
Message-ID: <20101002121039.5e0676f6.akpm@linux-foundation.org>

On Sat, 02 Oct 2010 17:07:55 +0300 Artem Bityutskiy <dedekind1 at gmail.com> wrote:

> On Fri, 2010-10-01 at 14:16 -0700, akpm at linux-foundation.org wrote:
> > From: Wolfram Sang <w.sang at pengutronix.de>
> > 
> > yield() has different semantics meanwhile and even causes RT-kernels to
> > BUG.  Replace the only appearance left in jffs2.
> > 
> 
> This patch is also in my l2-mtd-2.6.git tree.

And I'll keep sending it and you'll keep telling me it's in your tree
until this situation gets fixed.


From viresh.kumar at st.com  Mon Oct  4 02:01:05 2010
From: viresh.kumar at st.com (viresh kumar)
Date: Mon, 4 Oct 2010 11:31:05 +0530
Subject: [PATCH V2 62/69] ST SPEAr: Appending spear3** with global
	structures
In-Reply-To: <AANLkTi=xNoG2T1Q2JqB7TH+O7AjW++UnSt1Q85VgPbzp@mail.gmail.com>
References: <cover.1285933331.git.viresh.kumar@st.com>	<f4787f6021bf3a8c009595749894332c05e656df.1285933332.git.viresh.kumar@st.com>
	<AANLkTi=xNoG2T1Q2JqB7TH+O7AjW++UnSt1Q85VgPbzp@mail.gmail.com>
Message-ID: <4CA96DA1.7040301@st.com>

On 10/01/2010 09:51 PM, viresh kumar wrote:
> Hello everybody,
> 
> I have used an latest patch on git for sending this patch series. I
> think there is some bug
> there, due to which all of you have received some mails which are not
> intended for all of you.
> There was a bugfix in git which enables to send mail to "recipients
> mentioned in TO field", of patch
> itself.
> 
> After creating patches (with git format-patch ---), i have added To
> and CC lists in patches.
> But when i sent patches the TO field was carried away in later patches
> too. So due to this
> all patches send after rtc patches have following recipients added:
> rtc-linux at googlegroups.com,
> a.zummo at towertech.it. Similarly for other patches too.
> 

Hello,

Should i resend my patches (with correct list of people in To:)??

-- 
viresh


From u.kleine-koenig at pengutronix.de  Mon Oct  4 02:58:02 2010
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Mon, 4 Oct 2010 08:58:02 +0200
Subject: [PATCH] mtd: mxc_nand: do not depend on disabling the irq in
	the interrupt handler
In-Reply-To: <20100929072843.GC23406@pengutronix.de>
References: <1285054802-21388-1-git-send-email-s.hauer@pengutronix.de>
	<1285054802-21388-2-git-send-email-s.hauer@pengutronix.de>
	<1285240612.29268.76.camel@localhost>
	<20100929072843.GC23406@pengutronix.de>
Message-ID: <20101004065802.GA13948@pengutronix.de>

On Wed, Sep 29, 2010 at 09:28:43AM +0200, Sascha Hauer wrote:
> David,
> 
> On Thu, Sep 23, 2010 at 02:16:52PM +0300, Artem Bityutskiy wrote:
> > On Tue, 2010-09-21 at 09:40 +0200, Sascha Hauer wrote:
> > > This patch reverts the driver to enabling/disabling the NFC interrupt
> > > mask rather than enabling/disabling the system interrupt. This cleans
> > > up the driver so that it doesn't rely on interrupts being disabled
> > > within the interrupt handler.
> > > For i.MX21 we keep the current behaviour, that is calling
> > > enable_irq/disable_irq_nosync to enable/disable interrupts.
> > > This patch is based on earlier work by John Ogness.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > > Acked-by: John Ogness <john.ogness at linutronix.de>
> > > Tested-by: John Ogness <john.ogness at linutronix.de>
> > 
> > I've created l2-mtd-2.6.git/for-2.6.36 branch, pushed your patch there,
> > pinged dwmw2 for you. I do not give you any guarantees this will reach
> > 2.6.36, you have to ping dwmw2.
> 
> Any chance to get this in? The mxc-nand driver is nonfunctional at the
> moment and 2.6.36 is getting closer.

Acked-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>

(for the patch and the request to get it in before 2.6.36.)

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From s-ghorai at ti.com  Mon Oct  4 03:29:29 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Mon, 4 Oct 2010 12:59:29 +0530
Subject: Issue : jffs2 and ecc layout
In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B03560990E3@dbde02.ent.ti.com>
References: <2A3DCF3DA181AD40BDE86A3150B27B6B03560990E3@dbde02.ent.ti.com>
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B0356594397@dbde02.ent.ti.com>



> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> owner at vger.kernel.org] On Behalf Of Ghorai, Sukumar
> Sent: Tuesday, September 28, 2010 6:17 PM
> To: linux-mtd at lists.infradead.org
> Cc: linux-omap at vger.kernel.org
> Subject: Issue : jffs2 and ecc layout
> 
> Hi,
> I was using the following ecc layout which is not working to mount the
> jffs2 File-system. I was in 2.6.32 kernel and working; but same layout is
> not working with latest 2.6 kernel.
> 
> Observation is that - no read request issued to the driver (say omap2.c).
> 
> # mount -t jffs2 /dev/mtdblock4 /mnt/nand
> [?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes, read
> 0 bytes, error -22
> mount: Mounting /dev/mtdblock4 on /mnt/nand failed: Input/output error
> 
> # dmesg
> <3>[?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes,
> read 0 bytes, error -22
> 
> Code:
> ?178 static struct nand_ecclayout hw_x16_romcode_oob_64 = {
> ?179???????? .eccbytes = 12,
> ?180???????? .eccpos = {
> ?181???????????????????? 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
> ?182?????????????????? },
> ?183???????? .oobfree = {
> ?184????????????????????? ???{.offset = 14,
> ?185????????????????????????? .length = 50}
> ?186??????????????????? }
> ?187 };
> 
> ?1188????????????? info->nand.ecc.layout = &hw_x16_romcode_oob_64;
[Ghorai] 
Does anyone using similar layout for Jffs2? i.e. ECC store at beginning of the spare area?


> 
> Regards,
> Ghorai
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From dedekind1 at gmail.com  Mon Oct  4 03:37:29 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 04 Oct 2010 10:37:29 +0300
Subject: [PATCH v2] jffs2reader: convert to common.h helpers
In-Reply-To: <1286045889-25811-1-git-send-email-vapier@gentoo.org>
References: <1285953246-19729-1-git-send-email-vapier@gentoo.org>
	<1286045889-25811-1-git-send-email-vapier@gentoo.org>
Message-ID: <1286177849.11684.76.camel@localhost>

On Sat, 2010-10-02 at 14:58 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v2
> 	- fix a few thinkos in previous patch
> 
>  jffs2reader.c |   71 +++++++++++++++++---------------------------------------
>  1 files changed, 22 insertions(+), 49 deletions(-)

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Oct  4 03:39:05 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 04 Oct 2010 10:39:05 +0300
Subject: [PATCH] nand: omap2: Missing arg to gpmc_prefetch_reset()
In-Reply-To: <1285364702-13922-1-git-send-email-loic.minier@linaro.org>
References: <1285364702-13922-1-git-send-email-loic.minier@linaro.org>
Message-ID: <1286177945.11684.77.camel@localhost>

On Fri, 2010-09-24 at 23:45 +0200, Lo?c Minier wrote:
> Fix missing cs arg to gpmc_prefetch_reset() when
> CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y which caused a build failure since
> 948d38e799f0ab87cf8ed9113fcdaaee61acf321:
> drivers/mtd/nand/omap2.c: In function 'omap_nand_dma_transfer':
> drivers/mtd/nand/omap2.c:416: error: too few arguments to function 'gpmc_prefetch_reset'
> 
> Signed-off-by: Lo?c Minier <loic.minier at linaro.org>
> ---
>  drivers/mtd/nand/omap2.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)

FYI, a similar patch is already in Linus' tree, so I'm dropping it from
my tree:

commit f12f662f29d5801e598c6bb4a71e54b2de218f72
Author: Daniel J Blueman <daniel.blueman at gmail.com>
Date:   Wed Sep 29 21:01:55 2010 +0100

    fix OMAP2 MTD build failure
    
    Fix build failure from recent interface change and merge.
    
    Tested on OMAP3430.
    
    Signed-off-by: Daniel J Blueman <daniel.blueman at gmail.com>
    Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From lool at dooz.org  Mon Oct  4 04:52:22 2010
From: lool at dooz.org (=?iso-8859-1?Q?Lo=EFc?= Minier)
Date: Mon, 4 Oct 2010 10:52:22 +0200
Subject: [PATCH] nand: omap2: Missing arg to gpmc_prefetch_reset()
In-Reply-To: <1286177945.11684.77.camel@localhost>
References: <1285364702-13922-1-git-send-email-loic.minier@linaro.org>
	<1286177945.11684.77.camel@localhost>
Message-ID: <20101004085222.GC4426@bee.dooz.org>

On Mon, Oct 04, 2010, Artem Bityutskiy wrote:
> FYI, a similar patch is already in Linus' tree, so I'm dropping it from
> my tree

 Ok, thanks; is there something I should have done to get this patch
 into Linus tree?

-- 
Lo?c Minier


From dedekind1 at gmail.com  Mon Oct  4 04:57:21 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 04 Oct 2010 11:57:21 +0300
Subject: [PATCH] nand: omap2: Missing arg to gpmc_prefetch_reset()
In-Reply-To: <20101004085222.GC4426@bee.dooz.org>
References: <1285364702-13922-1-git-send-email-loic.minier@linaro.org>
	<1286177945.11684.77.camel@localhost>
	<20101004085222.GC4426@bee.dooz.org>
Message-ID: <1286182641.11684.100.camel@localhost>

On Mon, 2010-10-04 at 10:52 +0200, Lo?c Minier wrote:
> On Mon, Oct 04, 2010, Artem Bityutskiy wrote:
> > FYI, a similar patch is already in Linus' tree, so I'm dropping it from
> > my tree
> 
>  Ok, thanks; is there something I should have done to get this patch
>  into Linus tree?

No, you did everything right. I guess that guy was just faster than you.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From matthieu.castet at parrot.com  Mon Oct  4 09:12:00 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Mon, 4 Oct 2010 15:12:00 +0200
Subject: UBI/UBIFS interrupted write page handling
In-Reply-To: <1285660934.2437.44.camel@localhost>
References: <4C88DDD5.4060507@parrot.com>	 <1284054669.11335.21.camel@brekeke>
	<1285006478.1762.1.camel@brekeke>	 <4C9B7CD8.4070806@parrot.com>,
	<1285266914.1766.1.camel@brekeke>	
	<F5C24FC168F95048BB6B9E0B13EB33152BA6F5304E@DIAMANT.xi-lite.lan>	
	<1285523911.1776.9.camel@brekeke>
	<1285657088.2437.23.camel@localhost>	 <4CA19DAE.7030402@parrot.com>
	<1285660934.2437.44.camel@localhost>
Message-ID: <4CA9D2A0.6010508@parrot.com>

Artem Bityutskiy a ?crit :
> On Tue, 2010-09-28 at 09:47 +0200, Matthieu CASTET wrote:
>> Artem Bityutskiy a ?crit :
>>> On Sun, 2010-09-26 at 20:58 +0300, Artem Bityutskiy wrote:
>>>
>> That's better : interrupt erased page are not put anymore in corrupted list.
>> But I have problem with interrupt write :
>> this night the test crashed [1].
> 
> Yeah, this should be fixed by forcing LEB refresh for the last LEBs of
> journal heads. This problem exists long time. I'll work on this and send
> you patches.
UBI will need also some patch.
For example in case of wear leveling, ubi could move a leb from a peb to 
another and the write can be interrupted.


> 
> We also have the outstanding gc_lnum problem - did you see it in new
> ubifs?
No, I find the cause of that. I was missing a patch in my backport tree.

Matthieu


From sudhakar.raj at ti.com  Mon Oct  4 10:28:37 2010
From: sudhakar.raj at ti.com (Sudhakar Rajashekhara)
Date: Mon, 4 Oct 2010 19:58:37 +0530
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
In-Reply-To: <1286030672.26080.2.camel@macbook.infradead.org>
References: <201010012116.o91LGRGn021118@imap1.linux-foundation.org>	
	<1286028592.32172.14.camel@brekeke>
	<1286030672.26080.2.camel@macbook.infradead.org>
Message-ID: <004b01cb63d0$6ee7e630$4cb7b290$@raj@ti.com>

All,

On Sat, Oct 02, 2010 at 20:14:32, David Woodhouse wrote:
> On Sat, 2010-10-02 at 17:09 +0300, Artem Bityutskiy wrote:
> > 
> > > Implement a memory accessor interface in the MTD layer which enables
> > the
> > > kernel to access flash data.
> > > 
> > > This patch adds two new members to the mtd_partition structure, a
> > function
> > > handler which will be called during setup of the partition and an
> > argument
> > > to be passed to this setup function.
> > 
> > This patch does not apply to my l2-mtd-2.6.git tree
> 
> Wasn't there going to be a much nicer version of this patch coming
> anyway?
> 

This patch can be dropped. Please see the discussion at [1] regarding this.

[1] http://lists.infradead.org/pipermail/linux-mtd/2010-August/031483.html

Thanks,
Sudhakar




From scottwood at freescale.com  Mon Oct  4 11:38:13 2010
From: scottwood at freescale.com (Scott Wood)
Date: Mon, 4 Oct 2010 10:38:13 -0500
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect
	nand flash partitions
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A256099@zch01exm23.fsl.freescale.net>
References: <20100920131907.GA2184@oksana.dev.rtsoft.ru>
	<3850A844E6A3854C827AC5C0BEC7B60A256099@zch01exm23.fsl.freescale.net>
Message-ID: <20101004103813.14d04956@udp111988uds.am.freescale.net>

On Sat, 2 Oct 2010 05:36:27 -0700
"Zang Roy-R61911" <r61911 at freescale.com> wrote:

> 
> 
> > -----Original Message-----
> > From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> > Sent: Monday, September 20, 2010 21:19 PM
> > To: Zang Roy-R61911
> > Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org; dedekind1 at gmail.com;
> > akpm at linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> > B11780; linuxppc-dev at ozlabs.org
> > Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
> > flash partitions
> > 
> > On Fri, Sep 17, 2010 at 03:01:08PM +0800, Roy Zang wrote:
> > [...]
> > > +static struct mutex fsl_elbc_nand_mutex;
> > > +
> > > +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
> > >  {
> > > -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > > +	struct fsl_lbc_regs __iomem *lbc;
> > >  	struct fsl_elbc_mtd *priv;
> > >  	struct resource res;
> > > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> > 
> > No need for = NULL.
> Any harm? Or just personal habit or style? Can you explain about why?

Besides not wanting superfluous code on general principle, it could
hide a bug if in the future the real initialization is missing on some
code path.  It would become a runtime NULL dereference rather than a
compiler warning.

-Scott



From tony at atomide.com  Mon Oct  4 22:14:56 2010
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 4 Oct 2010 19:14:56 -0700
Subject: [GIT PULL] omap2 sparse fixes
In-Reply-To: <E0D41E29EB0DAC4E9F3FF173962E9E9402DB7FE911@dbde02.ent.ti.com>
References: <20100923225851.GR4211@atomide.com>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DB3F859E@dbde02.ent.ti.com>
	<20100925001914.GO4211@atomide.com>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DB3F917C@dbde02.ent.ti.com>
	<20100928152139.GB3117@atomide.com>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DB3F94C9@dbde02.ent.ti.com>
	<20100928183157.GH3117@atomide.com>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DB7FE8F9@dbde02.ent.ti.com>
	<20100929215635.GC3117@atomide.com>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DB7FE911@dbde02.ent.ti.com>
Message-ID: <20101005021455.GE3117@atomide.com>

* G, Manjunath Kondaiah <manjugk at ti.com> [100929 16:38]:
> 
> Patches are same except pulling out twl and driver patches from
> the series.
> 
> Paul's comment is addressed and changes are pushed to git branch.
> Build tested with omap3_defconfig and boot tested with beagle board.

Thanks, pulling this into omap-for-linus.

Tony
 
> The following changes since commit 899611ee7d373e5eeda08e9a8632684e1ebbbf00:
>   Linus Torvalds (1):
>         Linux 2.6.36-rc6
> 
> are available in the git repository at:
> 
>   git://dev.omapzoom.org/pub/scm/manju/kernel-omap3-dev.git omap_sparse_fixesv2
> 
> G, Manjunath Kondaiah (7):
>       OMAP: mach-omap2: Fix incorrect assignment warnings
>       OMAP: mach-omap2: Fix static declaration warnings
>       OMAP2plus: Fix static function warnings
>       OMAP: mach-omap2: Fix miscellaneous sparse warnings
>       OMAP: plat-omap: Fix static function warnings
>       OMAP: Convert write/read functions to raw read/write
>       OMAP3: Keypad: Fix incorrect type initializer
> 
> -Manjunath
> 


From krellboy at gmail.com  Tue Oct  5 05:15:37 2010
From: krellboy at gmail.com (Aaron Nabil)
Date: Tue, 5 Oct 2010 02:15:37 -0700
Subject: questions about inval_cache_and_wait_for_operation
Message-ID: <AANLkTinZLNERwwQ2xZASRzVs7+ny-ZsTO3Gm8ceh8kVE@mail.gmail.com>

I apologize in advance for my newbie-ness and potential lack of
critical missing information, please correct me off-list and I will do
better.

I'm trying to fix a lock-up problem I'm seeing with jffs2, we run the
system with a cpu-hog for 8 hrs and somewhere between the GC thread
and sync the filesystems lock up.  I can supply more details about
this but I wanted to have all of my ducks in a row first.

While looking for the hang I ran across some code in
inval_cache_and_wait_for_operation I don't understand, and since it's
very close to the problem code I thought I'd ask.


First question....



        unsigned int timeo, sleep_time, reset_timeo;

( . . .)

        sleep_time = chip_op_time / 2;

        for (;;) {

( . . .)

                /* OK Still waiting. Drop the lock, wait a while and retry. */
                spin_unlock(chip->mutex);
                if (sleep_time >= 1000000/HZ) {
                        /*
                         * Half of the normal delay still remaining
                         * can be performed with a sleeping delay instead
                         * of busy waiting.
                         */
                        msleep(sleep_time/1000);
                        timeo -= sleep_time;
                        sleep_time = 1000000/HZ;
                } else {
                        udelay(1);
                        cond_resched();
                        timeo--;
                }

( . . . )
         }


If the execution path EVER takes the (sleep_time >= 1000000/HZ)
branch, it will ALWAYS take that branch every iteration thru the for
loop because the last statement sleep_time = 1000000/HZ sets
sleep_time explicitly to the value which is being tested for as
greater than OR EQUAL to.  Sleep_time is not otherwise changed
elsewhere in the loop.



Second question....

        unsigned int timeo, sleep_time, reset_timeo;

( . . . )

        timeo = chip_op_time_max;
        if (!timeo)
                timeo = 500000;

        sleep_time = chip_op_time / 2;

( . . .)


        for (;;) {

( . . . )

                if (!timeo) {
            // test if timeo is exactly 0
                        map_write(map, CMD(0x70), cmd_adr);
                        chip->state = FL_STATUS;
                        return -ETIME;
                }

                /* OK Still waiting. Drop the lock, wait a while and retry. */
                spin_unlock(chip->mutex);
                if (sleep_time >= 1000000/HZ) {
                        /*
                         * Half of the normal delay still remaining
                         * can be performed with a sleeping delay instead
                         * of busy waiting.
                         */
                        msleep(sleep_time/1000);
                        timeo -= sleep_time;
     //  timeo can underflow
                        sleep_time = 1000000/HZ;
                } else {
                        udelay(1);
                        cond_resched();
                        timeo--;
          // timeo will always hit 0 before underflow
                }

( . . .)


As timeo is an unsigned int and the timeo test is for exactly 0, the
timeo -= sleep_time can underflow and wrap timeo around. If this code
branch was executed only once and sleep_time < timeo this won't be a
problem, but, see first problem above.


Thanks in advance for extending me newbie latitude.


Aaron


From glecerf at gmail.com  Tue Oct  5 05:38:46 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 5 Oct 2010 11:38:46 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <DB610A768D2B46C7A888B2DBECEBEC79@THOR>
References: <E73F778B634944A0B8D4333B7BD012E4@THOR>
	<AANLkTin2b-QovauogfjMZP_7KeChY5oWsMPFBAiC2ERE@mail.gmail.com>
	<74A5BE60138147F696E151AACD52EDEE@THOR>
	<AANLkTintkdKGpkUGMkgGbVK6Pb3cttspwnuPQR=DJxnm@mail.gmail.com>
	<D3A375B91F5944B38630B07214914DF8@THOR>
	<AANLkTinotjfB26VPmF7_vx8M1kX5cYMzygFMk8X6exww@mail.gmail.com>
	<341EADF720C14B4F86C63204D9C60723@THOR>
	<AANLkTikXbKZLFOCBDkrwgVPJEYTwF88xBtYFnwaTQH+5@mail.gmail.com>
	<6E1A182A06054C5A99BD3C0D3202C24F@THOR>
	<AANLkTi=qZ_wYcHHfKjaJsvf-ODgnECDOTEHmuorpA7K2@mail.gmail.com>
	<DB610A768D2B46C7A888B2DBECEBEC79@THOR>
Message-ID: <AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com>

2010/9/24 Fl?vio Silveira <fggs at terra.com.br>:
> Hi Guillaume,
>
> ?I tried another router firmware with kernel 2.6.34.5, downloaded
> mtd-2.6.git and pasted chips folder and "linux/mtd" headers, applied your
> last patch and kernel compiled fine.
> ?I've also enabled debug in kernel and cfi. Should I paste console log in
> message body or should I attach a file with the log?
> ?I had an error but I don't know if it's related to mtd or the firmware,
> because my router is not officialy supported.

Any news on this one ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From fggs at terra.com.br  Tue Oct  5 06:07:52 2010
From: fggs at terra.com.br (=?UTF-8?Q?Fl=C3=A1vio_Silveira?=)
Date: Tue, 5 Oct 2010 07:07:52 -0300
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com>
References: <E73F778B634944A0B8D4333B7BD012E4@THOR>
	<AANLkTin2b-QovauogfjMZP_7KeChY5oWsMPFBAiC2ERE@mail.gmail.com><74A5BE60138147F696E151AACD52EDEE@THOR><AANLkTintkdKGpkUGMkgGbVK6Pb3cttspwnuPQR=DJxnm@mail.gmail.com><D3A375B91F5944B38630B07214914DF8@THOR><AANLkTinotjfB26VPmF7_vx8M1kX5cYMzygFMk8X6exww@mail.gmail.com><341EADF720C14B4F86C63204D9C60723@THOR><AANLkTikXbKZLFOCBDkrwgVPJEYTwF88xBtYFnwaTQH+5@mail.gmail.com><6E1A182A06054C5A99BD3C0D3202C24F@THOR><AANLkTi=qZ_wYcHHfKjaJsvf-ODgnECDOTEHmuorpA7K2@mail.gmail.com><DB610A768D2B46C7A888B2DBECEBEC79@THOR>
	<AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com>
Message-ID: <8129711D4006470194ABF97D154047CF@THOR>

Actually yes, I applied your patch to kernel 2.6.35.4 and it detects the 
chip.
I just need to test without your patch to see the difference.

My problem is that dd-wrt an old kernel (2.6.24) and I couldn't port all 
fixes
and openwrt doesn't support my router's lan switch, but I can send you the 
logs if you want.

Thanks for your feedback on this


----- Original Message ----- 
From: "Guillaume LECERF" <glecerf at gmail.com>
To: "Fl?vio Silveira" <fggs at terra.com.br>
Cc: <linux-mtd at lists.infradead.org>
Sent: Tuesday, October 05, 2010 6:38 AM
Subject: Re: [Help] SST39VF6401B Support


2010/9/24 Fl?vio Silveira <fggs at terra.com.br>:
> Hi Guillaume,
>
> I tried another router firmware with kernel 2.6.34.5, downloaded
> mtd-2.6.git and pasted chips folder and "linux/mtd" headers, applied your
> last patch and kernel compiled fine.
> I've also enabled debug in kernel and cfi. Should I paste console log in
> message body or should I attach a file with the log?
> I had an error but I don't know if it's related to mtd or the firmware,
> because my router is not officialy supported.

Any news on this one ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org



From glecerf at gmail.com  Tue Oct  5 06:12:48 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 5 Oct 2010 12:12:48 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <8129711D4006470194ABF97D154047CF@THOR>
References: <E73F778B634944A0B8D4333B7BD012E4@THOR>
	<AANLkTin2b-QovauogfjMZP_7KeChY5oWsMPFBAiC2ERE@mail.gmail.com>
	<74A5BE60138147F696E151AACD52EDEE@THOR>
	<AANLkTintkdKGpkUGMkgGbVK6Pb3cttspwnuPQR=DJxnm@mail.gmail.com>
	<D3A375B91F5944B38630B07214914DF8@THOR>
	<AANLkTinotjfB26VPmF7_vx8M1kX5cYMzygFMk8X6exww@mail.gmail.com>
	<341EADF720C14B4F86C63204D9C60723@THOR>
	<AANLkTikXbKZLFOCBDkrwgVPJEYTwF88xBtYFnwaTQH+5@mail.gmail.com>
	<6E1A182A06054C5A99BD3C0D3202C24F@THOR>
	<AANLkTi=qZ_wYcHHfKjaJsvf-ODgnECDOTEHmuorpA7K2@mail.gmail.com>
	<DB610A768D2B46C7A888B2DBECEBEC79@THOR>
	<AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com>
	<8129711D4006470194ABF97D154047CF@THOR>
Message-ID: <AANLkTim_eEw+uR+Yb87XHN9C-kLaBhmD-RP5ZOW_Dz-n@mail.gmail.com>

2010/10/5 Fl?vio Silveira <fggs at terra.com.br>:
> Actually yes, I applied your patch to kernel 2.6.35.4 and it detects the
> chip.
> I just need to test without your patch to see the difference.

As soon as you confirm me that the patch is indeed needed, I'll send
it for inclusion.

> My problem is that dd-wrt an old kernel (2.6.24) and I couldn't port all
> fixes
> and openwrt doesn't support my router's lan switch, but I can send you the
> logs if you want.

What is the exact reference of your router ?
Did you tried to ask on the OpenWRT mailing list ?

> Thanks for your feedback on this

No problem ;)

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From bigeasy at linutronix.de  Tue Oct  5 06:41:01 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Tue, 5 Oct 2010 12:41:01 +0200
Subject: [PATCH] mtd/nand.h: cleanups
Message-ID: <20101005104101.GA18714@www.tglx.de>

- *var instead of * var
- proper multiline comment
- func(args) instead of func (args)
- 80 lines

So from
|total: 2 errors, 37 warnings, 654 lines checked
we got to one warning.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 include/linux/mtd/nand.h |  155 +++++++++++++++++++++++++++++-----------------
 1 files changed, 99 insertions(+), 56 deletions(-)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 0238665..acd0b50 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -27,15 +27,17 @@
 struct mtd_info;
 struct nand_flash_dev;
 /* Scan and identify a NAND device */
-extern int nand_scan (struct mtd_info *mtd, int max_chips);
-/* Separate phases of nand_scan(), allowing board driver to intervene
- * and override command or ECC setup according to flash type */
+extern int nand_scan(struct mtd_info *mtd, int max_chips);
+/*
+ * Separate phases of nand_scan(), allowing board driver to intervene
+ * and override command or ECC setup according to flash type.
+ */
 extern int nand_scan_ident(struct mtd_info *mtd, int max_chips,
 			   struct nand_flash_dev *table);
 extern int nand_scan_tail(struct mtd_info *mtd);
 
 /* Free resources held by the NAND device */
-extern void nand_release (struct mtd_info *mtd);
+extern void nand_release(struct mtd_info *mtd);
 
 /* Internal helper for board drivers which need to override command function */
 extern void nand_wait_ready(struct mtd_info *mtd);
@@ -49,7 +51,8 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 /* The maximum number of NAND chips in an array */
 #define NAND_MAX_CHIPS		8
 
-/* This constant declares the max. oobsize / page, which
+/*
+ * This constant declares the max. oobsize / page, which
  * is supported now. If you add a chip with bigger oobsize/page
  * adjust this accordingly.
  */
@@ -153,9 +156,10 @@ typedef enum {
 #define NAND_GET_DEVICE		0x80
 
 
-/* Option constants for bizarre disfunctionality and real
-*  features
-*/
+/*
+ * Option constants for bizarre disfunctionality and real
+ * features.
+ */
 /* Chip can not auto increment pages */
 #define NAND_NO_AUTOINCR	0x00000001
 /* Buswitdh is 16 bit */
@@ -166,19 +170,27 @@ typedef enum {
 #define NAND_CACHEPRG		0x00000008
 /* Chip has copy back function */
 #define NAND_COPYBACK		0x00000010
-/* AND Chip which has 4 banks and a confusing page / block
- * assignment. See Renesas datasheet for further information */
+/*
+ * AND Chip which has 4 banks and a confusing page / block
+ * assignment. See Renesas datasheet for further information.
+ */
 #define NAND_IS_AND		0x00000020
-/* Chip has a array of 4 pages which can be read without
- * additional ready /busy waits */
+/*
+ * Chip has a array of 4 pages which can be read without
+ * additional ready /busy waits.
+ */
 #define NAND_4PAGE_ARRAY	0x00000040
-/* Chip requires that BBT is periodically rewritten to prevent
+/*
+ * Chip requires that BBT is periodically rewritten to prevent
  * bits from adjacent blocks from 'leaking' in altering data.
- * This happens with the Renesas AG-AND chips, possibly others.  */
+ * This happens with the Renesas AG-AND chips, possibly others.
+ */
 #define BBT_AUTO_REFRESH	0x00000080
-/* Chip does not require ready check on read. True
+/*
+ * Chip does not require ready check on read. True
  * for all large page devices, as they do not support
- * autoincrement.*/
+ * autoincrement.
+ */
 #define NAND_NO_READRDY		0x00000100
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE	0x00000200
@@ -213,8 +225,10 @@ typedef enum {
 #define NAND_USE_FLASH_BBT	0x00010000
 /* This option skips the bbt scan during initialization. */
 #define NAND_SKIP_BBTSCAN	0x00020000
-/* This option is defined if the board driver allocates its own buffers
-   (e.g. because it needs them DMA-coherent */
+/*
+ * This option is defined if the board driver allocates its own buffers
+ * (e.g. because it needs them DMA-coherent).
+ */
 #define NAND_OWN_BUFFERS	0x00040000
 /* Chip may not exist, so silence any errors in scan */
 #define NAND_SCAN_SILENT_NODEV	0x00080000
@@ -304,8 +318,9 @@ struct nand_onfi_params {
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
  * @active:		the mtd device which holds the controller currently
- * @wq:			wait queue to sleep on if a NAND operation is in progress
- *                      used instead of the per chip wait queue when a hw controller is available
+ * @wq:			wait queue to sleep on if a NAND operation is in
+ *			progress used instead of the per chip wait queue
+ *			when a hw controller is available.
  */
 struct nand_hw_control {
 	spinlock_t	 lock;
@@ -329,9 +344,11 @@ struct nand_hw_control {
  * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
  * @read_page_raw:	function to read a raw page without ECC
  * @write_page_raw:	function to write a raw page without ECC
- * @read_page:	function to read a page according to the ecc generator requirements
+ * @read_page:	function to read a page according to the ecc generator
+ *		requirements.
  * @read_subpage:	function to read parts of the page covered by ECC.
- * @write_page:	function to write a page according to the ecc generator requirements
+ * @write_page:	function to write a page according to the ecc generator
+ *		requirements.
  * @read_oob:	function to read chip OOB data
  * @write_oob:	function to write chip OOB data
  */
@@ -393,13 +410,16 @@ struct nand_buffers {
 
 /**
  * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
- * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
+ * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the
+ *			flash device
+ * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
+ *			flash device.
  * @read_byte:		[REPLACEABLE] read one byte from the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
  * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
  * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
- * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip data
+ * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip
+ *			data.
  * @select_chip:	[REPLACEABLE] select chip nr
  * @block_bad:		[REPLACEABLE] check, if the block is bad
  * @block_markbad:	[REPLACEABLE] mark the block bad
@@ -409,45 +429,60 @@ struct nand_buffers {
  *			mtd->oobsize, mtd->writesize and so on.
  *			@id_data contains the 8 bytes values of NAND_CMD_READID.
  *			Return with the bus width.
- * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
- *			If set to NULL no access to ready/busy is available and the ready/busy information
- *			is read from the chip status register
- * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
- * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
+ * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing
+ *			device ready/busy line. If set to NULL no access to
+ *			ready/busy is available and the ready/busy information
+ *			is read from the chip status register.
+ * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing
+ *			commands to the chip.
+ * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on
+ *			ready.
  * @ecc:		[BOARDSPECIFIC] ecc control ctructure
  * @buffers:		buffer structure for read/write
  * @hwcontrol:		platform-specific hardware control structure
  * @ops:		oob operation operands
- * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
+ * @erase_cmd:		[INTERN] erase command write function, selectable due
+ *			to AND support.
  * @scan_bbt:		[REPLACEABLE] function to scan bad block table
- * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
+ * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering
+ *			data from array to read regs (tR).
  * @state:		[INTERN] the current state of the NAND device
  * @oob_poi:		poison value buffer
- * @page_shift:		[INTERN] number of address bits in a page (column address bits)
+ * @page_shift:		[INTERN] number of address bits in a page (column
+ *			address bits).
  * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
  * @chip_shift:		[INTERN] number of address bits in one chip
- * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
- *			special functionality. See the defines for further explanation
- * @badblockpos:	[INTERN] position of the bad block marker in the oob area
+ * @options:		[BOARDSPECIFIC] various chip options. They can partly
+ *			be set to inform nand_scan about special functionality.
+ *			See the defines for further explanation.
+ * @badblockpos:	[INTERN] position of the bad block marker in the oob
+ *			area.
  * @cellinfo:		[INTERN] MLC/multichip data from chip ident
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
- * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
+ * @pagebuf:		[INTERN] holds the pagenumber which is currently in
+ *			data_buf.
  * @subpagesize:	[INTERN] holds the subpagesize
- * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded), non 0 if ONFI supported
- * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is supported, 0 otherwise
+ * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded),
+ *			non 0 if ONFI supported.
+ * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
+ *			supported, 0 otherwise.
  * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
  * @bbt:		[INTERN] bad block table pointer
- * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
+ * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
+ *			lookup.
  * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
- * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @controller:		[REPLACEABLE] a pointer to a hardware controller structure
- *			which is shared among multiple independend devices
+ * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial
+ *			bad block scan.
+ * @controller:		[REPLACEABLE] a pointer to a hardware controller
+ *			structure which is shared among multiple independend
+ *			devices.
  * @priv:		[OPTIONAL] pointer to private chip date
- * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
- *			(determine if errors are correctable)
+ * @errstat:		[OPTIONAL] hardware specific function to perform
+ *			additional error status checks (determine if errors are
+ *			correctable).
  * @write_page:		[REPLACEABLE] High-level page write function
  */
 
@@ -457,24 +492,32 @@ struct nand_chip {
 
 	uint8_t		(*read_byte)(struct mtd_info *mtd);
 	u16		(*read_word)(struct mtd_info *mtd);
-	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
-	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
-	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf,
+			int len);
+	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf,
+			int len);
+	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf,
+			int len);
 	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs,
+			int getchip);
 	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
 				    unsigned int ctrl);
 	int		(*init_size)(struct mtd_info *mtd,
 					struct nand_chip *this, u8 *id_data);
 	int		(*dev_ready)(struct mtd_info *mtd);
-	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
-	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
+	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command,
+			int column, int page_addr);
+	int		(*waitfunc)(struct mtd_info *mtd,
+			struct nand_chip *this);
 	void		(*erase_cmd)(struct mtd_info *mtd, int page);
 	int		(*scan_bbt)(struct mtd_info *mtd);
-	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
-	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-				      const uint8_t *buf, int page, int cached, int raw);
+	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this,
+			int state, int status, int page);
+	int		(*write_page)(struct mtd_info *mtd,
+			struct nand_chip *chip, const uint8_t *buf, int page,
+			int cached, int raw);
 
 	int		chip_delay;
 	unsigned int	options;
@@ -557,7 +600,7 @@ struct nand_flash_dev {
 */
 struct nand_manufacturers {
 	int id;
-	char * name;
+	char *name;
 };
 
 extern struct nand_flash_dev nand_flash_ids[];
@@ -570,7 +613,7 @@ extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
 extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 			   int allowbbt);
 extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
-			size_t * retlen, uint8_t * buf);
+			size_t *retlen, uint8_t *buf);
 
 /**
  * struct platform_nand_chip - chip level device structure
-- 
1.7.2.3



From w.sang at pengutronix.de  Tue Oct  5 14:26:56 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Tue, 5 Oct 2010 20:26:56 +0200
Subject: [PATCH] mtd/nand.h: cleanups
In-Reply-To: <20101005104101.GA18714@www.tglx.de>
References: <20101005104101.GA18714@www.tglx.de>
Message-ID: <20101005182656.GA21067@pengutronix.de>

Hi Sebastian,

just a minor comment.

On Tue, Oct 05, 2010 at 12:41:01PM +0200, Sebastian Andrzej Siewior wrote:
> - *var instead of * var
> - proper multiline comment
> - func(args) instead of func (args)
> - 80 lines
> 
> So from
> |total: 2 errors, 37 warnings, 654 lines checked
> we got to one warning.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
> ---
>  include/linux/mtd/nand.h |  155 +++++++++++++++++++++++++++++-----------------
>  1 files changed, 99 insertions(+), 56 deletions(-)
> 
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 0238665..acd0b50 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -27,15 +27,17 @@
>  struct mtd_info;
>  struct nand_flash_dev;
>  /* Scan and identify a NAND device */
> -extern int nand_scan (struct mtd_info *mtd, int max_chips);
> -/* Separate phases of nand_scan(), allowing board driver to intervene
> - * and override command or ECC setup according to flash type */
> +extern int nand_scan(struct mtd_info *mtd, int max_chips);
> +/*
> + * Separate phases of nand_scan(), allowing board driver to intervene
> + * and override command or ECC setup according to flash type.
> + */
>  extern int nand_scan_ident(struct mtd_info *mtd, int max_chips,
>  			   struct nand_flash_dev *table);
>  extern int nand_scan_tail(struct mtd_info *mtd);
>  
>  /* Free resources held by the NAND device */
> -extern void nand_release (struct mtd_info *mtd);
> +extern void nand_release(struct mtd_info *mtd);
>  
>  /* Internal helper for board drivers which need to override command function */
>  extern void nand_wait_ready(struct mtd_info *mtd);
> @@ -49,7 +51,8 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
>  /* The maximum number of NAND chips in an array */
>  #define NAND_MAX_CHIPS		8
>  
> -/* This constant declares the max. oobsize / page, which
> +/*
> + * This constant declares the max. oobsize / page, which
>   * is supported now. If you add a chip with bigger oobsize/page
>   * adjust this accordingly.
>   */
> @@ -153,9 +156,10 @@ typedef enum {
>  #define NAND_GET_DEVICE		0x80
>  
>  
> -/* Option constants for bizarre disfunctionality and real
> -*  features
> -*/
> +/*
> + * Option constants for bizarre disfunctionality and real
> + * features.
> + */
>  /* Chip can not auto increment pages */
>  #define NAND_NO_AUTOINCR	0x00000001
>  /* Buswitdh is 16 bit */
> @@ -166,19 +170,27 @@ typedef enum {
>  #define NAND_CACHEPRG		0x00000008
>  /* Chip has copy back function */
>  #define NAND_COPYBACK		0x00000010
> -/* AND Chip which has 4 banks and a confusing page / block
> - * assignment. See Renesas datasheet for further information */
> +/*
> + * AND Chip which has 4 banks and a confusing page / block
> + * assignment. See Renesas datasheet for further information.
> + */
>  #define NAND_IS_AND		0x00000020
> -/* Chip has a array of 4 pages which can be read without
> - * additional ready /busy waits */
> +/*
> + * Chip has a array of 4 pages which can be read without
> + * additional ready /busy waits.
> + */
>  #define NAND_4PAGE_ARRAY	0x00000040
> -/* Chip requires that BBT is periodically rewritten to prevent
> +/*
> + * Chip requires that BBT is periodically rewritten to prevent
>   * bits from adjacent blocks from 'leaking' in altering data.
> - * This happens with the Renesas AG-AND chips, possibly others.  */
> + * This happens with the Renesas AG-AND chips, possibly others.
> + */
>  #define BBT_AUTO_REFRESH	0x00000080
> -/* Chip does not require ready check on read. True
> +/*
> + * Chip does not require ready check on read. True
>   * for all large page devices, as they do not support
> - * autoincrement.*/
> + * autoincrement.
> + */
>  #define NAND_NO_READRDY		0x00000100
>  /* Chip does not allow subpage writes */
>  #define NAND_NO_SUBPAGE_WRITE	0x00000200
> @@ -213,8 +225,10 @@ typedef enum {
>  #define NAND_USE_FLASH_BBT	0x00010000
>  /* This option skips the bbt scan during initialization. */
>  #define NAND_SKIP_BBTSCAN	0x00020000
> -/* This option is defined if the board driver allocates its own buffers
> -   (e.g. because it needs them DMA-coherent */
> +/*
> + * This option is defined if the board driver allocates its own buffers
> + * (e.g. because it needs them DMA-coherent).
> + */
>  #define NAND_OWN_BUFFERS	0x00040000
>  /* Chip may not exist, so silence any errors in scan */
>  #define NAND_SCAN_SILENT_NODEV	0x00080000
> @@ -304,8 +318,9 @@ struct nand_onfi_params {
>   * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
>   * @lock:               protection lock
>   * @active:		the mtd device which holds the controller currently
> - * @wq:			wait queue to sleep on if a NAND operation is in progress
> - *                      used instead of the per chip wait queue when a hw controller is available
> + * @wq:			wait queue to sleep on if a NAND operation is in
> + *			progress used instead of the per chip wait queue
> + *			when a hw controller is available.
>   */
>  struct nand_hw_control {
>  	spinlock_t	 lock;
> @@ -329,9 +344,11 @@ struct nand_hw_control {
>   * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
>   * @read_page_raw:	function to read a raw page without ECC
>   * @write_page_raw:	function to write a raw page without ECC
> - * @read_page:	function to read a page according to the ecc generator requirements
> + * @read_page:	function to read a page according to the ecc generator
> + *		requirements.
>   * @read_subpage:	function to read parts of the page covered by ECC.
> - * @write_page:	function to write a page according to the ecc generator requirements
> + * @write_page:	function to write a page according to the ecc generator
> + *		requirements.
>   * @read_oob:	function to read chip OOB data
>   * @write_oob:	function to write chip OOB data
>   */
> @@ -393,13 +410,16 @@ struct nand_buffers {
>  
>  /**
>   * struct nand_chip - NAND Private Flash Chip Data
> - * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
> - * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
> + * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the
> + *			flash device
> + * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
> + *			flash device.
>   * @read_byte:		[REPLACEABLE] read one byte from the chip
>   * @read_word:		[REPLACEABLE] read one word from the chip
>   * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
>   * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
> - * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip data
> + * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip
> + *			data.
>   * @select_chip:	[REPLACEABLE] select chip nr
>   * @block_bad:		[REPLACEABLE] check, if the block is bad
>   * @block_markbad:	[REPLACEABLE] mark the block bad
> @@ -409,45 +429,60 @@ struct nand_buffers {
>   *			mtd->oobsize, mtd->writesize and so on.
>   *			@id_data contains the 8 bytes values of NAND_CMD_READID.
>   *			Return with the bus width.
> - * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
> - *			If set to NULL no access to ready/busy is available and the ready/busy information
> - *			is read from the chip status register
> - * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
> - * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
> + * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing
> + *			device ready/busy line. If set to NULL no access to
> + *			ready/busy is available and the ready/busy information
> + *			is read from the chip status register.
> + * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing
> + *			commands to the chip.
> + * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on
> + *			ready.
>   * @ecc:		[BOARDSPECIFIC] ecc control ctructure
>   * @buffers:		buffer structure for read/write
>   * @hwcontrol:		platform-specific hardware control structure
>   * @ops:		oob operation operands
> - * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
> + * @erase_cmd:		[INTERN] erase command write function, selectable due
> + *			to AND support.
>   * @scan_bbt:		[REPLACEABLE] function to scan bad block table
> - * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
> + * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering
> + *			data from array to read regs (tR).
>   * @state:		[INTERN] the current state of the NAND device
>   * @oob_poi:		poison value buffer
> - * @page_shift:		[INTERN] number of address bits in a page (column address bits)
> + * @page_shift:		[INTERN] number of address bits in a page (column
> + *			address bits).
>   * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
>   * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
>   * @chip_shift:		[INTERN] number of address bits in one chip
> - * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
> - *			special functionality. See the defines for further explanation
> - * @badblockpos:	[INTERN] position of the bad block marker in the oob area
> + * @options:		[BOARDSPECIFIC] various chip options. They can partly
> + *			be set to inform nand_scan about special functionality.
> + *			See the defines for further explanation.
> + * @badblockpos:	[INTERN] position of the bad block marker in the oob
> + *			area.
>   * @cellinfo:		[INTERN] MLC/multichip data from chip ident
>   * @numchips:		[INTERN] number of physical chips
>   * @chipsize:		[INTERN] the size of one chip for multichip arrays
>   * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
> - * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
> + * @pagebuf:		[INTERN] holds the pagenumber which is currently in
> + *			data_buf.
>   * @subpagesize:	[INTERN] holds the subpagesize
> - * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded), non 0 if ONFI supported
> - * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is supported, 0 otherwise
> + * @onfi_version:	[INTERN] holds the chip ONFI version (BCD encoded),
> + *			non 0 if ONFI supported.
> + * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
> + *			supported, 0 otherwise.
>   * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
>   * @bbt:		[INTERN] bad block table pointer
> - * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
> + * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
> + *			lookup.
>   * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
> - * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan
> - * @controller:		[REPLACEABLE] a pointer to a hardware controller structure
> - *			which is shared among multiple independend devices
> + * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial
> + *			bad block scan.
> + * @controller:		[REPLACEABLE] a pointer to a hardware controller
> + *			structure which is shared among multiple independend
> + *			devices.
>   * @priv:		[OPTIONAL] pointer to private chip date
> - * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
> - *			(determine if errors are correctable)
> + * @errstat:		[OPTIONAL] hardware specific function to perform
> + *			additional error status checks (determine if errors are
> + *			correctable).
>   * @write_page:		[REPLACEABLE] High-level page write function
>   */
>  
> @@ -457,24 +492,32 @@ struct nand_chip {
>  
>  	uint8_t		(*read_byte)(struct mtd_info *mtd);
>  	u16		(*read_word)(struct mtd_info *mtd);
> -	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
> -	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
> -	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
> +	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf,
> +			int len);

It might be more readable to get rid of the tabs after the type and keep the
arguments in one line?

> +	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf,
> +			int len);
> +	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf,
> +			int len);
>  	void		(*select_chip)(struct mtd_info *mtd, int chip);
> -	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
> +	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs,
> +			int getchip);
>  	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
>  	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
>  				    unsigned int ctrl);
>  	int		(*init_size)(struct mtd_info *mtd,
>  					struct nand_chip *this, u8 *id_data);
>  	int		(*dev_ready)(struct mtd_info *mtd);
> -	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
> -	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
> +	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command,
> +			int column, int page_addr);
> +	int		(*waitfunc)(struct mtd_info *mtd,
> +			struct nand_chip *this);
>  	void		(*erase_cmd)(struct mtd_info *mtd, int page);
>  	int		(*scan_bbt)(struct mtd_info *mtd);
> -	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
> -	int		(*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
> -				      const uint8_t *buf, int page, int cached, int raw);
> +	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this,
> +			int state, int status, int page);
> +	int		(*write_page)(struct mtd_info *mtd,
> +			struct nand_chip *chip, const uint8_t *buf, int page,
> +			int cached, int raw);
>  
>  	int		chip_delay;
>  	unsigned int	options;
> @@ -557,7 +600,7 @@ struct nand_flash_dev {
>  */
>  struct nand_manufacturers {
>  	int id;
> -	char * name;
> +	char *name;
>  };
>  
>  extern struct nand_flash_dev nand_flash_ids[];
> @@ -570,7 +613,7 @@ extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
>  extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
>  			   int allowbbt);
>  extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
> -			size_t * retlen, uint8_t * buf);
> +			size_t *retlen, uint8_t *buf);
>  
>  /**
>   * struct platform_nand_chip - chip level device structure
> -- 
> 1.7.2.3
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101005/5eb84660/attachment.sig>

From dedekind1 at gmail.com  Tue Oct  5 14:48:26 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 05 Oct 2010 21:48:26 +0300
Subject: [PATCH] mtd/nand.h: cleanups
In-Reply-To: <20101005182656.GA21067@pengutronix.de>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
Message-ID: <1286304506.1797.2.camel@brekeke>

On Tue, 2010-10-05 at 20:26 +0200, Wolfram Sang wrote:
> Hi Sebastian,
> 
> just a minor comment.

[Side note: it is much more reader-friendly to avoid citing whole patch
and making the readers search where you put the comment, like this:]

> > @@ -457,24 +492,32 @@ struct nand_chip {
> >  
> >  	uint8_t		(*read_byte)(struct mtd_info *mtd);
> >  	u16		(*read_word)(struct mtd_info *mtd);
> > -	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
> > -	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
> > -	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
> > +	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf,
> > +			int len);
> 
> It might be more readable to get rid of the tabs after the type and keep the
> arguments in one line?

I agree with this. Sebastian, I'll put your patch to my l2 tree when
git.infradead.org is back. But if you could send a separate follow up
patch which kills these ugly tabs - it would be nice.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From krellboy at gmail.com  Tue Oct  5 17:03:49 2010
From: krellboy at gmail.com (Aaron Nabil)
Date: Tue, 5 Oct 2010 14:03:49 -0700
Subject: questions about jffs2 jffs2_erase_pending_blocks in erase.c
Message-ID: <AANLkTikttX8kwa2upG1_T78y=r_cOZgoUrt4PWOZWv3i@mail.gmail.com>

Again apologies if I'm doing this wrong, I rarely poke at the kernel
and only have a few days experience looking at jffs2 and don't
understand the "big picture" yet, but I'm seeing some things I don't
understand and would be grateful for any help.  Please contact me
off-list if you want to send me a "you are so stupid, it's supposed to
be doing that", in fact I'd welcome that over silence.  I'd even thank
you.

My question:

jffs2_erase_pending_blocks is only called with 1 or 0 as count arguments.

 nodemgmt.c jffs2_reserve_space  121 jffs2_erase_pending_blocks(c, 1);
 nodemgmt.c jffs2_find_nextblock 248 jffs2_erase_pending_blocks(c, 1);
 super.c    jffs2_write_super     67 jffs2_erase_pending_blocks(c, 0);

The test  if (!--count) seems to be testing for (count == 1) as the
decrement happens first.  If count is 0 it will be decremented
negative, underflow and wrap around to positive, and then eventually
hit 0 4 billion loop interations later.

Thanks in advance to anyone looking at this,

Aaron

void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
{
        struct jffs2_eraseblock *jeb;

        mutex_lock(&c->erase_free_sem);

        spin_lock(&c->erase_completion_lock);

        while (!list_empty(&c->erase_complete_list) ||
               !list_empty(&c->erase_pending_list)) {

                if (!list_empty(&c->erase_complete_list)) {
                        jeb = list_entry(c->erase_complete_list.next,
struct jffs2_eraseblock, list);
                        list_move(&jeb->list, &c->erase_checking_list);
                        spin_unlock(&c->erase_completion_lock);
                        mutex_unlock(&c->erase_free_sem);
                        jffs2_mark_erased_block(c, jeb);

                        if (!--count) {            //  decrement then
test is equiv to (count == 1)
                                D1(printk(KERN_DEBUG "Count reached.
jffs2_erase_pending_blocks leaving\n"));
                                goto done;
                        }


From joakim.tjernlund at transmode.se  Tue Oct  5 17:43:28 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Tue, 5 Oct 2010 23:43:28 +0200
Subject: questions about jffs2 jffs2_erase_pending_blocks in erase.c
In-Reply-To: <AANLkTikttX8kwa2upG1_T78y=r_cOZgoUrt4PWOZWv3i@mail.gmail.com>
References: <AANLkTikttX8kwa2upG1_T78y=r_cOZgoUrt4PWOZWv3i@mail.gmail.com>
Message-ID: <OF3CECC71D.A74C9639-ONC12577B3.0077252E-C12577B3.0077564B@transmode.se>

>
> Again apologies if I'm doing this wrong, I rarely poke at the kernel
> and only have a few days experience looking at jffs2 and don't
> understand the "big picture" yet, but I'm seeing some things I don't
> understand and would be grateful for any help.  Please contact me
> off-list if you want to send me a "you are so stupid, it's supposed to
> be doing that", in fact I'd welcome that over silence.  I'd even thank
> you.
>
> My question:
>
> jffs2_erase_pending_blocks is only called with 1 or 0 as count arguments.
>
>  nodemgmt.c jffs2_reserve_space  121 jffs2_erase_pending_blocks(c, 1);
>  nodemgmt.c jffs2_find_nextblock 248 jffs2_erase_pending_blocks(c, 1);
>  super.c    jffs2_write_super     67 jffs2_erase_pending_blocks(c, 0);
>
> The test  if (!--count) seems to be testing for (count == 1) as the
> decrement happens first.  If count is 0 it will be decremented
> negative, underflow and wrap around to positive, and then eventually
> hit 0 4 billion loop interations later.
>
> Thanks in advance to anyone looking at this,

Yes, this will ensure JFFS2 erases until the list(s) are
empty.
Also, latest kernel has reworked this area so you might want to update.



From jon.povey at racelogic.co.uk  Tue Oct  5 23:21:58 2010
From: jon.povey at racelogic.co.uk (Jon Povey)
Date: Wed,  6 Oct 2010 12:21:58 +0900
Subject: [RFC] mtd: add MEMSETGOODBLOCK ioctl
Message-ID: <1286335318-17542-1-git-send-email-jon.povey@racelogic.co.uk>

Adds the MEMSETGOODBLOCK ioctl, inverse operation of MEMSETBADBLOCK for
times when you really are sure that a block is good, but was marked bad
in error.

WARNING: This ioctl should not be casually used, you can't magically
fix unreliable blocks, and causing the system to try and use them may
cause you problems. Manufacturer-marked bad blocks may be forgotten
and impossible to find again later. Be careful.

This ioctl is for situations where you know what you are doing, for
example your bootloader has to be written with a different OOB layout
and scanned as bad when the BBT was generated, but you know it's good
and want to rewrite it from Linux.

Signed-off-by: Jon Povey <jon.povey at racelogic.co.uk>
---
This is a request for comment on this approach to bad blocks, this patch
only considers the nand driver and only versions with a BBT on flash.

This works for me on davinci DM355 with 2K page NAND flash.

 drivers/mtd/mtdchar.c        |   13 +++++++++
 drivers/mtd/mtdpart.c        |   18 ++++++++++++
 drivers/mtd/nand/nand_base.c |   60 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h      |    1 +
 include/linux/mtd/nand.h     |    2 +
 include/mtd/mtd-abi.h        |    1 +
 6 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index a825002..20250ae 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -750,6 +750,19 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 		break;
 	}
 
+	case MEMSETGOODBLOCK:
+	{
+		loff_t offs;
+
+		if (copy_from_user(&offs, argp, sizeof(loff_t)))
+			return -EFAULT;
+		if (!mtd->block_markgood)
+			ret = -EOPNOTSUPP;
+		else
+			return mtd->block_markgood(mtd, offs);
+		break;
+	}
+
 #ifdef CONFIG_HAVE_MTD_OTP
 	case OTPSELECT:
 	{
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 0090690..cd03c29 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -327,6 +327,22 @@ static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	return res;
 }
 
+static int part_block_markgood(struct mtd_info *mtd, loff_t ofs)
+{
+	struct mtd_part *part = PART(mtd);
+	int res;
+
+	if (!(mtd->flags & MTD_WRITEABLE))
+		return -EROFS;
+	if (ofs >= mtd->size)
+		return -EINVAL;
+	ofs += part->offset;
+	res = part->master->block_markgood(part->master, ofs);
+	if (!res)
+		mtd->ecc_stats.badblocks--;
+	return res;
+}
+
 /*
  * This function unregisters and destroy all slave MTD objects which are
  * attached to the given master MTD object.
@@ -464,6 +480,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master,
 		slave->mtd.block_isbad = part_block_isbad;
 	if (master->block_markbad)
 		slave->mtd.block_markbad = part_block_markbad;
+	if (master->block_markgood)
+		slave->mtd.block_markgood = part_block_markgood;
 	slave->mtd.erase = part_erase;
 	slave->master = master;
 	slave->offset = part->offset;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index b3469a7..c2c6211 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -444,6 +444,40 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 }
 
 /**
+ * nand_default_block_markgood - [DEFAULT] mark a block good
+ * @mtd:	MTD device structure
+ * @ofs:	offset from device start
+ *
+ * This is the default implementation, which can be overridden by
+ * a hardware specific driver.
+*/
+static int nand_default_block_markgood(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	int block, ret;
+
+	if (chip->options & NAND_BBT_SCANLASTPAGE)
+		ofs += mtd->erasesize - mtd->writesize;
+
+	/* Get block number */
+	block = (int)(ofs >> chip->bbt_erase_shift);
+	if (chip->bbt)
+		chip->bbt[block >> 2] &= ~(0x03 << ((block & 0x03) << 1));
+
+	/* Do we have a flash based bad block table ? */
+	if (chip->options & NAND_USE_FLASH_BBT) {
+		ret = nand_update_bbt(mtd, ofs);
+	} else {
+		WARN_ONCE(1, "Attempt to NAND markgood without flash BBT");
+		ret = -EOPNOTSUPP;
+	}
+	if (!ret)
+		mtd->ecc_stats.badblocks--;
+
+	return ret;
+}
+
+/**
  * nand_check_wp - [GENERIC] check if the chip is write protected
  * @mtd:	MTD device structure
  * Check, if the device is write protected
@@ -2736,6 +2770,29 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 }
 
 /**
+ * nand_block_markgood - [MTD Interface] Mark block at the given offset as good
+ * @mtd:	MTD device structure
+ * @ofs:	offset relative to mtd start
+ */
+static int nand_block_markgood(struct mtd_info *mtd, loff_t ofs)
+{
+	struct nand_chip *chip = mtd->priv;
+	int ret;
+
+	printk(KERN_INFO "markgood 0x%llx\n", ofs);
+	ret = nand_block_isbad(mtd, ofs);
+	if (ret < 0)
+		return ret;
+	else if (ret == 0) {
+		printk(KERN_INFO "is good, do nothing\n");
+		/* Good already, return success and do nothing */
+		return 0;
+	}
+
+	return chip->block_markgood(mtd, ofs);
+}
+
+/**
  * nand_suspend - [MTD Interface] Suspend the NAND flash
  * @mtd:	MTD device structure
  */
@@ -2788,6 +2845,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
 		chip->block_bad = nand_block_bad;
 	if (!chip->block_markbad)
 		chip->block_markbad = nand_default_block_markbad;
+	if (!chip->block_markgood)
+		chip->block_markgood = nand_default_block_markgood;
 	if (!chip->write_buf)
 		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
 	if (!chip->read_buf)
@@ -3302,6 +3361,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->resume = nand_resume;
 	mtd->block_isbad = nand_block_isbad;
 	mtd->block_markbad = nand_block_markbad;
+	mtd->block_markgood = nand_block_markgood;
 
 	/* propagate ecc.layout to mtd_info */
 	mtd->ecclayout = chip->ecc.layout;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 8485e42..c71276f 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -237,6 +237,7 @@ struct mtd_info {
 	/* Bad block management functions */
 	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
 	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
+	int (*block_markgood) (struct mtd_info *mtd, loff_t ofs);
 
 	struct notifier_block reboot_notifier;  /* default mode before reboot */
 
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index e41d377..9744a51 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -332,6 +332,7 @@ struct nand_buffers {
  * @select_chip:	[REPLACEABLE] select chip nr
  * @block_bad:		[REPLACEABLE] check, if the block is bad
  * @block_markbad:	[REPLACEABLE] mark the block bad
+ * @block_markgood:	[REPLACEABLE] mark the block good
  * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific funtion for controlling
  *			ALE/CLE/nCE. Also used to write command and address
  * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
@@ -386,6 +387,7 @@ struct nand_chip {
 	void		(*select_chip)(struct mtd_info *mtd, int chip);
 	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
 	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+	int		(*block_markgood)(struct mtd_info *mtd, loff_t ofs);
 	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
 				    unsigned int ctrl);
 	int		(*dev_ready)(struct mtd_info *mtd);
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 4debb45..d32bea8 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -126,6 +126,7 @@ struct otp_info {
 #define MEMWRITEOOB64		_IOWR('M', 21, struct mtd_oob_buf64)
 #define MEMREADOOB64		_IOWR('M', 22, struct mtd_oob_buf64)
 #define MEMISLOCKED		_IOR('M', 23, struct erase_info_user)
+#define MEMSETGOODBLOCK		_IOW('M', 24, __kernel_loff_t)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
-- 
1.6.3.3



From dsd at laptop.org  Wed Oct  6 17:00:36 2010
From: dsd at laptop.org (Daniel Drake)
Date: Wed,  6 Oct 2010 22:00:36 +0100 (BST)
Subject: [doesn't work] JFFS2: Dynamically choose inocache hash size
Message-ID: <20101006210036.92C229D401B@zog.reactivated.net>

I'm trying to upstream an old OLPC patch which greatly speeds up mounting
of large jffs2 volumes.
Took a stab at a suggestion from David (shown here) but it crashes badly.
Causes lots of WARNINGs to be triggered from __mark_inode_dirty.

I'm not going to spend any more time on this for the time being,
just archiving the patch here, just in case someone has interest in
finishing it off.



When JFFS2 is used for large volumes, the mount times are quite long.
Increasing the hash size provides a significant speed boost on the OLPC
XO-1 laptop.

Add logic that dynamically selects a hash size based on the size of
the medium. A 64mb medium will result in a hash size of 128, and a 512mb
medium will result in a hash size of 1024.

Signed-off-by: Daniel Drake <dsd at laptop.org>
---
 fs/jffs2/build.c       |    2 +-
 fs/jffs2/fs.c          |   22 +++++++++++++++++++++-
 fs/jffs2/jffs2_fs_sb.h |    1 +
 fs/jffs2/nodelist.c    |    8 ++++----
 fs/jffs2/nodelist.h    |    3 ++-
 5 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index a906f53..85c6be2 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *,
 static inline struct jffs2_inode_cache *
 first_inode_chain(int *i, struct jffs2_sb_info *c)
 {
-	for (; *i < INOCACHE_HASHSIZE; (*i)++) {
+	for (; *i < c->inocache_hashsize; (*i)++) {
 		if (c->inocache_list[*i])
 			return c->inocache_list[*i];
 	}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 6b2964a..2701b37 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -478,6 +478,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 	return inode;
 }
 
+static int calculate_inocache_hashsize(uint32_t flash_size)
+{
+	/*
+	 * Pick a inocache hash size based on the size of the medium.
+	 * Count how many megabytes we're dealing with, apply a hashsize twice
+	 * that size, but rounding down to the usual big powers of 2. And keep
+	 * to sensible bounds.
+	 */
+
+	int size_mb = flash_size / 1024 / 1024;
+	int hashsize = (size_mb * 2) & ~0x3f;
+
+	if (hashsize < INOCACHE_HASHSIZE_MIN)
+		return INOCACHE_HASHSIZE_MIN;
+	if (hashsize > INOCACHE_HASHSIZE_MAX)
+		return INOCACHE_HASHSIZE_MAX;
+
+	return hashsize;
+}
 
 int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
 {
@@ -524,7 +543,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
 	if (ret)
 		return ret;
 
-	c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
+	c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
+	c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
 	if (!c->inocache_list) {
 		ret = -ENOMEM;
 		goto out_wbuf;
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 6784bc8..f864005 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -100,6 +100,7 @@ struct jffs2_sb_info {
 	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
 
 	wait_queue_head_t inocache_wq;
+	int inocache_hashsize;
 	struct jffs2_inode_cache **inocache_list;
 	spinlock_t inocache_lock;
 
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index af02bd1..5e03233 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t
 {
 	struct jffs2_inode_cache *ret;
 
-	ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
+	ret = c->inocache_list[ino % c->inocache_hashsize];
 	while (ret && ret->ino < ino) {
 		ret = ret->next;
 	}
@@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
 
 	dbg_inocache("add %p (ino #%u)\n", new, new->ino);
 
-	prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE];
+	prev = &c->inocache_list[new->ino % c->inocache_hashsize];
 
 	while ((*prev) && (*prev)->ino < new->ino) {
 		prev = &(*prev)->next;
@@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
 	dbg_inocache("del %p (ino #%u)\n", old, old->ino);
 	spin_lock(&c->inocache_lock);
 
-	prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
+	prev = &c->inocache_list[old->ino % c->inocache_hashsize];
 
 	while ((*prev) && (*prev)->ino < old->ino) {
 		prev = &(*prev)->next;
@@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
 	int i;
 	struct jffs2_inode_cache *this, *next;
 
-	for (i=0; i<INOCACHE_HASHSIZE; i++) {
+	for (i=0; i < c->inocache_hashsize; i++) {
 		this = c->inocache_list[i];
 		while (this) {
 			next = this->next;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 523a916..5a53d9b 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -199,7 +199,8 @@ struct jffs2_inode_cache {
 #define RAWNODE_CLASS_XATTR_DATUM	1
 #define RAWNODE_CLASS_XATTR_REF		2
 
-#define INOCACHE_HASHSIZE 128
+#define INOCACHE_HASHSIZE_MIN 128
+#define INOCACHE_HASHSIZE_MAX 1024
 
 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
 
-- 
1.7.2.3



From karl.beldan at gmail.com  Wed Oct  6 17:02:54 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Wed,  6 Oct 2010 23:02:54 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
Message-ID: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>

Hi,

I have been using this tweak for some time now, and I am getting tired of 
having to resort to it so often.
It allows to pass such cmdline root as: 
 "root=mtdb:ubivolx rootfstype=squashfs"
I am pretty sure many people use squashfs/cramfs filesystems on top of nand, 
for example, and I thought that this might initiate discussion.

-- 
Karl

Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
---
 init/do_mounts.c |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/init/do_mounts.c b/init/do_mounts.c
index 02e3ca4..20d9380 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -20,6 +20,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
 #include <linux/nfs_mount.h>
+#include <linux/mtd/mtd.h>
 
 #include "do_mounts.h"
 
@@ -386,8 +387,18 @@ void __init prepare_namespace(void)
 
 	if (saved_root_name[0]) {
 		root_device_name = saved_root_name;
-		if (!strncmp(root_device_name, "mtd", 3) ||
-		    !strncmp(root_device_name, "ubi", 3)) {
+		if (!strncmp(root_device_name, "mtdb:", 4)) {
+			struct mtd_info *mtd = get_mtd_device_nm(root_device_name + 4);
+			if (!IS_ERR(mtd))
+				sprintf(root_device_name, "/dev/mtdblock%d", mtd->index);
+			else {
+				printk(KERN_ERR "VFS: Unable to find mtd \"%s\"\n", root_device_name + 4);
+				printk("List of all partitions:\n");
+				printk_all_partitions();
+				panic("VFS: Unable to mount root fs");
+			}
+		} else if (!strncmp(root_device_name, "mtd", 3) ||
+			   !strncmp(root_device_name, "ubi", 3)) {
 			mount_block_root(root_device_name, root_mountflags);
 			goto out;
 		}
-- 
1.7.1.422.g049e9



From bigeasy at linutronix.de  Wed Oct  6 17:06:14 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Wed, 6 Oct 2010 23:06:14 +0200
Subject: [PATCH] mtd/nand.h: little more cleanup
In-Reply-To: <1286304506.1797.2.camel@brekeke>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>
Message-ID: <20101006210614.GA18551@www.tglx.de>

- remove tabs between type and name.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
 include/linux/mtd/nand.h |  315 +++++++++++++++++++++------------------------
 1 files changed, 147 insertions(+), 168 deletions(-)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index acd0b50..6473849 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -253,61 +253,62 @@ struct nand_chip;
 
 struct nand_onfi_params {
 	/* rev info and features block */
-	u8		sig[4]; /* 'O' 'N' 'F' 'I'  */
-	__le16		revision;
-	__le16		features;
-	__le16		opt_cmd;
-	u8		reserved[22];
+	/* 'O' 'N' 'F' 'I'  */
+	u8 sig[4];
+	__le16 revision;
+	__le16 features;
+	__le16 opt_cmd;
+	u8 reserved[22];
 
 	/* manufacturer information block */
-	char		manufacturer[12];
-	char		model[20];
-	u8		jedec_id;
-	__le16		date_code;
-	u8		reserved2[13];
+	char manufacturer[12];
+	char model[20];
+	u8 jedec_id;
+	__le16 date_code;
+	u8 reserved2[13];
 
 	/* memory organization block */
-	__le32		byte_per_page;
-	__le16		spare_bytes_per_page;
-	__le32		data_bytes_per_ppage;
-	__le16		spare_bytes_per_ppage;
-	__le32		pages_per_block;
-	__le32		blocks_per_lun;
-	u8		lun_count;
-	u8		addr_cycles;
-	u8		bits_per_cell;
-	__le16		bb_per_lun;
-	__le16		block_endurance;
-	u8		guaranteed_good_blocks;
-	__le16		guaranteed_block_endurance;
-	u8		programs_per_page;
-	u8		ppage_attr;
-	u8		ecc_bits;
-	u8		interleaved_bits;
-	u8		interleaved_ops;
-	u8		reserved3[13];
+	__le32 byte_per_page;
+	__le16 spare_bytes_per_page;
+	__le32 data_bytes_per_ppage;
+	__le16 spare_bytes_per_ppage;
+	__le32 pages_per_block;
+	__le32 blocks_per_lun;
+	u8 lun_count;
+	u8 addr_cycles;
+	u8 bits_per_cell;
+	__le16 bb_per_lun;
+	__le16 block_endurance;
+	u8 guaranteed_good_blocks;
+	__le16 guaranteed_block_endurance;
+	u8 programs_per_page;
+	u8 ppage_attr;
+	u8 ecc_bits;
+	u8 interleaved_bits;
+	u8 interleaved_ops;
+	u8 reserved3[13];
 
 	/* electrical parameter block */
-	u8		io_pin_capacitance_max;
-	__le16		async_timing_mode;
-	__le16		program_cache_timing_mode;
-	__le16		t_prog;
-	__le16		t_bers;
-	__le16		t_r;
-	__le16		t_ccs;
-	__le16		src_sync_timing_mode;
-	__le16		src_ssync_features;
-	__le16		clk_pin_capacitance_typ;
-	__le16		io_pin_capacitance_typ;
-	__le16		input_pin_capacitance_typ;
-	u8		input_pin_capacitance_max;
-	u8		driver_strenght_support;
-	__le16		t_int_r;
-	__le16		t_ald;
-	u8		reserved4[7];
+	u8 io_pin_capacitance_max;
+	__le16 async_timing_mode;
+	__le16 program_cache_timing_mode;
+	__le16 t_prog;
+	__le16 t_bers;
+	__le16 t_r;
+	__le16 t_ccs;
+	__le16 src_sync_timing_mode;
+	__le16 src_ssync_features;
+	__le16 clk_pin_capacitance_typ;
+	__le16 io_pin_capacitance_typ;
+	__le16 input_pin_capacitance_typ;
+	u8 input_pin_capacitance_max;
+	u8 driver_strenght_support;
+	__le16 t_int_r;
+	__le16 t_ald;
+	u8 reserved4[7];
 
 	/* vendor */
-	u8		reserved5[90];
+	u8 reserved5[90];
 
 	__le16 crc;
 } __attribute__((packed));
@@ -323,7 +324,7 @@ struct nand_onfi_params {
  *			when a hw controller is available.
  */
 struct nand_hw_control {
-	spinlock_t	 lock;
+	spinlock_t lock;
 	struct nand_chip *active;
 	wait_queue_head_t wq;
 };
@@ -353,44 +354,33 @@ struct nand_hw_control {
  * @write_oob:	function to write chip OOB data
  */
 struct nand_ecc_ctrl {
-	nand_ecc_modes_t	mode;
-	int			steps;
-	int			size;
-	int			bytes;
-	int			total;
-	int			prepad;
-	int			postpad;
+	nand_ecc_modes_t mode;
+	int steps;
+	int size;
+	int bytes;
+	int total;
+	int prepad;
+	int postpad;
 	struct nand_ecclayout	*layout;
-	void			(*hwctl)(struct mtd_info *mtd, int mode);
-	int			(*calculate)(struct mtd_info *mtd,
-					     const uint8_t *dat,
-					     uint8_t *ecc_code);
-	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
-					   uint8_t *read_ecc,
-					   uint8_t *calc_ecc);
-	int			(*read_page_raw)(struct mtd_info *mtd,
-						 struct nand_chip *chip,
-						 uint8_t *buf, int page);
-	void			(*write_page_raw)(struct mtd_info *mtd,
-						  struct nand_chip *chip,
-						  const uint8_t *buf);
-	int			(*read_page)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     uint8_t *buf, int page);
-	int			(*read_subpage)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     uint32_t offs, uint32_t len,
-					     uint8_t *buf);
-	void			(*write_page)(struct mtd_info *mtd,
-					      struct nand_chip *chip,
-					      const uint8_t *buf);
-	int			(*read_oob)(struct mtd_info *mtd,
-					    struct nand_chip *chip,
-					    int page,
-					    int sndcmd);
-	int			(*write_oob)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     int page);
+	void (*hwctl)(struct mtd_info *mtd, int mode);
+	int (*calculate)(struct mtd_info *mtd, const uint8_t *dat,
+			uint8_t *ecc_code);
+	int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
+			uint8_t *calc_ecc);
+	int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint8_t *buf, int page);
+	void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf);
+	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint8_t *buf, int page);
+	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t offs, uint32_t len, uint8_t *buf);
+	void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf);
+	int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
+			int sndcmd);
+	int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
+			int page);
 };
 
 /**
@@ -487,62 +477,55 @@ struct nand_buffers {
  */
 
 struct nand_chip {
-	void  __iomem	*IO_ADDR_R;
-	void  __iomem	*IO_ADDR_W;
-
-	uint8_t		(*read_byte)(struct mtd_info *mtd);
-	u16		(*read_word)(struct mtd_info *mtd);
-	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf,
-			int len);
-	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf,
-			int len);
-	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf,
-			int len);
-	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs,
-			int getchip);
-	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
-				    unsigned int ctrl);
-	int		(*init_size)(struct mtd_info *mtd,
-					struct nand_chip *this, u8 *id_data);
-	int		(*dev_ready)(struct mtd_info *mtd);
-	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command,
-			int column, int page_addr);
-	int		(*waitfunc)(struct mtd_info *mtd,
-			struct nand_chip *this);
-	void		(*erase_cmd)(struct mtd_info *mtd, int page);
-	int		(*scan_bbt)(struct mtd_info *mtd);
-	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this,
-			int state, int status, int page);
-	int		(*write_page)(struct mtd_info *mtd,
-			struct nand_chip *chip, const uint8_t *buf, int page,
-			int cached, int raw);
-
-	int		chip_delay;
-	unsigned int	options;
-
-	int		page_shift;
-	int		phys_erase_shift;
-	int		bbt_erase_shift;
-	int		chip_shift;
-	int		numchips;
-	uint64_t	chipsize;
-	int		pagemask;
-	int		pagebuf;
-	int		subpagesize;
-	uint8_t		cellinfo;
-	int		badblockpos;
-	int		badblockbits;
-
-	int		onfi_version;
+	void __iomem *IO_ADDR_R;
+	void __iomem *IO_ADDR_W;
+
+	uint8_t (*read_byte)(struct mtd_info *mtd);
+	u16 (*read_word)(struct mtd_info *mtd);
+	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+	int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*select_chip)(struct mtd_info *mtd, int chip);
+	int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+	int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
+			u8 *id_data);
+	int (*dev_ready)(struct mtd_info *mtd);
+	void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
+			int page_addr);
+	int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
+	void (*erase_cmd)(struct mtd_info *mtd, int page);
+	int (*scan_bbt)(struct mtd_info *mtd);
+	int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
+			int status, int page);
+	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf, int page, int cached, int raw);
+
+	int chip_delay;
+	unsigned int options;
+
+	int page_shift;
+	int phys_erase_shift;
+	int bbt_erase_shift;
+	int chip_shift;
+	int numchips;
+	uint64_t hipsize;
+	int pagemask;
+	int pagebuf;
+	int subpagesize;
+	uint8_t cellinfo;
+	int badblockpos;
+	int badblockbits;
+
+	int onfi_version;
 	struct nand_onfi_params	onfi_params;
 
-	flstate_t	state;
+	flstate_t state;
 
-	uint8_t		*oob_poi;
-	struct nand_hw_control  *controller;
-	struct nand_ecclayout	*ecclayout;
+	uint8_t *oob_poi;
+	struct nand_hw_control *controller;
+	struct nand_ecclayout *ecclayout;
 
 	struct nand_ecc_ctrl ecc;
 	struct nand_buffers *buffers;
@@ -550,13 +533,13 @@ struct nand_chip {
 
 	struct mtd_oob_ops ops;
 
-	uint8_t		*bbt;
-	struct nand_bbt_descr	*bbt_td;
-	struct nand_bbt_descr	*bbt_md;
+	uint8_t *bbt;
+	struct nand_bbt_descr *bbt_td;
+	struct nand_bbt_descr *bbt_md;
 
-	struct nand_bbt_descr	*badblock_pattern;
+	struct nand_bbt_descr *badblock_pattern;
 
-	void		*priv;
+	void *priv;
 };
 
 /*
@@ -629,17 +612,16 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @priv:		hardware controller specific settings
  */
 struct platform_nand_chip {
-	int			nr_chips;
-	int			chip_offset;
-	int			nr_partitions;
-	struct mtd_partition	*partitions;
-	struct nand_ecclayout	*ecclayout;
-	int			chip_delay;
-	unsigned int		options;
-	const char		**part_probe_types;
-	void			(*set_parts)(uint64_t size,
-					struct platform_nand_chip *chip);
-	void			*priv;
+	int nr_chips;
+	int chip_offset;
+	int nr_partitions;
+	struct mtd_partition *partitions;
+	struct nand_ecclayout *ecclayout;
+	int chip_delay;
+	unsigned int options;
+	const char **part_probe_types;
+	void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
+	void *priv;
 };
 
 /* Keep gcc happy */
@@ -661,18 +643,15 @@ struct platform_device;
  * All fields are optional and depend on the hardware driver requirements
  */
 struct platform_nand_ctrl {
-	int		(*probe)(struct platform_device *pdev);
-	void		(*remove)(struct platform_device *pdev);
-	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
-	int		(*dev_ready)(struct mtd_info *mtd);
-	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
-				    unsigned int ctrl);
-	void		(*write_buf)(struct mtd_info *mtd,
-				    const uint8_t *buf, int len);
-	void		(*read_buf)(struct mtd_info *mtd,
-				    uint8_t *buf, int len);
-	void		*priv;
+	int (*probe)(struct platform_device *pdev);
+	void (*remove)(struct platform_device *pdev);
+	void (*hwcontrol)(struct mtd_info *mtd, int cmd);
+	int (*dev_ready)(struct mtd_info *mtd);
+	void (*select_chip)(struct mtd_info *mtd, int chip);
+	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+	void *priv;
 };
 
 /**
@@ -681,8 +660,8 @@ struct platform_nand_ctrl {
  * @ctrl:		controller level device structure
  */
 struct platform_nand_data {
-	struct platform_nand_chip	chip;
-	struct platform_nand_ctrl	ctrl;
+	struct platform_nand_chip chip;
+	struct platform_nand_ctrl ctrl;
 };
 
 /* Some helpers to access the data structures */
-- 
1.7.2.3



From w.sang at pengutronix.de  Wed Oct  6 17:21:16 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 6 Oct 2010 23:21:16 +0200
Subject: [PATCH] mtd/nand.h: little more cleanup
In-Reply-To: <20101006210614.GA18551@www.tglx.de>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>
	<20101006210614.GA18551@www.tglx.de>
Message-ID: <20101006212116.GB9722@pengutronix.de>

On Wed, Oct 06, 2010 at 11:06:14PM +0200, Sebastian Andrzej Siewior wrote:
> - remove tabs between type and name.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

Thanks!

Acked-by: Wolfram Sang <w.sang at pengutronix.de>

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101006/53f6b7e4/attachment.sig>

From karl.beldan at gmail.com  Wed Oct  6 17:22:27 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Wed, 6 Oct 2010 23:22:27 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
Message-ID: <AANLkTi=1j-N-VdJ0=tF5Sf8B8tasvtBYaWteoHCuxnkD@mail.gmail.com>

Edit for my off-by-one typo:

On Wed, Oct 6, 2010 at 11:02 PM, Karl Beldan <karl.beldan at gmail.com> wrote:
> Hi,
>
> I have been using this tweak for some time now, and I am getting tired of
> having to resort to it so often.
> It allows to pass such cmdline root as:
> ?"root=mtdb:ubivolx rootfstype=squashfs"
> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
> for example, and I thought that this might initiate discussion.
>
> --
> Karl
>
> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
> ---
> ?init/do_mounts.c | ? 15 +++++++++++++--
> ?1 files changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/init/do_mounts.c b/init/do_mounts.c
> index 02e3ca4..20d9380 100644
> --- a/init/do_mounts.c
> +++ b/init/do_mounts.c
> @@ -20,6 +20,7 @@
> ?#include <linux/nfs_fs.h>
> ?#include <linux/nfs_fs_sb.h>
> ?#include <linux/nfs_mount.h>
> +#include <linux/mtd/mtd.h>
>
> ?#include "do_mounts.h"
>
> @@ -386,8 +387,18 @@ void __init prepare_namespace(void)
>
> ? ? ? ?if (saved_root_name[0]) {
> ? ? ? ? ? ? ? ?root_device_name = saved_root_name;
> - ? ? ? ? ? ? ? if (!strncmp(root_device_name, "mtd", 3) ||
> - ? ? ? ? ? ? ? ? ? !strncmp(root_device_name, "ubi", 3)) {
> + ? ? ? ? ? ? ? if (!strncmp(root_device_name, "mtdb:", 4)) {
Here, it is 5 not 4

> + ? ? ? ? ? ? ? ? ? ? ? struct mtd_info *mtd = get_mtd_device_nm(root_device_name + 4);
same here

> + ? ? ? ? ? ? ? ? ? ? ? if (!IS_ERR(mtd))
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sprintf(root_device_name, "/dev/mtdblock%d", mtd->index);
> + ? ? ? ? ? ? ? ? ? ? ? else {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "VFS: Unable to find mtd \"%s\"\n", root_device_name + 4);
and here

> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printk("List of all partitions:\n");
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printk_all_partitions();
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? panic("VFS: Unable to mount root fs");
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? } else if (!strncmp(root_device_name, "mtd", 3) ||
> + ? ? ? ? ? ? ? ? ? ? ? ? ?!strncmp(root_device_name, "ubi", 3)) {
> ? ? ? ? ? ? ? ? ? ? ? ?mount_block_root(root_device_name, root_mountflags);
> ? ? ? ? ? ? ? ? ? ? ? ?goto out;
> ? ? ? ? ? ? ? ?}
> --
> 1.7.1.422.g049e9
>

-- 
Karl


From rohit.hs at samsung.com  Thu Oct  7 00:32:02 2010
From: rohit.hs at samsung.com (Rohit Hassan Sathyanarayan)
Date: Thu, 07 Oct 2010 10:02:02 +0530
Subject: [PATCH RESEND][MTD]MLC device check in OneNAND driver
In-Reply-To: <1285329124.29268.175.camel@localhost>
References: <001701cb5bdd$3fd69a80$bf83cf80$%hs@samsung.com>
	<1285329124.29268.175.camel@localhost>
Message-ID: <000f01cb65d8$984b15b0$c8e14110$%hs@samsung.com>

Hi Artem,

> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1 at gmail.com]
> Sent: Friday, September 24, 2010 5:22 PM
> To: Rohit Hassan Sathyanarayan
> Cc: linux-mtd at lists.infradead.org; gupta.raghav at samsung.com; v.dalal at samsung.com
> Subject: Re: [PATCH RESEND][MTD]MLC device check in OneNAND driver
> 
> On Fri, 2010-09-24 at 17:10 +0530, Rohit Hassan Sathyanarayan wrote:
> > Signed-off-by: Rohit HS <rohit.hs at samsung.com>
> > Signed-off-by: Raghav Gupta <gupta.raghav at samsung.com>
> 
> Almost perfect. However:
> 
> 1. All mtd patches should have "mtd:" prefix.
> 2. Add some description about what you do and why into the commit
> message.
> 3. I think combining is not good, better do it old way - first patch
> introduces the flag, second uses it in OneNAND
> 

  We made changes as per your comments and have posted two patches,
  Links of two patches,
  http://lists.infradead.org/pipermail/linux-mtd/2010-September/032333.html
  http://lists.infradead.org/pipermail/linux-mtd/2010-September/032334.html

   	
> Sorry for being picky, but I really want to show you how to send patches
> properly once and later get good series from you.
> 
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)



From joakim.tjernlund at transmode.se  Thu Oct  7 02:57:40 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 08:57:40 +0200
Subject: JFFS2 very slow when erasing
Message-ID: <OF23585AD5.AC5BB50F-ONC12577B5.0025413E-C12577B5.00263D39@transmode.se>


With 2.6.35 JFFS2 takes a very long time cp files while it erases:
 cp big_file test
 rm test
 cp big_file test
The last cp op. takes several times longer because JFFS2 is erasing.
Revering the patches I helped out with make JFFS2 go fast again:
  jffs2: Stop triggering block erases from jffs2_write_super()
  jffs2: Rename jffs2_erase_pending_trigger() to jffs2_dirty_trigger()
  jffs2: Use jffs2_garbage_collect_trigger() to trigger pending erases
  jffs2: Require jffs2_garbage_collect_trigger() to be called with lock held
  jffs2: Wake GC thread when there are blocks to be erased
  jffs2: Erase pending blocks in GC pass, avoid invalid -EIO return

The final patches were somewhat different than the ones I originally wrote
and I THINK those didn't make JFFS2 go this slow.

I suspect there is a locking problem somewhere.

 Jocke



From joakim.tjernlund at transmode.se  Thu Oct  7 03:49:44 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 09:49:44 +0200
Subject: JFFS2 very slow when erasing
In-Reply-To: <OF23585AD5.AC5BB50F-ONC12577B5.0025413E-C12577B5.00263D39@transmode.se>
References: <OF23585AD5.AC5BB50F-ONC12577B5.0025413E-C12577B5.00263D39@transmode.se>
Message-ID: <OF2426448C.2DD5559B-ONC12577B5.002AC992-C12577B5.002B0177@transmode.se>

> With 2.6.35 JFFS2 takes a very long time cp files while it erases:
>  cp big_file test
>  rm test
>  cp big_file test
> The last cp op. takes several times longer because JFFS2 is erasing.
> Revering the patches I helped out with make JFFS2 go fast again:
>   jffs2: Stop triggering block erases from jffs2_write_super()
>   jffs2: Rename jffs2_erase_pending_trigger() to jffs2_dirty_trigger()
>   jffs2: Use jffs2_garbage_collect_trigger() to trigger pending erases
>   jffs2: Require jffs2_garbage_collect_trigger() to be called with lock held
>   jffs2: Wake GC thread when there are blocks to be erased
>   jffs2: Erase pending blocks in GC pass, avoid invalid -EIO return
>
> The final patches were somewhat different than the ones I originally wrote
> and I THINK those didn't make JFFS2 go this slow.
>
> I suspect there is a locking problem somewhere.

Commenting out this makes JFFS2 fast again:
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f5e96bd..bce3a30 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -213,7 +213,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 		mutex_unlock(&c->alloc_sem);
 		return ret;
 	}
-
+#if 0
 	/* If there are any blocks which need erasing, erase them now */
 	if (!list_empty(&c->erase_complete_list) ||
 	    !list_empty(&c->erase_pending_list)) {
@@ -226,7 +226,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 		D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
 		spin_lock(&c->erase_completion_lock);
 	}
-
+#endif
 	/* First, work out which block we're garbage-collecting */
 	jeb = c->gcblock;

Seems to me that jffs2_garbage_collect_pass() is trying too much.
David?

      Jocke



From joakim.tjernlund at transmode.se  Thu Oct  7 08:00:20 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 14:00:20 +0200
Subject: JFFS2 very slow when erasing
In-Reply-To: <OF2426448C.2DD5559B-ONC12577B5.002AC992-C12577B5.002B0177@transmode.se>
References: <OF23585AD5.AC5BB50F-ONC12577B5.0025413E-C12577B5.00263D39@transmode.se>
	<OF2426448C.2DD5559B-ONC12577B5.002AC992-C12577B5.002B0177@transmode.se>
Message-ID: <OFFCEBB9A1.311BB67A-ONC12577B5.0041BA45-C12577B5.0041F321@transmode.se>

> > With 2.6.35 JFFS2 takes a very long time cp files while it erases:
> >  cp big_file test
> >  rm test
> >  cp big_file test
> > The last cp op. takes several times longer because JFFS2 is erasing.
> > Revering the patches I helped out with make JFFS2 go fast again:
> >   jffs2: Stop triggering block erases from jffs2_write_super()
> >   jffs2: Rename jffs2_erase_pending_trigger() to jffs2_dirty_trigger()
> >   jffs2: Use jffs2_garbage_collect_trigger() to trigger pending erases
> >   jffs2: Require jffs2_garbage_collect_trigger() to be called with lock held
> >   jffs2: Wake GC thread when there are blocks to be erased
> >   jffs2: Erase pending blocks in GC pass, avoid invalid -EIO return
> >
> > The final patches were somewhat different than the ones I originally wrote
> > and I THINK those didn't make JFFS2 go this slow.
> >
> > I suspect there is a locking problem somewhere.
>
> Commenting out this makes JFFS2 fast again:
> diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
> index f5e96bd..bce3a30 100644
> --- a/fs/jffs2/gc.c
> +++ b/fs/jffs2/gc.c
> @@ -213,7 +213,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
>        mutex_unlock(&c->alloc_sem);
>        return ret;
>     }
> -
> +#if 0
>     /* If there are any blocks which need erasing, erase them now */
>     if (!list_empty(&c->erase_complete_list) ||
>         !list_empty(&c->erase_pending_list)) {
> @@ -226,7 +226,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
>        D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
>        spin_lock(&c->erase_completion_lock);
>     }
> -
> +#endif
>     /* First, work out which block we're garbage-collecting */
>     jeb = c->gcblock;
>
> Seems to me that jffs2_garbage_collect_pass() is trying too much.
> David?

So, if I release the alloc_sem before erase thing gets back to normal.
Is releasing the alloc_sem bad here?

diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f5e96bd..042ac66 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -218,13 +218,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 	if (!list_empty(&c->erase_complete_list) ||
 	    !list_empty(&c->erase_pending_list)) {
 		spin_unlock(&c->erase_completion_lock);
+		mutex_unlock(&c->alloc_sem);
 		D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n"));
 		if (jffs2_erase_pending_blocks(c, 1)) {
-			mutex_unlock(&c->alloc_sem);
 			return 0;
 		}
 		D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
 		spin_lock(&c->erase_completion_lock);
+		mutex_lock(&c->alloc_sem);
 	}

 	/* First, work out which block we're garbage-collecting */



From savinay.dharmappa at ti.com  Thu Oct  7 07:31:14 2010
From: savinay.dharmappa at ti.com (Savinay Dharmappa)
Date: Thu,  7 Oct 2010 17:01:14 +0530
Subject: [PATCH 1/2] mtd: NOR flash driver for OMAP-L137/AM17x
Message-ID: <1286451074-12765-1-git-send-email-savinay.dharmappa@ti.com>

From: David Griego <dgriego at mvista.com>

OMAP-L137/AM17x has limited number of dedicated EMIFA
address pins, enough to interface directly to an SDRAM.
If a device such as an asynchronous flash needs to be
attached to the EMIFA, then either GPIO pins or a chip
select may be used to control the flash device's upper
address lines.

This patch adds support for the NOR flash on the OMAP-L137/
AM17x user interface daughter board using the latch-addr-flash
MTD mapping driver which allows flashes to be partially
physically addressed. The upper address lines are set by
a board specific code which is a separate patch.

Signed-off-by: Aleksey Makarov <amakarov at ru.mvista.com>
Signed-off-by: Sergei Shtylyov <sshtylyov at ru.mvista.com>
Signed-off-by: Savinay Dharmappa <savinay.dharmappa at ti.com>
---
 drivers/mtd/maps/Kconfig             |    9 +
 drivers/mtd/maps/Makefile            |    1 +
 drivers/mtd/maps/latch-addr-flash.c  |  271 ++++++++++++++++++++++++++++++++++
 include/linux/mtd/latch-addr-flash.h |   29 ++++
 4 files changed, 310 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/maps/latch-addr-flash.c
 create mode 100644 include/linux/mtd/latch-addr-flash.h

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 701d942..b794ea2 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -543,4 +543,13 @@ config MTD_PISMO
 
 	  When built as a module, it will be called pismo.ko
 
+config MTD_LATCH_ADDR
+        tristate "Latch-assisted Flash Chip Support"
+        depends on MTD_COMPLEX_MAPPINGS
+        help
+          Map driver which allows flashes to be partially physically addressed
+          and have the upper address lines set by a board specific code.
+
+          If compiled as a module, it will be called latch-addr-flash.
+
 endmenu
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index f216bb5..35c3573 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_MTD_BFIN_ASYNC)	+= bfin-async-flash.o
 obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
 obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
+obj-$(CONFIG_MTD_LATCH_ADDR)	+= latch-addr-flash.o
diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
new file mode 100644
index 0000000..e3a7f91
--- /dev/null
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -0,0 +1,271 @@
+/*
+ * Interface for NOR flash driver whose high address lines are latched
+ *
+ * Copyright 2000 Nicolas Pitre <nico at cam.org>
+ * Copyright 2005-2008 Analog Devices Inc.
+ * Coyright (C) 2008 MontaVista Software, Inc. <source at mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "latch-addr-flash"
+
+struct latch_addr_flash_info {
+	struct mtd_info		*mtd;
+	struct map_info		map;
+	struct resource		*res;
+
+	void			(*set_window)(unsigned long offset, void *data);
+	void			*data;
+
+	/* cache; could be found out of res */
+	unsigned long		win_mask;
+
+	int			nr_parts;
+	struct mtd_partition	*parts;
+
+	spinlock_t		lock;
+};
+
+static map_word lf_read(struct map_info *map, unsigned long ofs)
+{
+	struct latch_addr_flash_info *info;
+	map_word datum;
+
+	info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+	spin_lock(&info->lock);
+
+	info->set_window(ofs, info->data);
+	datum = inline_map_read(map, info->win_mask & ofs);
+
+	spin_unlock(&info->lock);
+
+	return datum;
+}
+
+static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
+{
+	struct latch_addr_flash_info *info;
+
+	info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+	spin_lock(&info->lock);
+
+	info->set_window(ofs, info->data);
+	inline_map_write(map, datum, info->win_mask & ofs);
+
+	spin_unlock(&info->lock);
+}
+
+static void lf_copy_from(struct map_info *map, void *to,
+		unsigned long from, ssize_t len)
+{
+	struct latch_addr_flash_info *info =
+		(struct latch_addr_flash_info *) map->map_priv_1;
+	unsigned n;
+
+	while (len > 0) {
+		n = info->win_mask + 1 - (from & info->win_mask);
+		if (n > len)
+			n = len;
+
+		spin_lock(&info->lock);
+
+		info->set_window(from, info->data);
+		memcpy_fromio(to, map->virt + (from & info->win_mask), n);
+
+		spin_unlock(&info->lock);
+
+		to += n;
+		from += n;
+		len -= n;
+	}
+}
+
+static const char *rom_probe_types[] = { "cfi_probe", NULL };
+
+static const char *part_probe_types[] = { "cmdlinepart", NULL };
+
+static int latch_addr_flash_remove(struct platform_device *dev)
+{
+	struct latch_addr_flash_info *info;
+	struct latch_addr_flash_data *latch_addr_data;
+
+	info = platform_get_drvdata(dev);
+	if (info == NULL)
+		return 0;
+	platform_set_drvdata(dev, NULL);
+
+	latch_addr_data = dev->dev.platform_data;
+
+	if (info->mtd != NULL) {
+		if (mtd_has_partitions()) {
+			if (info->nr_parts) {
+				del_mtd_partitions(info->mtd);
+				kfree(info->parts);
+			} else if (latch_addr_data->nr_parts) {
+				del_mtd_partitions(info->mtd);
+			} else {
+				del_mtd_device(info->mtd);
+			}
+		} else {
+			del_mtd_device(info->mtd);
+		}
+		map_destroy(info->mtd);
+	}
+
+	if (info->map.virt != NULL)
+		iounmap(info->map.virt);
+
+	if (info->res != NULL)
+		release_mem_region(info->res->start, resource_size(info->res));
+
+	kfree(info);
+
+	if (latch_addr_data->done)
+		latch_addr_data->done(latch_addr_data->data);
+
+	return 0;
+}
+
+static int __devinit latch_addr_flash_probe(struct platform_device *dev)
+{
+	struct latch_addr_flash_data *latch_addr_data;
+	struct latch_addr_flash_info *info;
+	resource_size_t win_base = dev->resource->start;
+	resource_size_t win_size = resource_size(dev->resource);
+	const char **probe_type;
+	int chipsel;
+	int err;
+
+	latch_addr_data = dev->dev.platform_data;
+	if (latch_addr_data == NULL)
+		return -ENODEV;
+
+	pr_notice("latch-addr platform flash device: %#llx byte "
+		  "window at %#.8llx\n",
+		  (unsigned long long)win_size, (unsigned long long)win_base);
+
+	chipsel = dev->id;
+
+	if (latch_addr_data->init) {
+		err = latch_addr_data->init(latch_addr_data->data, chipsel);
+		if (err != 0)
+			return err;
+	}
+
+	info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
+	if (info == NULL) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	platform_set_drvdata(dev, info);
+
+	info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
+	if (info->res == NULL) {
+		dev_err(&dev->dev, "Could not reserve memory region\n");
+		err = -EBUSY;
+		goto free_info;
+	}
+
+	info->map.name		= DRIVER_NAME;
+	info->map.size		= latch_addr_data->size;
+	info->map.bankwidth	= latch_addr_data->width;
+
+	info->map.phys		= NO_XIP;
+	info->map.virt		= ioremap(win_base, win_size);
+	if (!info->map.virt) {
+		err = -ENOMEM;
+		goto free_res;
+	}
+
+	info->map.map_priv_1	= (unsigned long)info;
+
+	info->map.read		= lf_read;
+	info->map.copy_from	= lf_copy_from;
+	info->map.write		= lf_write;
+	info->set_window	= latch_addr_data->set_window;
+	info->data		= latch_addr_data->data;
+	info->win_mask		= win_size - 1;
+
+	spin_lock_init(&info->lock);
+
+	for (probe_type = rom_probe_types; !info->mtd && *probe_type;
+		probe_type++)
+		info->mtd = do_map_probe(*probe_type, &info->map);
+
+	if (info->mtd == NULL) {
+		dev_err(&dev->dev, "map_probe failed\n");
+		err = -ENODEV;
+		goto iounmap;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+	if (mtd_has_partitions()) {
+
+		err = parse_mtd_partitions(info->mtd, part_probe_types,
+					   &info->parts, 0);
+		if (err > 0) {
+			add_mtd_partitions(info->mtd, info->parts, err);
+			return 0;
+		}
+		if (latch_addr_data->nr_parts) {
+			pr_notice("Using latch-addr-flash partition information\n");
+			add_mtd_partitions(info->mtd, latch_addr_data->parts,
+					latch_addr_data->nr_parts);
+			return 0;
+		}
+	}
+	add_mtd_device(info->mtd);
+	return 0;
+
+iounmap:
+	iounmap(info->map.virt);
+free_res:
+	release_mem_region(info->res->start, resource_size(info->res));
+free_info:
+	kfree(info);
+done:
+	if (latch_addr_data->done)
+		latch_addr_data->done(latch_addr_data->data);
+	return err;
+}
+
+static struct platform_driver latch_addr_flash_driver = {
+	.probe		= latch_addr_flash_probe,
+	.remove		= __devexit_p(latch_addr_flash_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init latch_addr_flash_init(void)
+{
+	return platform_driver_register(&latch_addr_flash_driver);
+}
+module_init(latch_addr_flash_init);
+
+static void __exit latch_addr_flash_exit(void)
+{
+	platform_driver_unregister(&latch_addr_flash_driver);
+}
+module_exit(latch_addr_flash_exit);
+
+MODULE_AUTHOR("David Griego <dgriego at mvista.com>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
+		"address lines being set board specifically");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mtd/latch-addr-flash.h b/include/linux/mtd/latch-addr-flash.h
new file mode 100644
index 0000000..c77e7c9
--- /dev/null
+++ b/include/linux/mtd/latch-addr-flash.h
@@ -0,0 +1,29 @@
+/*
+ * Interface for NOR flash driver whose high address lines are latched
+ *
+ * Copyright (C) 2008 MontaVista Software, Inc. <source at mvista.com>
+ *
+ * This file is licensed underthe terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+#ifndef __LATCH_ADDR_FLASH__
+#define __LATCH_ADDR_FLASH__
+
+struct map_info;
+struct mtd_partition;
+
+struct latch_addr_flash_data {
+	unsigned int		width;
+	unsigned int		size;
+
+	int			(*init)(void *data, int cs);
+	void			(*done)(void *data);
+	void			(*set_window)(unsigned long offset, void *data);
+	void			*data;
+
+	unsigned int		nr_parts;
+	struct mtd_partition	*parts;
+};
+
+#endif
-- 
1.5.6



From savinay.dharmappa at ti.com  Thu Oct  7 07:34:32 2010
From: savinay.dharmappa at ti.com (Savinay Dharmappa)
Date: Thu,  7 Oct 2010 17:04:32 +0530
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR flash
	driver
Message-ID: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>

From: David Griego <dgriego at mvista.com>

Adds platform support for OMAP-L137/AM17x NOR flash driver.

Also, configures chip select 3 to control NOR flash's upper
address lines.

Signed-off-by: Aleksey Makarov <amakarov at ru.mvista.com>
Signed-off-by: Sergei Shtylyov <sshtylyov at ru.mvista.com>
Signed-off-by: Savinay Dharmappa <savinay.dharmappa at ti.com>
---
 arch/arm/mach-davinci/Kconfig           |    8 +
 arch/arm/mach-davinci/board-da830-evm.c |  224 +++++++++++++++++++++++++++++++
 2 files changed, 232 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 9aca60c..baa39ee 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -142,6 +142,14 @@ config DA830_UI_NAND
 	help
 	  Say Y here to use the NAND flash. Do not forget to setup
 	  the switch correctly.
+
+config DA830_UI_NOR
+        bool "NOR flash"
+        help
+          Configure this option to specify the that AEMIF CE2/CE3 will be used to
+          communicate to the NOR flash. Do not forget to setup the switch SW1
+          on UI card correctly.
+
 endchoice
 
 config MACH_DAVINCI_DA850_EVM
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 1bb89d3..9f18efc 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -20,6 +20,8 @@
 #include <linux/i2c/at24.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/clk.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -429,6 +431,226 @@ static inline void da830_evm_init_nand(int mux_mode)
 static inline void da830_evm_init_nand(int mux_mode) { }
 #endif
 
+#ifdef CONFIG_DA830_UI_NOR
+/*
+ * Number of Address line going to the NOR flash that are latched using
+ * AEMIF address lines  B_EMIF_BA0-B_EMIF_A12  on CS2.
+ */
+#define NOR_WINDOW_SIZE_LOG2     15
+#define NOR_WINDOW_SIZE         (1 << NOR_WINDOW_SIZE_LOG2)
+
+static struct {
+	struct clk *clk;
+	struct {
+		struct resource *res;
+		void __iomem *addr;
+	} latch, aemif;
+} da830_evm_nor;
+
+static struct davinci_aemif_timing da830_evm_norflash_timing = {
+	.wsetup		= 0,
+	.wstrobe	= 40,
+	.whold		= 0,
+	.rsetup		= 0,
+	.rstrobe	= 130,
+	.rhold		= 0,
+	.ta		= 20,
+};
+
+static void da830_evm_nor_set_window(unsigned long offset, void *data)
+{
+	/*
+	 * CS2 and CS3 address lines are used to address nor flash. Address
+	 * line A0-A14 going to the NOR flash are latched using AEMIF address
+	 * lines B_EMIF_BA0-B_EMIF_A12 on CS2. Address lines A15-A23 of the
+	 * NOR flash are latched using AEMIF address lines B_EMIF_A0-B_EMIF_A6
+	 * on CS3. The offset argument received by this function is the offset
+	 * within NOR flash. Upper address is obtained  by shifting the offset
+	 * by the number of CS2 address lines used (13) and masking it with
+	 * complement of 3 (2 address lines used to address banks) and adding
+	 * the resultant offset value to CS3 base address. Writing a zero to
+	 * this address will latch the upper address lines.
+	 */
+	writeb(0, da830_evm_nor.latch.addr +
+		(~3UL & (offset >> (NOR_WINDOW_SIZE_LOG2 - 2))));
+}
+
+static void da830_evm_nor_done(void *data)
+{
+	clk_disable(da830_evm_nor.clk);
+	clk_put(da830_evm_nor.clk);
+	iounmap(da830_evm_nor.latch.addr);
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	iounmap(da830_evm_nor.aemif.addr);
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+}
+
+static int da830_evm_nor_init(void *data, int cs)
+{
+	/* Turn on AEMIF clocks */
+	da830_evm_nor.clk = clk_get(NULL, "aemif");
+	if (IS_ERR(da830_evm_nor.clk)) {
+		pr_err("%s: could not get AEMIF clock\n", __func__);
+		da830_evm_nor.clk = NULL;
+		return -ENODEV;
+	}
+	clk_enable(da830_evm_nor.clk);
+
+	da830_evm_nor.aemif.res = request_mem_region(DA8XX_AEMIF_CTL_BASE,
+						     SZ_32K, "AEMIF control");
+	if (da830_evm_nor.aemif.res == NULL) {
+		pr_err("%s: could not request AEMIF control region\n",
+			__func__);
+		goto err_aemif_region;
+	}
+
+	da830_evm_nor.aemif.addr = ioremap_nocache(DA8XX_AEMIF_CTL_BASE,
+						   SZ_32K);
+	if (da830_evm_nor.aemif.addr == NULL) {
+		pr_err("%s: could not remap AEMIF control region\n", __func__);
+		goto err_aemif_ioremap;
+	}
+
+	/* Setup AEMIF -- timings, etc. */
+
+	/* Set maximum wait cycles */
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+						da830_evm_nor.aemif.addr, cs);
+
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+					da830_evm_nor.aemif.addr, cs + 1);
+
+	/* Setup the window to access the latch */
+	da830_evm_nor.latch.res =
+		request_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE,
+				   "DA830 UI NOR address latch");
+	if (da830_evm_nor.latch.res == NULL) {
+		pr_err("%s: could not request address latch region\n",
+			__func__);
+		goto err_latch_region;
+	}
+
+	da830_evm_nor.latch.addr =
+		ioremap_nocache(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	if (da830_evm_nor.latch.addr == NULL) {
+		pr_err("%s: could not remap address latch region\n", __func__);
+		goto err_latch_ioremap;
+	}
+	return 0;
+
+err_aemif_region:
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+	da830_evm_nor.aemif.res = NULL;
+	return -EBUSY;
+
+err_aemif_ioremap:
+	iounmap(da830_evm_nor.aemif.addr);
+	da830_evm_nor.aemif.addr = NULL;
+	return -ENOMEM;
+
+err_latch_region:
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	da830_evm_nor.latch.res = NULL;
+	return -EBUSY;
+
+err_latch_ioremap:
+	iounmap(da830_evm_nor.latch.addr);
+	da830_evm_nor.latch.addr = NULL;
+	return -ENOMEM;
+}
+
+static struct mtd_partition da830_evm_nor_partitions[] = {
+	/* bootloader (U-Boot, etc) in first 2 sectors */
+	[0] = {
+		.name           = "bootloader",
+		.offset		= 0,
+		.size           = SZ_128K,
+		.mask_flags     = MTD_WRITEABLE, /* force read-only */
+	},
+	/* bootloader parameters in the next 1 sector */
+	[1] = {
+		.name           = "params",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_64K,
+	},
+	/* kernel */
+	[2] = {
+		.name           = "kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_2M,
+	},
+	/* file system */
+	[3] = {
+		.name           = "filesystem",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	}
+};
+
+static struct latch_addr_flash_data da830_evm_nor_pdata = {
+	.width          = 1,
+	.size           = SZ_4M,
+	.init           = da830_evm_nor_init,
+	.done           = da830_evm_nor_done,
+	.set_window     = da830_evm_nor_set_window,
+	.nr_parts       = ARRAY_SIZE(da830_evm_nor_partitions),
+	.parts          = da830_evm_nor_partitions,
+};
+
+static struct resource da830_evm_nor_resource[] = {
+	[0] = {
+		.start  = DA8XX_AEMIF_CS2_BASE,
+		.end    = DA8XX_AEMIF_CS2_BASE + NOR_WINDOW_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = DA8XX_AEMIF_CS3_BASE,
+		.end    = DA8XX_AEMIF_CS3_BASE + PAGE_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = DA8XX_AEMIF_CTL_BASE,
+		.end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+		.flags  = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device da830_evm_nor_device = {
+	.name           = "latch-addr-flash",
+	.id             = 0,
+	.dev            = {
+		.platform_data  = &da830_evm_nor_pdata,
+	},
+	.num_resources  = ARRAY_SIZE(da830_evm_nor_resource),
+	.resource       = da830_evm_nor_resource,
+};
+
+static inline void da830_evm_init_nor(int mux_mode)
+{
+	int ret;
+
+	if (HAS_MMC) {
+		pr_warning("WARNING: both MMC/SD and NOR are "
+				"enabled, but they share AEMIF pins.\n"
+					"\tDisable MMC/SD for NOR support.\n");
+		return;
+	}
+
+	ret = davinci_cfg_reg_list(da830_evm_emif25_pins);
+	if (ret)
+		pr_warning("da830_evm_init: emif25 mux setup failed: %d\n",
+			  ret);
+
+	ret = platform_device_register(&da830_evm_nor_device);
+	if (ret)
+		pr_warning("da830_evm_init: NOR device not registered.\n");
+
+	gpio_direction_output(mux_mode, 1);
+}
+#else
+static inline void da830_evm_init_nor(int mux_mode) { }
+#endif  /* CONFIG_DA830_UI_NOR */
+
 #ifdef CONFIG_DA830_UI_LCD
 static inline void da830_evm_init_lcdc(int mux_mode)
 {
@@ -469,6 +691,8 @@ static int __init da830_evm_ui_expander_setup(struct i2c_client *client,
 
 	da830_evm_init_nand(gpio + 6);
 
+	da830_evm_init_nor(gpio + 6);
+
 	return 0;
 }
 
-- 
1.5.6



From nm at ti.com  Thu Oct  7 08:17:08 2010
From: nm at ti.com (Menon, Nishanth)
Date: Thu, 7 Oct 2010 07:17:08 -0500
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <1285063280-4057-10-git-send-email-manjugk@ti.com>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
Message-ID: <7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>


> -----Original Message-----
> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> owner at vger.kernel.org] On Behalf Of G, Manjunath Kondaiah
> Sent: Tuesday, September 21, 2010 5:01 AM
> To: linux-omap at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org
> Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
> read/write
> 
> Following sparse warnings exists due to use of writel/w and readl/w
> functions.
> 
> This patch fixes the sparse warnings by converting readl/w functions usage
> into
> __raw_readl/__raw_readw functions.

Apologies on bringing up an old topic here -> Is'nt it better to fix readl/w or writel/w than replacing it with __raw_readl/w etc?



Regards,
Nishanth Menon

[...]


From sshtylyov at mvista.com  Thu Oct  7 11:05:28 2010
From: sshtylyov at mvista.com (Sergei Shtylyov)
Date: Thu, 07 Oct 2010 19:05:28 +0400
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
Message-ID: <4CADE1B8.50800@mvista.com>

Hello.

Savinay Dharmappa wrote:

> From: David Griego <dgriego at mvista.com>

    And that's after I have told you this code is not authored by David, but by 
Aleksey Makarov... :-(

> Adds platform support for OMAP-L137/AM17x NOR flash driver.

> Also, configures chip select 3 to control NOR flash's upper
> address lines.

> Signed-off-by: Aleksey Makarov <amakarov at ru.mvista.com>
> Signed-off-by: Sergei Shtylyov <sshtylyov at ru.mvista.com>
> Signed-off-by: Savinay Dharmappa <savinay.dharmappa at ti.com>

    Moreover, I'm seeing that you've done some incorrect changes to the 
previously correct code. NAK.

[...]

>  config MACH_DAVINCI_DA850_EVM
> diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
> index 1bb89d3..9f18efc 100644
> --- a/arch/arm/mach-davinci/board-da830-evm.c
> +++ b/arch/arm/mach-davinci/board-da830-evm.c
[...]
> @@ -429,6 +431,226 @@ static inline void da830_evm_init_nand(int mux_mode)
[...]
> +static void da830_evm_nor_done(void *data)
> +{
> +	clk_disable(da830_evm_nor.clk);
> +	clk_put(da830_evm_nor.clk);
> +	iounmap(da830_evm_nor.latch.addr);
> +	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
> +	iounmap(da830_evm_nor.aemif.addr);
> +	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
> +}

    Why you've changed this function which was useful also for the error cleanup 
before?

> +static int da830_evm_nor_init(void *data, int cs)
> +{
> +	/* Turn on AEMIF clocks */
> +	da830_evm_nor.clk = clk_get(NULL, "aemif");
> +	if (IS_ERR(da830_evm_nor.clk)) {
> +		pr_err("%s: could not get AEMIF clock\n", __func__);
> +		da830_evm_nor.clk = NULL;
> +		return -ENODEV;
> +	}
> +	clk_enable(da830_evm_nor.clk);
> +
> +	da830_evm_nor.aemif.res = request_mem_region(DA8XX_AEMIF_CTL_BASE,
> +						     SZ_32K, "AEMIF control");
> +	if (da830_evm_nor.aemif.res == NULL) {
> +		pr_err("%s: could not request AEMIF control region\n",
> +			__func__);
> +		goto err_aemif_region;

    I wonder why you used goto's at all. Anyway, the error cleanup code is 
completely broken now.

> +	}
> +
> +	da830_evm_nor.aemif.addr = ioremap_nocache(DA8XX_AEMIF_CTL_BASE,
> +						   SZ_32K);
> +	if (da830_evm_nor.aemif.addr == NULL) {
> +		pr_err("%s: could not remap AEMIF control region\n", __func__);
> +		goto err_aemif_ioremap;
> +	}
> +
> +	/* Setup AEMIF -- timings, etc. */
> +
> +	/* Set maximum wait cycles */
> +	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
> +						da830_evm_nor.aemif.addr, cs);
> +
> +	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
> +					da830_evm_nor.aemif.addr, cs + 1);
> +
> +	/* Setup the window to access the latch */
> +	da830_evm_nor.latch.res =
> +		request_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE,
> +				   "DA830 UI NOR address latch");
> +	if (da830_evm_nor.latch.res == NULL) {
> +		pr_err("%s: could not request address latch region\n",
> +			__func__);
> +		goto err_latch_region;
> +	}
> +
> +	da830_evm_nor.latch.addr =
> +		ioremap_nocache(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
> +	if (da830_evm_nor.latch.addr == NULL) {
> +		pr_err("%s: could not remap address latch region\n", __func__);
> +		goto err_latch_ioremap;
> +	}
> +	return 0;
> +
> +err_aemif_region:
> +	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);

    Why release what you've just failed to request?!

> +	da830_evm_nor.aemif.res = NULL;

    Useless assignment.

> +	return -EBUSY;

    And you're not calling clk_disable().

> +err_aemif_ioremap:
> +	iounmap(da830_evm_nor.aemif.addr);

    Why unmap what you've just failed to map?! da830_evm_nor.aemif.addr is NULL.

> +	da830_evm_nor.aemif.addr = NULL;

    Useless assignment.

> +	return -ENOMEM;

    You're not calling release_mem_region() and clk_disable().

> +err_latch_region:
> +	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);

    Why release what you've just failed to request?!

> +	da830_evm_nor.latch.res = NULL;

    Useless assginment.

> +	return -EBUSY;

    You're not calling iounmap() and release_mem_region() for the NOR flash 
region and also not calling clk_disable().

> +
> +err_latch_ioremap:
> +	iounmap(da830_evm_nor.latch.addr);

    Why unmap what you've just failed to map?! da830_evm_nor.latch.addr is NULL.

> +	da830_evm_nor.latch.addr = NULL;

    Useless assginment.

> +	return -ENOMEM;

    You're not release_mem_region() for the latch region, not calling iounmap() 
and release_mem_region() for the NOR flash region and also not calling 
clk_disable().

> +}
[...]

    Your changes made me doubt that you actually understood the code well enough 
before doing them...

WBR, Sergei



From joakim.tjernlund at transmode.se  Thu Oct  7 11:33:36 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 17:33:36 +0200
Subject: [doesn't work] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <20101006210036.92C229D401B@zog.reactivated.net>
References: <20101006210036.92C229D401B@zog.reactivated.net>
Message-ID: <OFB9367F81.DD135AF9-ONC12577B5.00550D41-C12577B5.00557990@transmode.se>

>
> I'm trying to upstream an old OLPC patch which greatly speeds up mounting
> of large jffs2 volumes.
> Took a stab at a suggestion from David (shown here) but it crashes badly.
> Causes lots of WARNINGs to be triggered from __mark_inode_dirty.

Does #define INOCACHE_HASHSIZE <something bigger> work?

if so I would guess something is using inocache_hashsize before
it is initialized.

Perhaps it is time to up INOCACHE_HASHSIZE to 256 or 512?

     Jocke



From Joakim.Tjernlund at transmode.se  Thu Oct  7 12:01:44 2010
From: Joakim.Tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 18:01:44 +0200
Subject: [PATCH] jffs2: Fix serious write stall due to erase
Message-ID: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>

Drop the alloc_sem before erasing flash in
jffs2_garbage_collect_pass().
Otherwise writes are put on hold until the erase
has finised.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
---

 I am fairly sure it is safe to unlock the alloc_sem before
 calling jffs2_erase_pending_blocks(). Extra confirmation
 would be great though.

 This problem was introduced in 2.6.35

 fs/jffs2/gc.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f5e96bd..b5f7175 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -218,13 +218,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 	if (!list_empty(&c->erase_complete_list) ||
 	    !list_empty(&c->erase_pending_list)) {
 		spin_unlock(&c->erase_completion_lock);
+		mutex_unlock(&c->alloc_sem);
 		D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n"));
-		if (jffs2_erase_pending_blocks(c, 1)) {
-			mutex_unlock(&c->alloc_sem);
+		if (jffs2_erase_pending_blocks(c, 1))
 			return 0;
-		}
+
 		D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
 		spin_lock(&c->erase_completion_lock);
+		mutex_lock(&c->alloc_sem);
 	}
 
 	/* First, work out which block we're garbage-collecting */
-- 
1.7.2.2



From dsd at laptop.org  Thu Oct  7 12:09:59 2010
From: dsd at laptop.org (Daniel Drake)
Date: Thu, 7 Oct 2010 17:09:59 +0100
Subject: [doesn't work] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <OFB9367F81.DD135AF9-ONC12577B5.00550D41-C12577B5.00557990@transmode.se>
References: <20101006210036.92C229D401B@zog.reactivated.net>
	<OFB9367F81.DD135AF9-ONC12577B5.00550D41-C12577B5.00557990@transmode.se>
Message-ID: <AANLkTikGL87-J-EbRiStmRaVN=g-rH7XL6SNB0zYwuaQ@mail.gmail.com>

On 7 October 2010 16:33, Joakim Tjernlund <joakim.tjernlund at transmode.se> wrote:
> Does #define INOCACHE_HASHSIZE <something bigger> work?

Yes. Tested for years as value 1024 in OLPC builds.

> if so I would guess something is using inocache_hashsize before
> it is initialized.

Me too. But it's initialized early, at the same time as inocache_list.
And all users of inocache_hashsize use the list at the same time. So
if that were as obvious as it sounds, we'd be seeing bigger problems.

Thanks for your input!
Daniel


From joakim.tjernlund at transmode.se  Thu Oct  7 12:24:23 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 18:24:23 +0200
Subject: [doesn't work] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <AANLkTikGL87-J-EbRiStmRaVN=g-rH7XL6SNB0zYwuaQ@mail.gmail.com>
References: <20101006210036.92C229D401B@zog.reactivated.net>	<OFB9367F81.DD135AF9-ONC12577B5.00550D41-C12577B5.00557990@transmode.se>
	<AANLkTikGL87-J-EbRiStmRaVN=g-rH7XL6SNB0zYwuaQ@mail.gmail.com>
Message-ID: <OF67B76228.51E20AF7-ONC12577B5.0059D5BD-C12577B5.005A1FBE@transmode.se>

dsd.olpc at gmail.com wrote on 2010/10/07 18:09:59:
>
> On 7 October 2010 16:33, Joakim Tjernlund <joakim.tjernlund at transmode.se> wrote:
> > Does #define INOCACHE_HASHSIZE <something bigger> work?
>
> Yes. Tested for years as value 1024 in OLPC builds.

OK, Good.

>
> > if so I would guess something is using inocache_hashsize before
> > it is initialized.
>
> Me too. But it's initialized early, at the same time as inocache_list.
> And all users of inocache_hashsize use the list at the same time. So
> if that were as obvious as it sounds, we'd be seeing bigger problems.

Sure, but something might still use it before. Try adding an
assert(inocache_hashsize) wherever you use inocache_hashsize.



From Joakim.Tjernlund at transmode.se  Thu Oct  7 12:29:46 2010
From: Joakim.Tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 18:29:46 +0200
Subject: [PATCH] jffs2: Do not assume erase will fail
Message-ID: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>

Test if it did and then abort.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
---
 fs/jffs2/nodemgmt.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 694aa5b..49ee5de 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
 		spin_lock(&c->erase_completion_lock);
 
 		/* An erase may have failed, decreasing the
-		   amount of free space available. So we must
-		   restart from the beginning */
-		return -EAGAIN;
+		   amount of free space available. */
+		if (list_empty(&c->free_list))
+			return -EAGAIN; /* restart from the beginning */
 	}
 
 	next = c->free_list.next;
-- 
1.7.2.2



From Joakim.Tjernlund at transmode.se  Thu Oct  7 13:09:34 2010
From: Joakim.Tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 7 Oct 2010 19:09:34 +0200
Subject: [PATCH] jffs2: Reduce excessive scan of empty blocks
Message-ID: <1286471374-25840-1-git-send-email-Joakim.Tjernlund@transmode.se>

Scanning 1024 bytes to see if an EB is empty is a bit much.
Lower it to 256 bytes and make sure the while loop is
optimized.

Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
---
 fs/jffs2/scan.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 3131860..4657918 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -20,7 +20,7 @@
 #include "summary.h"
 #include "debug.h"
 
-#define DEFAULT_EMPTY_SCAN_SIZE 1024
+#define DEFAULT_EMPTY_SCAN_SIZE 256
 
 #define noisy_printk(noise, args...) do { \
 	if (*(noise)) { \
@@ -435,7 +435,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
 	struct jffs2_unknown_node *node;
 	struct jffs2_unknown_node crcnode;
-	uint32_t ofs, prevofs;
+	uint32_t ofs, prevofs, max_ofs;
 	uint32_t hdr_crc, buf_ofs, buf_len;
 	int err;
 	int noise = 0;
@@ -550,12 +550,12 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
 
 	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
 	ofs = 0;
-
-	/* Scan only 4KiB of 0xFF before declaring it's empty */
-	while(ofs < EMPTY_SCAN_SIZE(c->sector_size) && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
+	max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
+	/* Scan only EMPTY_SCAN_SIZE of 0xFF before declaring it's empty */
+	while(ofs < max_ofs && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
 		ofs += 4;
 
-	if (ofs == EMPTY_SCAN_SIZE(c->sector_size)) {
+	if (ofs == max_ofs) {
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 		if (jffs2_cleanmarker_oob(c)) {
 			/* scan oob, take care of cleanmarker */
-- 
1.7.2.2



From vimal.newwork at gmail.com  Thu Oct  7 13:31:36 2010
From: vimal.newwork at gmail.com (Vimal Singh)
Date: Thu, 7 Oct 2010 23:01:36 +0530
Subject: Issue : jffs2 and ecc layout
In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B0356594397@dbde02.ent.ti.com>
References: <2A3DCF3DA181AD40BDE86A3150B27B6B03560990E3@dbde02.ent.ti.com>
	<2A3DCF3DA181AD40BDE86A3150B27B6B0356594397@dbde02.ent.ti.com>
Message-ID: <AANLkTi=y1JwSBrELd=KyUsmhitSCF2eWW9iYFg3a_-J4@mail.gmail.com>

On Mon, Oct 4, 2010 at 12:59 PM, Ghorai, Sukumar <s-ghorai at ti.com> wrote:
>
>
>> -----Original Message-----
>> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
>> owner at vger.kernel.org] On Behalf Of Ghorai, Sukumar
>> Sent: Tuesday, September 28, 2010 6:17 PM
>> To: linux-mtd at lists.infradead.org
>> Cc: linux-omap at vger.kernel.org
>> Subject: Issue : jffs2 and ecc layout
>>
>> Hi,
>> I was using the following ecc layout which is not working to mount the
>> jffs2 File-system. I was in 2.6.32 kernel and working; but same layout is
>> not working with latest 2.6 kernel.
>>
>> Observation is that - no read request issued to the driver (say omap2.c).
>>
>> # mount -t jffs2 /dev/mtdblock4 /mnt/nand
>> [?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes, read
>> 0 bytes, error -22
>> mount: Mounting /dev/mtdblock4 on /mnt/nand failed: Input/output error
>>
>> # dmesg
>> <3>[?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes,
>> read 0 bytes, error -22
>>
I do not think above issue has anything to do with the ECC layout.
But as I earlier pointed (in [1]), this change [2] has messed up
function 'omap_hwcontrol'.
All read/write functions read/write data from/to address
info->nand.IO_ADDR_(R/W), which is not set by new function
'gpmc_nand_write' (which still take care of writing address/cmd to
write registers). But since above pointer is not set (hence points to
address '0'), driver tries to read data from wrong location.

In fact, I would even suggest to try dumping nand command registers(or
use T32) and verify if commands issued were written correctly to
appropriate registers.



[1]: http://marc.info/?l=linux-omap&m=128302624528822&w=2
[2] commit: http://git.infradead.org/mtd-2.6.git/commitdiff/2c01946c6b9ebaa5a89710bc42ca224a7f52f227

-- 
Regards,
Vimal Singh


From vimal.newwork at gmail.com  Thu Oct  7 13:35:10 2010
From: vimal.newwork at gmail.com (Vimal Singh)
Date: Thu, 7 Oct 2010 23:05:10 +0530
Subject: [PATCH v3] OMAP: NAND: Fix static declaration warning
In-Reply-To: <1286315819-5906-1-git-send-email-manjugk@ti.com>
References: <1286315819-5906-1-git-send-email-manjugk@ti.com>
Message-ID: <AANLkTin-rjxxDpiN9V5CinWr4cCqH1QB=cEH+huEcxYv@mail.gmail.com>

On Wed, Oct 6, 2010 at 3:26 AM, G, Manjunath Kondaiah <manjugk at ti.com> wrote:
> This patch fixes sparse warning for static declaration of variable "use_dma"
>
> drivers/mtd/nand/omap2.c:114:11: warning: symbol 'use_dma' was not declared. Should it be static?
>
> Signed-off-by: G, Manjunath Kondaiah <manjugk at ti.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mtd at lists.infradead.org
> Cc: Tony Lindgren <tony at atomide.com>
> Cc: Nishanth Menon <nm at ti.com>
> ---
> Changes since v1:
> ?- no logical changes, patch seperated from series based Tony's suggestion.
>
> ?drivers/mtd/nand/omap2.c | ? ?4 ++--
> ?1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 133d515..439e80d 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -111,11 +111,11 @@ static int use_dma = 1;
> ?module_param(use_dma, bool, 0);
> ?MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
> ?#else
> -const int use_dma;
> +static const int use_dma;
> ?#endif
> ?#else
> ?const int use_prefetch;
> -const int use_dma;
> +static const int use_dma;

I did not understand, why did it not pointed same error for 'const int
use_prefetch'?

-- 
Regards,
Vimal Singh


From vimal.newwork at gmail.com  Thu Oct  7 13:39:49 2010
From: vimal.newwork at gmail.com (Vimal Singh)
Date: Thu, 7 Oct 2010 23:09:49 +0530
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <1285063280-4057-10-git-send-email-manjugk@ti.com>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
Message-ID: <AANLkTikUpZ9FxPUoQE64hJcT31GiAC7868MPCr=Bm_0o@mail.gmail.com>

On Tue, Sep 21, 2010 at 3:31 PM, G, Manjunath Kondaiah <manjugk at ti.com> wrote:
> Following sparse warnings exists due to use of writel/w and readl/w functions.
>
> This patch fixes the sparse warnings by converting readl/w functions usage into
> __raw_readl/__raw_readw functions.
>
[...]
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -481,7 +481,7 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
>
> ? ? ? ?len >>= 1;
> ? ? ? ?while (len--) {
> - ? ? ? ? ? ? ? if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R)))
> + ? ? ? ? ? ? ? if (*p++ != cpu_to_le16(__raw_readw(info->nand.IO_ADDR_R)))

There was an old comment to remove use of 'cpu_to_le16' from driver, I
just missed it. Can you rather use 'ioread16_rep' for reading data.

-- 
Regards,
Vimal Singh


From s-ghorai at ti.com  Thu Oct  7 14:09:38 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Thu, 7 Oct 2010 23:39:38 +0530
Subject: Issue : jffs2 and ecc layout
In-Reply-To: <AANLkTi=y1JwSBrELd=KyUsmhitSCF2eWW9iYFg3a_-J4@mail.gmail.com>
References: <2A3DCF3DA181AD40BDE86A3150B27B6B03560990E3@dbde02.ent.ti.com>
	<2A3DCF3DA181AD40BDE86A3150B27B6B0356594397@dbde02.ent.ti.com>
	<AANLkTi=y1JwSBrELd=KyUsmhitSCF2eWW9iYFg3a_-J4@mail.gmail.com>
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B03567115C3@dbde02.ent.ti.com>



> -----Original Message-----
> From: Vimal Singh [mailto:vimal.newwork at gmail.com]
> Sent: Thursday, October 07, 2010 11:02 PM
> To: Ghorai, Sukumar
> Cc: linux-mtd at lists.infradead.org; linux-omap at vger.kernel.org
> Subject: Re: Issue : jffs2 and ecc layout
> 
> On Mon, Oct 4, 2010 at 12:59 PM, Ghorai, Sukumar <s-ghorai at ti.com> wrote:
> >
> >
> >> -----Original Message-----
> >> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> >> owner at vger.kernel.org] On Behalf Of Ghorai, Sukumar
> >> Sent: Tuesday, September 28, 2010 6:17 PM
> >> To: linux-mtd at lists.infradead.org
> >> Cc: linux-omap at vger.kernel.org
> >> Subject: Issue : jffs2 and ecc layout
> >>
> >> Hi,
> >> I was using the following ecc layout which is not working to mount the
> >> jffs2 File-system. I was in 2.6.32 kernel and working; but same layout
> is
> >> not working with latest 2.6 kernel.
> >>
> >> Observation is that - no read request issued to the driver (say
> omap2.c).
> >>
> >> # mount -t jffs2 /dev/mtdblock4 /mnt/nand
> >> [?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes,
> read
> >> 0 bytes, error -22
> >> mount: Mounting /dev/mtdblock4 on /mnt/nand failed: Input/output error
> >>
> >> # dmesg
> >> <3>[?? 32.505218] cannot read OOB for EB at 00000000, requested 8 bytes,
> >> read 0 bytes, error -22
> >>
> I do not think above issue has anything to do with the ECC layout.
> But as I earlier pointed (in [1]), this change [2] has messed up
> function 'omap_hwcontrol'.
[Ghorai] in that case how other layout is working? Say storing the ecc at end of the spare area is working.

> All read/write functions read/write data from/to address
> info->nand.IO_ADDR_(R/W), which is not set by new function
> 'gpmc_nand_write' (which still take care of writing address/cmd to
> write registers). But since above pointer is not set (hence points to
> address '0'), driver tries to read data from wrong location.
[Ghorai] you can see following two line in _probe() function
info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;

> 
> In fact, I would even suggest to try dumping nand command registers(or
> use T32) and verify if commands issued were written correctly to
> appropriate registers.
[Ghorai] I mentioned read request does not come to driver.

> 
> 
> 
> [1]: http://marc.info/?l=linux-omap&m=128302624528822&w=2
> [2] commit: http://git.infradead.org/mtd-
> 2.6.git/commitdiff/2c01946c6b9ebaa5a89710bc42ca224a7f52f227
> 
> --
> Regards,
> Vimal Singh


From dsd at laptop.org  Thu Oct  7 14:14:02 2010
From: dsd at laptop.org (Daniel Drake)
Date: Thu,  7 Oct 2010 19:14:02 +0100 (BST)
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
Message-ID: <20101007181402.982199D401B@zog.reactivated.net>

When JFFS2 is used for large volumes, the mount times are quite long.
Increasing the hash size provides a significant speed boost on the OLPC
XO-1 laptop.

Add logic that dynamically selects a hash size based on the size of
the medium. A 64mb medium will result in a hash size of 128, and a 512mb
medium will result in a hash size of 1024.

Signed-off-by: Daniel Drake <dsd at laptop.org>
---
 fs/jffs2/build.c       |    2 +-
 fs/jffs2/fs.c          |   22 +++++++++++++++++++++-
 fs/jffs2/jffs2_fs_sb.h |    1 +
 fs/jffs2/nodelist.c    |    8 ++++----
 fs/jffs2/nodelist.h    |    3 ++-
 5 files changed, 29 insertions(+), 7 deletions(-)

Yesterday I wrote saying this patch didn't work. It's actually working fine.
The problem was that I was comparing linus tree to linux-next (with this
patch applied), and linux-next introduced a bug:
http://www.spinics.net/lists/linux-fsdevel/msg37534.html
This seems to be already fixed in more recent linux-next as well.

diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index a906f53..85c6be2 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -23,7 +23,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *,
 static inline struct jffs2_inode_cache *
 first_inode_chain(int *i, struct jffs2_sb_info *c)
 {
-	for (; *i < INOCACHE_HASHSIZE; (*i)++) {
+	for (; *i < c->inocache_hashsize; (*i)++) {
 		if (c->inocache_list[*i])
 			return c->inocache_list[*i];
 	}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 6b2964a..2701b37 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -478,6 +478,25 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 	return inode;
 }
 
+static int calculate_inocache_hashsize(uint32_t flash_size)
+{
+	/*
+	 * Pick a inocache hash size based on the size of the medium.
+	 * Count how many megabytes we're dealing with, apply a hashsize twice
+	 * that size, but rounding down to the usual big powers of 2. And keep
+	 * to sensible bounds.
+	 */
+
+	int size_mb = flash_size / 1024 / 1024;
+	int hashsize = (size_mb * 2) & ~0x3f;
+
+	if (hashsize < INOCACHE_HASHSIZE_MIN)
+		return INOCACHE_HASHSIZE_MIN;
+	if (hashsize > INOCACHE_HASHSIZE_MAX)
+		return INOCACHE_HASHSIZE_MAX;
+
+	return hashsize;
+}
 
 int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
 {
@@ -524,7 +543,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
 	if (ret)
 		return ret;
 
-	c->inocache_list = kcalloc(INOCACHE_HASHSIZE, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
+	c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
+	c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
 	if (!c->inocache_list) {
 		ret = -ENOMEM;
 		goto out_wbuf;
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 6784bc8..f864005 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -100,6 +100,7 @@ struct jffs2_sb_info {
 	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
 
 	wait_queue_head_t inocache_wq;
+	int inocache_hashsize;
 	struct jffs2_inode_cache **inocache_list;
 	spinlock_t inocache_lock;
 
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index af02bd1..5e03233 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -420,7 +420,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t
 {
 	struct jffs2_inode_cache *ret;
 
-	ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
+	ret = c->inocache_list[ino % c->inocache_hashsize];
 	while (ret && ret->ino < ino) {
 		ret = ret->next;
 	}
@@ -441,7 +441,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
 
 	dbg_inocache("add %p (ino #%u)\n", new, new->ino);
 
-	prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE];
+	prev = &c->inocache_list[new->ino % c->inocache_hashsize];
 
 	while ((*prev) && (*prev)->ino < new->ino) {
 		prev = &(*prev)->next;
@@ -462,7 +462,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
 	dbg_inocache("del %p (ino #%u)\n", old, old->ino);
 	spin_lock(&c->inocache_lock);
 
-	prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE];
+	prev = &c->inocache_list[old->ino % c->inocache_hashsize];
 
 	while ((*prev) && (*prev)->ino < old->ino) {
 		prev = &(*prev)->next;
@@ -487,7 +487,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
 	int i;
 	struct jffs2_inode_cache *this, *next;
 
-	for (i=0; i<INOCACHE_HASHSIZE; i++) {
+	for (i=0; i < c->inocache_hashsize; i++) {
 		this = c->inocache_list[i];
 		while (this) {
 			next = this->next;
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 523a916..5a53d9b 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -199,7 +199,8 @@ struct jffs2_inode_cache {
 #define RAWNODE_CLASS_XATTR_DATUM	1
 #define RAWNODE_CLASS_XATTR_REF		2
 
-#define INOCACHE_HASHSIZE 128
+#define INOCACHE_HASHSIZE_MIN 128
+#define INOCACHE_HASHSIZE_MAX 1024
 
 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
 
-- 
1.7.2.3



From linux at arm.linux.org.uk  Thu Oct  7 14:56:30 2010
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 7 Oct 2010 19:56:30 +0100
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
Message-ID: <20101007185630.GA26435@n2100.arm.linux.org.uk>

On Thu, Oct 07, 2010 at 07:17:08AM -0500, Menon, Nishanth wrote:
> 
> > -----Original Message-----
> > From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
> > owner at vger.kernel.org] On Behalf Of G, Manjunath Kondaiah
> > Sent: Tuesday, September 21, 2010 5:01 AM
> > To: linux-omap at vger.kernel.org
> > Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org
> > Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
> > read/write
> > 
> > Following sparse warnings exists due to use of writel/w and readl/w
> > functions.
> > 
> > This patch fixes the sparse warnings by converting readl/w functions usage
> > into
> > __raw_readl/__raw_readw functions.
> 
> Apologies on bringing up an old topic here -> Is'nt it better to fix
> readl/w or writel/w than replacing it with __raw_readl/w etc?

No.  If you're getting sparse warnings its because _you_ are using
readl/writel wrongly.

They take a void __iomem pointer, not a u32, unsigned long, int, or
even a void pointer.


From dedekind1 at gmail.com  Thu Oct  7 15:17:06 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 07 Oct 2010 22:17:06 +0300
Subject: [PATCH] mtd/nand.h: cleanups
In-Reply-To: <20101005104101.GA18714@www.tglx.de>
References: <20101005104101.GA18714@www.tglx.de>
Message-ID: <1286479026.1797.3.camel@brekeke>

On Tue, 2010-10-05 at 12:41 +0200, Sebastian Andrzej Siewior wrote:
> - *var instead of * var
> - proper multiline comment
> - func(args) instead of func (args)
> - 80 lines
> 
> So from
> |total: 2 errors, 37 warnings, 654 lines checked
> we got to one warning.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>

Pushed both patches to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Thu Oct  7 15:18:00 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 07 Oct 2010 22:18:00 +0300
Subject: [PATCH RESEND][MTD]MLC device check in OneNAND driver
In-Reply-To: <000f01cb65d8$984b15b0$c8e14110$%hs@samsung.com>
References: <001701cb5bdd$3fd69a80$bf83cf80$%hs@samsung.com>
	<1285329124.29268.175.camel@localhost>
	<000f01cb65d8$984b15b0$c8e14110$%hs@samsung.com>
Message-ID: <1286479080.1797.4.camel@brekeke>

On Thu, 2010-10-07 at 10:02 +0530, Rohit Hassan Sathyanarayan wrote:
>   We made changes as per your comments and have posted two patches,
>   Links of two patches,
>   http://lists.infradead.org/pipermail/linux-mtd/2010-September/032333.html
>   http://lists.infradead.org/pipermail/linux-mtd/2010-September/032334.html

Yes, I have them in my l2-mtd-2.6.git tree.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Thu Oct  7 15:30:29 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 07 Oct 2010 22:30:29 +0300
Subject: [PATCH] mtd/nand.h: little more cleanup
In-Reply-To: <20101006210614.GA18551@www.tglx.de>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>
	<20101006210614.GA18551@www.tglx.de>
Message-ID: <1286479829.1797.12.camel@brekeke>

On Wed, 2010-10-06 at 23:06 +0200, Sebastian Andrzej Siewior wrote:
> - remove tabs between type and name.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
> ---
>  include/linux/mtd/nand.h |  315 +++++++++++++++++++++------------------------
>  1 files changed, 147 insertions(+), 168 deletions(-)

This one was not compile-tested:

[dedekind at brekeke l2-mtd-2.6]$ make -j2
  CHK     include/linux/version.h
  CHK     include/generated/utsrelease.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  CC [M]  drivers/mtd/devices/doc2000.o
  CC [M]  drivers/mtd/devices/doc2001.o
  CC [M]  drivers/mtd/devices/doc2001plus.o
  CC [M]  drivers/mtd/devices/docprobe.o
  CC [M]  drivers/mtd/nand/nand_base.o
drivers/mtd/nand/nand_base.c: In function ?nand_command?:
drivers/mtd/nand/nand_base.c:589: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c: In function ?nand_command_lp?:
drivers/mtd/nand/nand_base.c:680: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c: In function ?nand_flash_detect_onfi?:
drivers/mtd/nand/nand_base.c:2890: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c: In function ?nand_get_flash_type?:
drivers/mtd/nand/nand_base.c:2977: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c:3099: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c:3103: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c:3104: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c:3106: error: ?struct nand_chip? has no member named ?chipsize?
drivers/mtd/nand/nand_base.c: In function ?nand_scan_ident?:
drivers/mtd/nand/nand_base.c:3216: error: ?struct nand_chip? has no member named ?chipsize?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Thu Oct  7 15:32:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 07 Oct 2010 22:32:15 +0300
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <20101007181402.982199D401B@zog.reactivated.net>
References: <20101007181402.982199D401B@zog.reactivated.net>
Message-ID: <1286479935.1797.14.camel@brekeke>

On Thu, 2010-10-07 at 19:14 +0100, Daniel Drake wrote:
> When JFFS2 is used for large volumes, the mount times are quite long.
> Increasing the hash size provides a significant speed boost on the OLPC
> XO-1 laptop.
> 
> Add logic that dynamically selects a hash size based on the size of
> the medium. A 64mb medium will result in a hash size of 128, and a 512mb
> medium will result in a hash size of 1024.
> 
> Signed-off-by: Daniel Drake <dsd at laptop.org>

Why is this complication needed? Unless there is a very good reason, I'd
just stick with older patch you sent, which I BTW also have in my
l2-mtd-2.6.git tree:

http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/22cf48a8673a8eabfd014de032e426452cce0fc9


-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dwmw2 at infradead.org  Thu Oct  7 15:35:23 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Thu, 07 Oct 2010 20:35:23 +0100
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <1286479935.1797.14.camel@brekeke>
References: <20101007181402.982199D401B@zog.reactivated.net>
	<1286479935.1797.14.camel@brekeke>
Message-ID: <1286480123.3757.2.camel@i7.infradead.org>

On Thu, 2010-10-07 at 22:32 +0300, Artem Bityutskiy wrote:
> Why is this complication needed? Unless there is a very good reason, I'd
> just stick with older patch you sent, which I BTW also have in my
> l2-mtd-2.6.git tree: 

I asked for it. With smaller file systems, a huge increase buys nothing
and is just bloat.

-- 
dwmw2



From bigeasy at linutronix.de  Thu Oct  7 15:41:10 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Thu, 07 Oct 2010 21:41:10 +0200
Subject: [PATCH] mtd/nand.h: little more cleanup
In-Reply-To: <1286479829.1797.12.camel@brekeke>
References: <20101005104101.GA18714@www.tglx.de>	
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>	
	<20101006210614.GA18551@www.tglx.de>
	<1286479829.1797.12.camel@brekeke>
Message-ID: <4CAE2256.6000700@linutronix.de>

Artem Bityutskiy wrote:
> drivers/mtd/nand/nand_base.c: In function ?nand_command?:
> drivers/mtd/nand/nand_base.c:589: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c: In function ?nand_command_lp?:
> drivers/mtd/nand/nand_base.c:680: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c: In function ?nand_flash_detect_onfi?:
> drivers/mtd/nand/nand_base.c:2890: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c: In function ?nand_get_flash_type?:
> drivers/mtd/nand/nand_base.c:2977: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c:3099: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c:3103: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c:3104: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c:3106: error: ?struct nand_chip? has no member named ?chipsize?
> drivers/mtd/nand/nand_base.c: In function ?nand_scan_ident?:
> drivers/mtd/nand/nand_base.c:3216: error: ?struct nand_chip? has no member named ?chipsize?

I'm very sorry for that. I fix is coming in a jiffy or two.

Sebastian


From bigeasy at linutronix.de  Thu Oct  7 15:48:27 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Thu, 7 Oct 2010 21:48:27 +0200
Subject: [PATCH v2] mtd/nand.h: little more cleanup
In-Reply-To: <1286479829.1797.12.camel@brekeke>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>
	<20101006210614.GA18551@www.tglx.de>
	<1286479829.1797.12.camel@brekeke>
Message-ID: <20101007194827.GA5512@www.tglx.de>

- remove tabs between type and name.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
---
- replaced hipsize with chipsize.

 include/linux/mtd/nand.h |  315 +++++++++++++++++++++------------------------
 1 files changed, 147 insertions(+), 168 deletions(-)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index acd0b50..63e17d0 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -253,61 +253,62 @@ struct nand_chip;
 
 struct nand_onfi_params {
 	/* rev info and features block */
-	u8		sig[4]; /* 'O' 'N' 'F' 'I'  */
-	__le16		revision;
-	__le16		features;
-	__le16		opt_cmd;
-	u8		reserved[22];
+	/* 'O' 'N' 'F' 'I'  */
+	u8 sig[4];
+	__le16 revision;
+	__le16 features;
+	__le16 opt_cmd;
+	u8 reserved[22];
 
 	/* manufacturer information block */
-	char		manufacturer[12];
-	char		model[20];
-	u8		jedec_id;
-	__le16		date_code;
-	u8		reserved2[13];
+	char manufacturer[12];
+	char model[20];
+	u8 jedec_id;
+	__le16 date_code;
+	u8 reserved2[13];
 
 	/* memory organization block */
-	__le32		byte_per_page;
-	__le16		spare_bytes_per_page;
-	__le32		data_bytes_per_ppage;
-	__le16		spare_bytes_per_ppage;
-	__le32		pages_per_block;
-	__le32		blocks_per_lun;
-	u8		lun_count;
-	u8		addr_cycles;
-	u8		bits_per_cell;
-	__le16		bb_per_lun;
-	__le16		block_endurance;
-	u8		guaranteed_good_blocks;
-	__le16		guaranteed_block_endurance;
-	u8		programs_per_page;
-	u8		ppage_attr;
-	u8		ecc_bits;
-	u8		interleaved_bits;
-	u8		interleaved_ops;
-	u8		reserved3[13];
+	__le32 byte_per_page;
+	__le16 spare_bytes_per_page;
+	__le32 data_bytes_per_ppage;
+	__le16 spare_bytes_per_ppage;
+	__le32 pages_per_block;
+	__le32 blocks_per_lun;
+	u8 lun_count;
+	u8 addr_cycles;
+	u8 bits_per_cell;
+	__le16 bb_per_lun;
+	__le16 block_endurance;
+	u8 guaranteed_good_blocks;
+	__le16 guaranteed_block_endurance;
+	u8 programs_per_page;
+	u8 ppage_attr;
+	u8 ecc_bits;
+	u8 interleaved_bits;
+	u8 interleaved_ops;
+	u8 reserved3[13];
 
 	/* electrical parameter block */
-	u8		io_pin_capacitance_max;
-	__le16		async_timing_mode;
-	__le16		program_cache_timing_mode;
-	__le16		t_prog;
-	__le16		t_bers;
-	__le16		t_r;
-	__le16		t_ccs;
-	__le16		src_sync_timing_mode;
-	__le16		src_ssync_features;
-	__le16		clk_pin_capacitance_typ;
-	__le16		io_pin_capacitance_typ;
-	__le16		input_pin_capacitance_typ;
-	u8		input_pin_capacitance_max;
-	u8		driver_strenght_support;
-	__le16		t_int_r;
-	__le16		t_ald;
-	u8		reserved4[7];
+	u8 io_pin_capacitance_max;
+	__le16 async_timing_mode;
+	__le16 program_cache_timing_mode;
+	__le16 t_prog;
+	__le16 t_bers;
+	__le16 t_r;
+	__le16 t_ccs;
+	__le16 src_sync_timing_mode;
+	__le16 src_ssync_features;
+	__le16 clk_pin_capacitance_typ;
+	__le16 io_pin_capacitance_typ;
+	__le16 input_pin_capacitance_typ;
+	u8 input_pin_capacitance_max;
+	u8 driver_strenght_support;
+	__le16 t_int_r;
+	__le16 t_ald;
+	u8 reserved4[7];
 
 	/* vendor */
-	u8		reserved5[90];
+	u8 reserved5[90];
 
 	__le16 crc;
 } __attribute__((packed));
@@ -323,7 +324,7 @@ struct nand_onfi_params {
  *			when a hw controller is available.
  */
 struct nand_hw_control {
-	spinlock_t	 lock;
+	spinlock_t lock;
 	struct nand_chip *active;
 	wait_queue_head_t wq;
 };
@@ -353,44 +354,33 @@ struct nand_hw_control {
  * @write_oob:	function to write chip OOB data
  */
 struct nand_ecc_ctrl {
-	nand_ecc_modes_t	mode;
-	int			steps;
-	int			size;
-	int			bytes;
-	int			total;
-	int			prepad;
-	int			postpad;
+	nand_ecc_modes_t mode;
+	int steps;
+	int size;
+	int bytes;
+	int total;
+	int prepad;
+	int postpad;
 	struct nand_ecclayout	*layout;
-	void			(*hwctl)(struct mtd_info *mtd, int mode);
-	int			(*calculate)(struct mtd_info *mtd,
-					     const uint8_t *dat,
-					     uint8_t *ecc_code);
-	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
-					   uint8_t *read_ecc,
-					   uint8_t *calc_ecc);
-	int			(*read_page_raw)(struct mtd_info *mtd,
-						 struct nand_chip *chip,
-						 uint8_t *buf, int page);
-	void			(*write_page_raw)(struct mtd_info *mtd,
-						  struct nand_chip *chip,
-						  const uint8_t *buf);
-	int			(*read_page)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     uint8_t *buf, int page);
-	int			(*read_subpage)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     uint32_t offs, uint32_t len,
-					     uint8_t *buf);
-	void			(*write_page)(struct mtd_info *mtd,
-					      struct nand_chip *chip,
-					      const uint8_t *buf);
-	int			(*read_oob)(struct mtd_info *mtd,
-					    struct nand_chip *chip,
-					    int page,
-					    int sndcmd);
-	int			(*write_oob)(struct mtd_info *mtd,
-					     struct nand_chip *chip,
-					     int page);
+	void (*hwctl)(struct mtd_info *mtd, int mode);
+	int (*calculate)(struct mtd_info *mtd, const uint8_t *dat,
+			uint8_t *ecc_code);
+	int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
+			uint8_t *calc_ecc);
+	int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint8_t *buf, int page);
+	void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf);
+	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint8_t *buf, int page);
+	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t offs, uint32_t len, uint8_t *buf);
+	void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf);
+	int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page,
+			int sndcmd);
+	int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
+			int page);
 };
 
 /**
@@ -487,62 +477,55 @@ struct nand_buffers {
  */
 
 struct nand_chip {
-	void  __iomem	*IO_ADDR_R;
-	void  __iomem	*IO_ADDR_W;
-
-	uint8_t		(*read_byte)(struct mtd_info *mtd);
-	u16		(*read_word)(struct mtd_info *mtd);
-	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf,
-			int len);
-	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf,
-			int len);
-	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf,
-			int len);
-	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs,
-			int getchip);
-	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
-				    unsigned int ctrl);
-	int		(*init_size)(struct mtd_info *mtd,
-					struct nand_chip *this, u8 *id_data);
-	int		(*dev_ready)(struct mtd_info *mtd);
-	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command,
-			int column, int page_addr);
-	int		(*waitfunc)(struct mtd_info *mtd,
-			struct nand_chip *this);
-	void		(*erase_cmd)(struct mtd_info *mtd, int page);
-	int		(*scan_bbt)(struct mtd_info *mtd);
-	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this,
-			int state, int status, int page);
-	int		(*write_page)(struct mtd_info *mtd,
-			struct nand_chip *chip, const uint8_t *buf, int page,
-			int cached, int raw);
-
-	int		chip_delay;
-	unsigned int	options;
-
-	int		page_shift;
-	int		phys_erase_shift;
-	int		bbt_erase_shift;
-	int		chip_shift;
-	int		numchips;
-	uint64_t	chipsize;
-	int		pagemask;
-	int		pagebuf;
-	int		subpagesize;
-	uint8_t		cellinfo;
-	int		badblockpos;
-	int		badblockbits;
-
-	int		onfi_version;
+	void __iomem *IO_ADDR_R;
+	void __iomem *IO_ADDR_W;
+
+	uint8_t (*read_byte)(struct mtd_info *mtd);
+	u16 (*read_word)(struct mtd_info *mtd);
+	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+	int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*select_chip)(struct mtd_info *mtd, int chip);
+	int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+	int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
+			u8 *id_data);
+	int (*dev_ready)(struct mtd_info *mtd);
+	void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
+			int page_addr);
+	int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
+	void (*erase_cmd)(struct mtd_info *mtd, int page);
+	int (*scan_bbt)(struct mtd_info *mtd);
+	int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
+			int status, int page);
+	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			const uint8_t *buf, int page, int cached, int raw);
+
+	int chip_delay;
+	unsigned int options;
+
+	int page_shift;
+	int phys_erase_shift;
+	int bbt_erase_shift;
+	int chip_shift;
+	int numchips;
+	uint64_t chipsize;
+	int pagemask;
+	int pagebuf;
+	int subpagesize;
+	uint8_t cellinfo;
+	int badblockpos;
+	int badblockbits;
+
+	int onfi_version;
 	struct nand_onfi_params	onfi_params;
 
-	flstate_t	state;
+	flstate_t state;
 
-	uint8_t		*oob_poi;
-	struct nand_hw_control  *controller;
-	struct nand_ecclayout	*ecclayout;
+	uint8_t *oob_poi;
+	struct nand_hw_control *controller;
+	struct nand_ecclayout *ecclayout;
 
 	struct nand_ecc_ctrl ecc;
 	struct nand_buffers *buffers;
@@ -550,13 +533,13 @@ struct nand_chip {
 
 	struct mtd_oob_ops ops;
 
-	uint8_t		*bbt;
-	struct nand_bbt_descr	*bbt_td;
-	struct nand_bbt_descr	*bbt_md;
+	uint8_t *bbt;
+	struct nand_bbt_descr *bbt_td;
+	struct nand_bbt_descr *bbt_md;
 
-	struct nand_bbt_descr	*badblock_pattern;
+	struct nand_bbt_descr *badblock_pattern;
 
-	void		*priv;
+	void *priv;
 };
 
 /*
@@ -629,17 +612,16 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @priv:		hardware controller specific settings
  */
 struct platform_nand_chip {
-	int			nr_chips;
-	int			chip_offset;
-	int			nr_partitions;
-	struct mtd_partition	*partitions;
-	struct nand_ecclayout	*ecclayout;
-	int			chip_delay;
-	unsigned int		options;
-	const char		**part_probe_types;
-	void			(*set_parts)(uint64_t size,
-					struct platform_nand_chip *chip);
-	void			*priv;
+	int nr_chips;
+	int chip_offset;
+	int nr_partitions;
+	struct mtd_partition *partitions;
+	struct nand_ecclayout *ecclayout;
+	int chip_delay;
+	unsigned int options;
+	const char **part_probe_types;
+	void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
+	void *priv;
 };
 
 /* Keep gcc happy */
@@ -661,18 +643,15 @@ struct platform_device;
  * All fields are optional and depend on the hardware driver requirements
  */
 struct platform_nand_ctrl {
-	int		(*probe)(struct platform_device *pdev);
-	void		(*remove)(struct platform_device *pdev);
-	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
-	int		(*dev_ready)(struct mtd_info *mtd);
-	void		(*select_chip)(struct mtd_info *mtd, int chip);
-	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
-				    unsigned int ctrl);
-	void		(*write_buf)(struct mtd_info *mtd,
-				    const uint8_t *buf, int len);
-	void		(*read_buf)(struct mtd_info *mtd,
-				    uint8_t *buf, int len);
-	void		*priv;
+	int (*probe)(struct platform_device *pdev);
+	void (*remove)(struct platform_device *pdev);
+	void (*hwcontrol)(struct mtd_info *mtd, int cmd);
+	int (*dev_ready)(struct mtd_info *mtd);
+	void (*select_chip)(struct mtd_info *mtd, int chip);
+	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+	void *priv;
 };
 
 /**
@@ -681,8 +660,8 @@ struct platform_nand_ctrl {
  * @ctrl:		controller level device structure
  */
 struct platform_nand_data {
-	struct platform_nand_chip	chip;
-	struct platform_nand_ctrl	ctrl;
+	struct platform_nand_chip chip;
+	struct platform_nand_ctrl ctrl;
 };
 
 /* Some helpers to access the data structures */
-- 
1.7.2.3



From nm at ti.com  Thu Oct  7 15:50:13 2010
From: nm at ti.com (Nishanth Menon)
Date: Thu, 7 Oct 2010 14:50:13 -0500
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <20101007185630.GA26435@n2100.arm.linux.org.uk>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
	<20101007185630.GA26435@n2100.arm.linux.org.uk>
Message-ID: <4CAE2475.4090607@ti.com>

Russell King - ARM Linux had written, on 10/07/2010 01:56 PM, the following:
> On Thu, Oct 07, 2010 at 07:17:08AM -0500, Menon, Nishanth wrote:
>>> -----Original Message-----
>>> From: linux-omap-owner at vger.kernel.org [mailto:linux-omap-
>>> owner at vger.kernel.org] On Behalf Of G, Manjunath Kondaiah
>>> Sent: Tuesday, September 21, 2010 5:01 AM
>>> To: linux-omap at vger.kernel.org
>>> Cc: linux-arm-kernel at lists.infradead.org; linux-mtd at lists.infradead.org
>>> Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
>>> read/write
>>>
>>> Following sparse warnings exists due to use of writel/w and readl/w
>>> functions.
>>>
>>> This patch fixes the sparse warnings by converting readl/w functions usage
>>> into
>>> __raw_readl/__raw_readw functions.
>> Apologies on bringing up an old topic here -> Is'nt it better to fix
>> readl/w or writel/w than replacing it with __raw_readl/w etc?
> 
> No.  If you're getting sparse warnings its because _you_ are using
> readl/writel wrongly.
> 
> They take a void __iomem pointer, not a u32, unsigned long, int, or
> even a void pointer.
void __iomem *p;
...

readl(p);

unrolls to:
({ u32 __v = ({ u32 __v = (( __u32)(__le32)(( __le32) ((void)0, 
*(volatile unsigned int *)((p))))); __v; }); __asm__ __volatile__ ("mcr 
p15,
, %0, c7, c10, 5" : : "r" (0) : "memory"); __v; });

({ u32 __v = ({ u32 __v

seems to be the obvious cause of sparse warnings such as that attempted 
to be fixed in [1]

  warning: symbol '__v' shadows an earlier one

my comment being that by moving {read,write}[wlb] to __raw versions dont 
solve the real issue of namespace here. fix should be in 
arch/arm/include/asm/io.h IMHO. so that there are no overlaps as this.

[1]http://marc.info/?l=linux-omap&m=128506333803725&w=2

-- 
Regards,
Nishanth Menon


From B21284 at freescale.com  Thu Oct  7 22:13:08 2010
From: B21284 at freescale.com (Hu Mingkai-B21284)
Date: Fri, 8 Oct 2010 10:13:08 +0800
Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by
	page
In-Reply-To: <841976.76219.qm@web180306.mail.gq1.yahoo.com>
References: <841976.76219.qm@web180306.mail.gq1.yahoo.com>
Message-ID: <73839B4A0818E747864426270AC332C3057F6134@zmy16exm20.fsl.freescale.net>



> -----Original Message-----
> From: David Brownell [mailto:david-b at pacbell.net]
> Sent: Thursday, September 30, 2010 6:46 PM
> To: linuxppc-dev at ozlabs.org; spi-devel-general at lists.sourceforge.net; linux-
> mtd at lists.infradead.org; Hu Mingkai-B21284
> Cc: Gala Kumar-B11780; Zang Roy-R61911; Hu Mingkai-B21284
> Subject: Re: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by
> page
> 
> 
> --- On Thu, 9/30/10, Mingkai Hu <Mingkai.hu at freescale.com> wrote:
> 
> > From: Mingkai Hu <Mingkai.hu at freescale.com>
> > Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page
> > by page
> 
> NAK.
> 
> We went over this before.
> 
> ? The bug is in your SPI master controller driver, and the fix there involves
> mapping large reads  into multiple smaller reads.? (Example, 128K read as two
> 64K reads instead of one of 128K.
> 
> It's *NEVER* appropriate to commit to patching all upper level drivers in order
> to work around bugs in lower level ones.? The set of such upper level drivers
> that may need bugfixing is quite large, most will never be used with your buggy
> controller driver, and all such patches will need testing (but the test
> resources are probably not available).
> 
> Whatever SPI controller driver you're working with is clearly buggy ... but not
> unfixably so.
> 
> DO NOT head down the path of requiring every SPI device driver to include
> workarounds for this odd little SPI master driver bug.
> 
> - Dave
> 

Thanks for your comments, the controller driver is the proper place to handle this, I'll fix it.

Thanks,
Mingkai



From B21284 at freescale.com  Thu Oct  7 22:15:26 2010
From: B21284 at freescale.com (Hu Mingkai-B21284)
Date: Fri, 8 Oct 2010 10:15:26 +0800
Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by
	page
In-Reply-To: <20100930150633.GA13741@oksana.dev.rtsoft.ru>
References: <841976.76219.qm@web180306.mail.gq1.yahoo.com>
	<AANLkTinBDdEyMDt3KoauNdmTCz1ZAJ5mZ23iMWiwsUm4@mail.gmail.com>
	<AANLkTi=GydTyhf3TOzCZOtrme1Jh0UmNDHqTVP59q=LH@mail.gmail.com>
	<20100930150633.GA13741@oksana.dev.rtsoft.ru>
Message-ID: <73839B4A0818E747864426270AC332C3057F6138@zmy16exm20.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Thursday, September 30, 2010 11:07 PM
> To: Grant Likely
> Cc: David Brownell; linuxppc-dev at ozlabs.org; Hu Mingkai-B21284; linux-
> mtd at lists.infradead.org; Gala Kumar-B11780; spi-devel-
> general at lists.sourceforge.net
> Subject: Re: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by
> page
> 
> On Thu, Sep 30, 2010 at 11:41:40PM +0900, Grant Likely wrote:
> > On Thu, Sep 30, 2010 at 11:16 PM, Grant Likely
> > <grant.likely at secretlab.ca> wrote:
> > > On Thu, Sep 30, 2010 at 7:46 PM, David Brownell <david-b at pacbell.net> wrote:
> > >>
> > >> --- On Thu, 9/30/10, Mingkai Hu <Mingkai.hu at freescale.com> wrote:
> > >>
> > >>> From: Mingkai Hu <Mingkai.hu at freescale.com>
> > >>> Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read
> > >>> page by page
> > >>
> > >> NAK.
> > >>
> > >> We went over this before.
> > >
> > > Yes, I agree with David on this. ?If large transfers don't work,
> > > then it is the SPI master driver that is buggy.
> >
> > By the way, does this fix your problem?
> >
> > https://patchwork.kernel.org/patch/184752/
> 
> It shouldn't. AFAIK, eSPI is PIO-only controller, and the overrun fix is for the
> DMA mode.
> 
> Thanks,
> 
> p.s. Btw, in patch 3/7, is_dma_mapped argument of fsl_espi_bufs() is unneeded.
> 

Yes, the is_dma_mapped isn't needed, I'll remove it.

Thanks,
Mingkai

From B21284 at freescale.com  Thu Oct  7 22:42:10 2010
From: B21284 at freescale.com (Hu Mingkai-B21284)
Date: Fri, 8 Oct 2010 10:42:10 +0800
Subject: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI flash's
	partitions
In-Reply-To: <AANLkTi=eBA+i7kCOrEPao1AXofKUjBQokWLXFpgx3WND@mail.gmail.com>
References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-5-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-6-git-send-email-Mingkai.hu@freescale.com>
	<AANLkTi=eBA+i7kCOrEPao1AXofKUjBQokWLXFpgx3WND@mail.gmail.com>
Message-ID: <73839B4A0818E747864426270AC332C3057F616A@zmy16exm20.fsl.freescale.net>



> -----Original Message-----
> From: glikely at secretlab.ca [mailto:glikely at secretlab.ca] On Behalf Of Grant
> Likely
> Sent: Friday, October 01, 2010 5:35 AM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev at ozlabs.org; spi-devel-general at lists.sourceforge.net; linux-
> mtd at lists.infradead.org; Gala Kumar-B11780; Zang Roy-R61911
> Subject: Re: [PATCH v3 5/7] mtd: m25p80: add support to parse the SPI flash's
> partitions
> 
> On Thu, Sep 30, 2010 at 5:00 PM, Mingkai Hu <Mingkai.hu at freescale.com> wrote:
> > Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
> > ---
> > v3:
> > ?- Move the SPI flash partition code to the probe function.
> >
> > ?drivers/mtd/devices/m25p80.c | ? 39 +++++++++++++++++++++++++++------------
> > ?1 files changed, 27 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> > index 6f512b5..47d53c7 100644
> > --- a/drivers/mtd/devices/m25p80.c
> > +++ b/drivers/mtd/devices/m25p80.c
> > @@ -772,7 +772,7 @@ static const struct spi_device_id *__devinit
> jedec_probe(struct spi_device *spi)
> > ?static int __devinit m25p_probe(struct spi_device *spi)
> > ?{
> > ? ? ? ?const struct spi_device_id ? ? ?*id = spi_get_device_id(spi);
> > - ? ? ? struct flash_platform_data ? ? ?*data;
> > + ? ? ? struct flash_platform_data ? ? ?data, *pdata;
> > ? ? ? ?struct m25p ? ? ? ? ? ? ? ? ? ? *flash;
> > ? ? ? ?struct flash_info ? ? ? ? ? ? ? *info;
> > ? ? ? ?unsigned ? ? ? ? ? ? ? ? ? ? ? ?i;
> > @@ -782,13 +782,27 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > ? ? ? ? * a chip ID, try the JEDEC id commands; they'll work for most
> > ? ? ? ? * newer chips, even if we don't recognize the particular chip.
> > ? ? ? ? */
> > - ? ? ? data = spi->dev.platform_data;
> > - ? ? ? if (data && data->type) {
> > + ? ? ? pdata = spi->dev.platform_data;
> > + ? ? ? if (!pdata && spi->dev.of_node) {
> > + ? ? ? ? ? ? ? int nr_parts;
> > + ? ? ? ? ? ? ? struct mtd_partition *parts;
> > + ? ? ? ? ? ? ? struct device_node *np = spi->dev.of_node;
> > +
> > + ? ? ? ? ? ? ? nr_parts = of_mtd_parse_partitions(&spi->dev, np, &parts);
> > + ? ? ? ? ? ? ? if (nr_parts) {
> > + ? ? ? ? ? ? ? ? ? ? ? pdata = &data;
> > + ? ? ? ? ? ? ? ? ? ? ? memset(pdata, 0, sizeof(*pdata));
> > + ? ? ? ? ? ? ? ? ? ? ? pdata->parts = parts;
> > + ? ? ? ? ? ? ? ? ? ? ? pdata->nr_parts = nr_parts;
> > + ? ? ? ? ? ? ? }
> > + ? ? ? }
> 
> Yes, this is the correct way to go about adding the partitions.
> However, this patch can be made simpler by not renaming 'data' to
> 'pdata' and by moving the above code down to just before the partition
> information is actually used.  in the OF case, only the parts and the
> nr_parts values written into data, and those values aren't used until
> the last part of the probe function.
> 
> Regardless, in principle this patch is correct:
> 
> Acked-by: Grant Likely <grant.likely at secretlab.ca>
> 
> > +
> > + ? ? ? if (pdata && pdata->type) {
> > ? ? ? ? ? ? ? ?const struct spi_device_id *plat_id;
> >
> > ? ? ? ? ? ? ? ?for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
> > ? ? ? ? ? ? ? ? ? ? ? ?plat_id = &m25p_ids[i];
> > - ? ? ? ? ? ? ? ? ? ? ? if (strcmp(data->type, plat_id->name))
> > + ? ? ? ? ? ? ? ? ? ? ? if (strcmp(pdata->type, plat_id->name))
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?continue;
> > ? ? ? ? ? ? ? ? ? ? ? ?break;
> > ? ? ? ? ? ? ? ?}
> > @@ -796,7 +810,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > ? ? ? ? ? ? ? ?if (i < ARRAY_SIZE(m25p_ids) - 1)
> > ? ? ? ? ? ? ? ? ? ? ? ?id = plat_id;
> > ? ? ? ? ? ? ? ?else
> > - ? ? ? ? ? ? ? ? ? ? ? dev_warn(&spi->dev, "unrecognized id %s\n", data-
> >type);
> > + ? ? ? ? ? ? ? ? ? ? ? dev_warn(&spi->dev, "unrecognized id %s\n",
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pdata->type);
> > ? ? ? ?}
> >
> > ? ? ? ?info = (void *)id->driver_data;
> > @@ -847,8 +862,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > ? ? ? ? ? ? ? ?write_sr(flash, 0);
> > ? ? ? ?}
> >
> > - ? ? ? if (data && data->name)
> > - ? ? ? ? ? ? ? flash->mtd.name = data->name;
> > + ? ? ? if (pdata && pdata->name)
> > + ? ? ? ? ? ? ? flash->mtd.name = pdata->name;
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?flash->mtd.name = dev_name(&spi->dev);
> >
> > @@ -919,9 +934,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?part_probes, &parts, 0);
> > ? ? ? ? ? ? ? ?}
> >
> > - ? ? ? ? ? ? ? if (nr_parts <= 0 && data && data->parts) {
> > - ? ? ? ? ? ? ? ? ? ? ? parts = data->parts;
> > - ? ? ? ? ? ? ? ? ? ? ? nr_parts = data->nr_parts;
> > + ? ? ? ? ? ? ? if (nr_parts <= 0 && pdata && pdata->parts) {
> > + ? ? ? ? ? ? ? ? ? ? ? parts = pdata->parts;
> > + ? ? ? ? ? ? ? ? ? ? ? nr_parts = pdata->nr_parts;
> > ? ? ? ? ? ? ? ?}
> 
> As per my comment earlier; since parts and nr_parts isn't needed
> before this point, this block could simply be:
> 
> if (nr_parts <= 0 && data && data->parts) {
>         parts = data->parts;
>         nr_parts = data->nr_parts;
> }
> if (nr_parts <= 0 && spi->dev.of_node)
>   ? ? ? nr_parts = of_mtd_parse_partitions(&spi->dev, np, &parts);
> 
> And most of the other changes to this file goes away.  Simpler, yes?
> 

Yes, you're right, I'll fix it. Also thanks for your suggestion and ACK.

Thanks,
Mingkai



From nsekhar at ti.com  Fri Oct  8 00:54:48 2010
From: nsekhar at ti.com (Nori, Sekhar)
Date: Fri, 8 Oct 2010 10:24:48 +0530
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <4CADE1B8.50800@mvista.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
	<4CADE1B8.50800@mvista.com>
Message-ID: <B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>

Hi Sergei,

On Thu, Oct 07, 2010 at 20:35:28, Sergei Shtylyov wrote:

> > +static void da830_evm_nor_done(void *data)
> > +{
> > +   clk_disable(da830_evm_nor.clk);
> > +   clk_put(da830_evm_nor.clk);
> > +   iounmap(da830_evm_nor.latch.addr);
> > +   release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
> > +   iounmap(da830_evm_nor.aemif.addr);
> > +   release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
> > +}
>
>     Why you've changed this function which was useful also for the error cleanup
> before?

The issues down below aside, I think goto based error handling
is clearer to follow. Any objections to using goto based
error handing per-se?

Thanks,
Sekhar

>
> > +static int da830_evm_nor_init(void *data, int cs)
> > +{
> > +   /* Turn on AEMIF clocks */
> > +   da830_evm_nor.clk = clk_get(NULL, "aemif");
> > +   if (IS_ERR(da830_evm_nor.clk)) {
> > +           pr_err("%s: could not get AEMIF clock\n", __func__);
> > +           da830_evm_nor.clk = NULL;
> > +           return -ENODEV;
> > +   }
> > +   clk_enable(da830_evm_nor.clk);
> > +
> > +   da830_evm_nor.aemif.res = request_mem_region(DA8XX_AEMIF_CTL_BASE,
> > +                                                SZ_32K, "AEMIF control");
> > +   if (da830_evm_nor.aemif.res == NULL) {
> > +           pr_err("%s: could not request AEMIF control region\n",
> > +                   __func__);
> > +           goto err_aemif_region;
>
>     I wonder why you used goto's at all. Anyway, the error cleanup code is
> completely broken now.
>
> > +   }
> > +
> > +   da830_evm_nor.aemif.addr = ioremap_nocache(DA8XX_AEMIF_CTL_BASE,
> > +                                              SZ_32K);
> > +   if (da830_evm_nor.aemif.addr == NULL) {
> > +           pr_err("%s: could not remap AEMIF control region\n", __func__);
> > +           goto err_aemif_ioremap;
> > +   }
> > +
> > +   /* Setup AEMIF -- timings, etc. */
> > +
> > +   /* Set maximum wait cycles */
> > +   davinci_aemif_setup_timing(&da830_evm_norflash_timing,
> > +                                           da830_evm_nor.aemif.addr, cs);
> > +
> > +   davinci_aemif_setup_timing(&da830_evm_norflash_timing,
> > +                                   da830_evm_nor.aemif.addr, cs + 1);
> > +
> > +   /* Setup the window to access the latch */
> > +   da830_evm_nor.latch.res =
> > +           request_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE,
> > +                              "DA830 UI NOR address latch");
> > +   if (da830_evm_nor.latch.res == NULL) {
> > +           pr_err("%s: could not request address latch region\n",
> > +                   __func__);
> > +           goto err_latch_region;
> > +   }
> > +
> > +   da830_evm_nor.latch.addr =
> > +           ioremap_nocache(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
> > +   if (da830_evm_nor.latch.addr == NULL) {
> > +           pr_err("%s: could not remap address latch region\n", __func__);
> > +           goto err_latch_ioremap;
> > +   }
> > +   return 0;
> > +
> > +err_aemif_region:
> > +   release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
>
>     Why release what you've just failed to request?!
>
> > +   da830_evm_nor.aemif.res = NULL;
>
>     Useless assignment.
>
> > +   return -EBUSY;
>
>     And you're not calling clk_disable().
>
> > +err_aemif_ioremap:
> > +   iounmap(da830_evm_nor.aemif.addr);
>
>     Why unmap what you've just failed to map?! da830_evm_nor.aemif.addr is NULL.
>
> > +   da830_evm_nor.aemif.addr = NULL;
>
>     Useless assignment.
>
> > +   return -ENOMEM;
>
>     You're not calling release_mem_region() and clk_disable().
>
> > +err_latch_region:
> > +   release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
>
>     Why release what you've just failed to request?!
>
> > +   da830_evm_nor.latch.res = NULL;
>
>     Useless assginment.
>
> > +   return -EBUSY;
>
>     You're not calling iounmap() and release_mem_region() for the NOR flash
> region and also not calling clk_disable().
>
> > +
> > +err_latch_ioremap:
> > +   iounmap(da830_evm_nor.latch.addr);
>
>     Why unmap what you've just failed to map?! da830_evm_nor.latch.addr is NULL.
>
> > +   da830_evm_nor.latch.addr = NULL;
>
>     Useless assginment.
>
> > +   return -ENOMEM;
>
>     You're not release_mem_region() for the latch region, not calling iounmap()
> and release_mem_region() for the NOR flash region and also not calling
> clk_disable().
>
> > +}
> [...]
>
>     Your changes made me doubt that you actually understood the code well enough
> before doing them...
>
> WBR, Sergei
>
> _______________________________________________
> Davinci-linux-open-source mailing list
> Davinci-linux-open-source at linux.davincidsp.com
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
>



From dedekind1 at gmail.com  Fri Oct  8 01:51:18 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 08 Oct 2010 08:51:18 +0300
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <1286480123.3757.2.camel@i7.infradead.org>
References: <20101007181402.982199D401B@zog.reactivated.net>
	<1286479935.1797.14.camel@brekeke>
	<1286480123.3757.2.camel@i7.infradead.org>
Message-ID: <1286517078.2095.15.camel@localhost>

On Thu, 2010-10-07 at 20:35 +0100, David Woodhouse wrote:
> On Thu, 2010-10-07 at 22:32 +0300, Artem Bityutskiy wrote:
> > Why is this complication needed? Unless there is a very good reason, I'd
> > just stick with older patch you sent, which I BTW also have in my
> > l2-mtd-2.6.git tree: 
> 
> I asked for it. With smaller file systems, a huge increase buys nothing
> and is just bloat.

OK, I looked closer to the code and I see that I misunderstood this
constant. I though it is only about increasing the size of an array of
integers, but this is about increasing the size of an array of
struct jffs2_inode_cache.

Fair enough.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Oct  8 02:00:42 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 08 Oct 2010 09:00:42 +0300
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <20101007181402.982199D401B@zog.reactivated.net>
References: <20101007181402.982199D401B@zog.reactivated.net>
Message-ID: <1286517642.2095.29.camel@localhost>

On Thu, 2010-10-07 at 19:14 +0100, Daniel Drake wrote:
> When JFFS2 is used for large volumes, the mount times are quite long.
> Increasing the hash size provides a significant speed boost on the OLPC
> XO-1 laptop.
> 
> Add logic that dynamically selects a hash size based on the size of
> the medium. A 64mb medium will result in a hash size of 128, and a 512mb
> medium will result in a hash size of 1024.
> 
> Signed-off-by: Daniel Drake <dsd at laptop.org>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Oct  8 02:00:54 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 08 Oct 2010 09:00:54 +0300
Subject: [PATCH v2] mtd/nand.h: little more cleanup
In-Reply-To: <20101007194827.GA5512@www.tglx.de>
References: <20101005104101.GA18714@www.tglx.de>
	<20101005182656.GA21067@pengutronix.de>
	<1286304506.1797.2.camel@brekeke>
	<20101006210614.GA18551@www.tglx.de> <1286479829.1797.12.camel@brekeke>
	<20101007194827.GA5512@www.tglx.de>
Message-ID: <1286517654.2095.30.camel@localhost>

On Thu, 2010-10-07 at 21:48 +0200, Sebastian Andrzej Siewior wrote:
> - remove tabs between type and name.
> 
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy at linutronix.de>
> ---
> - replaced hipsize with chipsize.
> 
>  include/linux/mtd/nand.h |  315 +++++++++++++++++++++------------------------
>  1 files changed, 147 insertions(+), 168 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From galak at kernel.crashing.org  Fri Oct  8 02:11:49 2010
From: galak at kernel.crashing.org (Kumar Gala)
Date: Fri, 8 Oct 2010 01:11:49 -0500
Subject: [PATCH v3 6/7] mtd: m25p80: add a read function to read page by
	page
In-Reply-To: <73839B4A0818E747864426270AC332C3057F6138@zmy16exm20.fsl.freescale.net>
References: <841976.76219.qm@web180306.mail.gq1.yahoo.com>
	<AANLkTinBDdEyMDt3KoauNdmTCz1ZAJ5mZ23iMWiwsUm4@mail.gmail.com>
	<AANLkTi=GydTyhf3TOzCZOtrme1Jh0UmNDHqTVP59q=LH@mail.gmail.com>
	<20100930150633.GA13741@oksana.dev.rtsoft.ru>
	<73839B4A0818E747864426270AC332C3057F6138@zmy16exm20.fsl.freescale.net>
Message-ID: <5FE2FD44-A491-4E7C-86E9-5247B9598AD2@kernel.crashing.org>


On Oct 7, 2010, at 9:15 PM, Hu Mingkai-B21284 wrote:

>>>> Yes, I agree with David on this.  If large transfers don't work,
>>>> then it is the SPI master driver that is buggy.
>>> 
>>> By the way, does this fix your problem?
>>> 
>>> https://patchwork.kernel.org/patch/184752/
>> 
>> It shouldn't. AFAIK, eSPI is PIO-only controller, and the overrun fix is for the
>> DMA mode.
>> 
>> Thanks,
>> 
>> p.s. Btw, in patch 3/7, is_dma_mapped argument of fsl_espi_bufs() is unneeded.
>> 
> 
> Yes, the is_dma_mapped isn't needed, I'll remove it.
> 
> Thanks,
> Mingkai

I'd be really nice if we could close on this patchset in time for .37 acceptance.  I'm guessing that cutoff is quickly approaching.

- k

From dedekind1 at gmail.com  Fri Oct  8 02:17:23 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 08 Oct 2010 09:17:23 +0300
Subject: [PATCH] JFFS2: Dynamically choose inocache hash size
In-Reply-To: <1286517078.2095.15.camel@localhost>
References: <20101007181402.982199D401B@zog.reactivated.net>
	<1286479935.1797.14.camel@brekeke>
	<1286480123.3757.2.camel@i7.infradead.org>
	<1286517078.2095.15.camel@localhost>
Message-ID: <1286518643.2095.35.camel@localhost>

On Fri, 2010-10-08 at 08:51 +0300, Artem Bityutskiy wrote:
> On Thu, 2010-10-07 at 20:35 +0100, David Woodhouse wrote:
> > On Thu, 2010-10-07 at 22:32 +0300, Artem Bityutskiy wrote:
> > > Why is this complication needed? Unless there is a very good reason, I'd
> > > just stick with older patch you sent, which I BTW also have in my
> > > l2-mtd-2.6.git tree: 
> > 
> > I asked for it. With smaller file systems, a huge increase buys nothing
> > and is just bloat.
> 
> OK, I looked closer to the code and I see that I misunderstood this
> constant. I though it is only about increasing the size of an array of
> integers, but this is about increasing the size of an array of
> struct jffs2_inode_cache.

Oh my, it is indeed about increasing size of array of pointers. I would
not bother with additional calculations - it is just (1024 - 256) * 4 =
3072 bytes which is nothing comparing to overall JFFS2 memory
consumption, not worth bothering.

Anyway, not so important.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From B21284 at freescale.com  Fri Oct  8 02:35:50 2010
From: B21284 at freescale.com (Hu Mingkai-B21284)
Date: Fri, 8 Oct 2010 14:35:50 +0800
Subject: [PATCH v3 3/7] eSPI: add eSPI controller support
In-Reply-To: <20101001112204.GA16783@oksana.dev.rtsoft.ru>
References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-4-git-send-email-Mingkai.hu@freescale.com>
	<20101001112204.GA16783@oksana.dev.rtsoft.ru>
Message-ID: <73839B4A0818E747864426270AC332C3057F626D@zmy16exm20.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Friday, October 01, 2010 7:22 PM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev at ozlabs.org; spi-devel-general at lists.sourceforge.net; linux-
> mtd at lists.infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH v3 3/7] eSPI: add eSPI controller support
> 
> Hello Mingkai,
> 
> There are mostly cosmetic comments down below.
> 
> > +		/* spin until TX is done */
> > +		while (((events = mpc8xxx_spi_read_reg(&reg_base->event))
> > +					& SPIE_NF) == 0)
> > +			cpu_relax();
> 
> This is dangerous. There's a handy spin_event_timeout() in asm/delay.h.
> 

When timeout, can I use return in the interrupt function directly like this?

if (!(events & SPIE_NF)) {
        int ret;
        /* spin until TX is done */
        ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
                        &reg_base->event)) & SPIE_NF) == 0, 1000, 0);
        if (!ret) {
                dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
                return;
        }
}

> > +}
> > +
> > +static const struct of_device_id of_fsl_espi_match[] = {
> > +	{ .compatible = "fsl,mpc8536-espi" },
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> > +
> > +static struct of_platform_driver fsl_espi_driver = {
> > +	.driver = {
> > +		.name = "fsl_espi",
> > +		.owner = THIS_MODULE,
> > +		.of_match_table = of_fsl_espi_match,
> > +	},
> > +	.probe		= of_fsl_espi_probe,
> > +	.remove		= __devexit_p(of_fsl_espi_remove),
> > +};
> > +
> > +static int __init fsl_espi_init(void) {
> > +	return of_register_platform_driver(&fsl_espi_driver);
> > +}
> > +module_init(fsl_espi_init);
> > +
> > +static void __exit fsl_espi_exit(void) {
> > +	of_unregister_platform_driver(&fsl_espi_driver);
> > +}
> > +module_exit(fsl_espi_exit);
> > +
> > +MODULE_AUTHOR("Mingkai Hu");
> > +MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
> 
> This sounds like that this is an enhanced version of the Freescale SPI driver,
> which it is not. ;-)
> 

I quoted from the UM, maybe the enhancement is the controller takes over the
CS signal from the HW point view.

I changed all the other code according to your comments.

Thanks,
Mingkai


From B21284 at freescale.com  Fri Oct  8 02:37:00 2010
From: B21284 at freescale.com (Hu Mingkai-B21284)
Date: Fri, 8 Oct 2010 14:37:00 +0800
Subject: [PATCH v3 2/7] spi/mpc8xxx: refactor the common code for SPI/eSPI
	controller
In-Reply-To: <20101001112212.GA17505@oksana.dev.rtsoft.ru>
References: <1285833646-12006-1-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-2-git-send-email-Mingkai.hu@freescale.com>
	<1285833646-12006-3-git-send-email-Mingkai.hu@freescale.com>
	<20101001112212.GA17505@oksana.dev.rtsoft.ru>
Message-ID: <73839B4A0818E747864426270AC332C3057F6272@zmy16exm20.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Friday, October 01, 2010 7:22 PM
> To: Hu Mingkai-B21284
> Cc: linuxppc-dev at ozlabs.org; spi-devel-general at lists.sourceforge.net; linux-
> mtd at lists.infradead.org; Gala Kumar-B11780; Zang Roy-R61911
> Subject: Re: [PATCH v3 2/7] spi/mpc8xxx: refactor the common code for SPI/eSPI
> controller
> 
> On Thu, Sep 30, 2010 at 04:00:41PM +0800, Mingkai Hu wrote:
> [...]
> > -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> > +static void fsl_spi_change_mode(struct spi_device *spi)
> >  {
> >  	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> >  	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> > -	__be32 __iomem *mode = &mspi->base->mode;
> > +	struct fsl_spi_reg *reg_base = (struct fsl_spi_reg *)mspi->reg_base;
> 
> No need for these type casts (the same is for the whole patch).
> 

Fix it.

Thanks,
Mingkai

From vitalywool at gmail.com  Fri Oct  8 02:44:33 2010
From: vitalywool at gmail.com (Vitaly Wool)
Date: Fri, 8 Oct 2010 07:44:33 +0100
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
	<4CADE1B8.50800@mvista.com>
	<B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
Message-ID: <AANLkTi=P8DcjCn_mozmvaNue2d_jn6meBzvXDbk3gpd3@mail.gmail.com>

On Fri, Oct 8, 2010 at 5:54 AM, Nori, Sekhar <nsekhar at ti.com> wrote:
> Hi Sergei,
>
> On Thu, Oct 07, 2010 at 20:35:28, Sergei Shtylyov wrote:
>
>> > +static void da830_evm_nor_done(void *data)
>> > +{
>> > + ? clk_disable(da830_evm_nor.clk);
>> > + ? clk_put(da830_evm_nor.clk);
>> > + ? iounmap(da830_evm_nor.latch.addr);
>> > + ? release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
>> > + ? iounmap(da830_evm_nor.aemif.addr);
>> > + ? release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
>> > +}
>>
>> ? ? Why you've changed this function which was useful also for the error cleanup
>> before?
>
> The issues down below aside, I think goto based error handling
> is clearer to follow. Any objections to using goto based
> error handing per-se?

What you're saying just doesn't make sense in this context. Whatever
way of error handling is chosen, it first needs to be correct which is
absolutely not the case here.

~Vitaly


From nsekhar at ti.com  Fri Oct  8 02:50:15 2010
From: nsekhar at ti.com (Nori, Sekhar)
Date: Fri, 8 Oct 2010 12:20:15 +0530
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <AANLkTi=P8DcjCn_mozmvaNue2d_jn6meBzvXDbk3gpd3@mail.gmail.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
	<4CADE1B8.50800@mvista.com>
	<B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
	<AANLkTi=P8DcjCn_mozmvaNue2d_jn6meBzvXDbk3gpd3@mail.gmail.com>
Message-ID: <B85A65D85D7EB246BE421B3FB0FBB59302342ADFC2@dbde02.ent.ti.com>

On Fri, Oct 08, 2010 at 12:14:33, Vitaly Wool wrote:
> On Fri, Oct 8, 2010 at 5:54 AM, Nori, Sekhar <nsekhar at ti.com> wrote:
> > Hi Sergei,
> >
> > On Thu, Oct 07, 2010 at 20:35:28, Sergei Shtylyov wrote:
> >
> >> > +static void da830_evm_nor_done(void *data)
> >> > +{
> >> > +   clk_disable(da830_evm_nor.clk);
> >> > +   clk_put(da830_evm_nor.clk);
> >> > +   iounmap(da830_evm_nor.latch.addr);
> >> > +   release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
> >> > +   iounmap(da830_evm_nor.aemif.addr);
> >> > +   release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
> >> > +}
> >>
> >>     Why you've changed this function which was useful also for the error cleanup
> >> before?
> >
> > The issues down below aside, I think goto based error handling
> > is clearer to follow. Any objections to using goto based
> > error handing per-se?
>
> What you're saying just doesn't make sense in this context. Whatever
> way of error handling is chosen, it first needs to be correct which is
> absolutely not the case here.

Yes, agreed. It needs to be correct first.

Thanks,
Sekhar



From sshtylyov at mvista.com  Fri Oct  8 05:56:47 2010
From: sshtylyov at mvista.com (Sergei Shtylyov)
Date: Fri, 08 Oct 2010 13:56:47 +0400
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
	<4CADE1B8.50800@mvista.com>
	<B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
Message-ID: <4CAEEADF.5070103@mvista.com>

Hello.

On 08-10-2010 8:54, Nori, Sekhar wrote:

>>> +static void da830_evm_nor_done(void *data)
>>> +{
>>> +   clk_disable(da830_evm_nor.clk);
>>> +   clk_put(da830_evm_nor.clk);
>>> +   iounmap(da830_evm_nor.latch.addr);
>>> +   release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
>>> +   iounmap(da830_evm_nor.aemif.addr);
>>> +   release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
>>> +}

>>      Why you've changed this function which was useful also for the error cleanup
>> before?

> The issues down below aside, I think goto based error handling
> is clearer to follow. Any objections to using goto based
> error handing per-se?

    I think the code was more compact with the old error handling. And anyway, 
I'm not feeling happy when TI is changing MV's code.

> Thanks,
> Sekhar

WBR, Sergei


From vitalywool at gmail.com  Fri Oct  8 06:51:15 2010
From: vitalywool at gmail.com (Vitaly Wool)
Date: Fri, 8 Oct 2010 12:51:15 +0200
Subject: [PATCH 2/2] davinci: Platform support for OMAP-L137/AM17x NOR
	flash driver
In-Reply-To: <4CAEEADF.5070103@mvista.com>
References: <1286451272-12988-1-git-send-email-savinay.dharmappa@ti.com>
	<4CADE1B8.50800@mvista.com>
	<B85A65D85D7EB246BE421B3FB0FBB59302342ADE9D@dbde02.ent.ti.com>
	<4CAEEADF.5070103@mvista.com>
Message-ID: <AANLkTikzJc5QwSMBF8GzPbYRQaZ6Js-fEQHssphaWp0=@mail.gmail.com>

On Fri, Oct 8, 2010 at 11:56 AM, Sergei Shtylyov <sshtylyov at mvista.com> wrote:

> ? I think the code was more compact with the old error handling. And anyway,
> I'm not feeling happy when TI is changing MV's code.

Leaving the inter-vendor relations aside, I'd say, anyone can modify
any GPL code. The thing is, this person can not just inherit
Signed-off-by from the previous version, and this is what happened I
guess.

~Vitaly


From sr at denx.de  Fri Oct  8 08:41:27 2010
From: sr at denx.de (Stefan Roese)
Date: Fri,  8 Oct 2010 14:41:27 +0200
Subject: [PATCH] mtd: physmap_of: Loop through all "reg" tuples for mapping
Message-ID: <1286541687-5706-1-git-send-email-sr@denx.de>

This patch changes the loop over the "reg" tuples to not exit
directly upon of_address_to_resource() failure but to continue
with the next "reg" tuple instead. This failure could be due to
size = 0, which might be passed via the device-tree.

This is needed for boards, where a "reg" tuple might have size 0
(of_address_to_resource() returns with EINVAL when size = 0).

Example:

Fully equipped board:

	reg = <0 0x00000000 0x00400000
	       0 0x00400000 0x00400000>;

Partially equipped board:

	reg = <0 0x00000000 0x00400000
	       0 0x00400000 0x00000000>;

This could be the case on boards with runtime detection of
multiple NOR flash configurations where the detected flash size
is inserted into the dtb in U-Boot.

Signed-off-by: Stefan Roese <sr at denx.de>
---
 drivers/mtd/maps/physmap_of.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index fe63f6b..6967348 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -267,9 +267,11 @@ static int __devinit of_flash_probe(struct platform_device *dev,
 	for (i = 0; i < count; i++) {
 		err = -ENXIO;
 		if (of_address_to_resource(dp, i, &res)) {
-			dev_err(&dev->dev, "Can't get IO address from device"
-				" tree\n");
-			goto err_out;
+			/*
+			 * Continue with next register tuple if this
+			 * one is not mappable
+			 */
+			continue;
 		}
 
 		dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
-- 
1.7.3.1



From amckay at iders.ca  Fri Oct  8 14:04:17 2010
From: amckay at iders.ca (Andrew McKay)
Date: Fri, 08 Oct 2010 13:04:17 -0500
Subject: JFFS2 Summary warnings on large block NAND device
Message-ID: <4CAF5D21.2050103@iders.ca>

Hello,

I've been using JFFS2 for a little while now, and I'm just going through 
the warning and error messages that JFFS2 sometimes reports to see if we 
have any issues with our system.  We've moved to a new NAND part from 
Micron that has 4K pages and 512K erase blocks and I'm getting some new 
warnings from JFFS2 that I've never seen before and am wondering if I 
have an issue.

Here's the three messages I'm worried about:
JFFS2 warning: (1) jffs2_sum_scan_sumnode: Summary node crc error, 
skipping summary information.
JFFS2 warning: (633) jffs2_sum_write_data: Summary too big (-32 data, 
-2794 pad) in eraseblock at 27b80000
JFFS2 warning: (739) jffs2_sum_write_data: Not enough space for summary, 
padsize = -1324

Presumably, these messages are all related and are because summary 
information is limited to 64K so that kmalloc can be used for 
allocation.  With the larger sized erase block I assume that the summary 
information is often exceeding 64K.  Should I be worried about these 
messages?  As far as I understand summary information is only used so 
that JFFS2 can mount quickly.  Without it mount times will be a bit 
longer as it has to scan each page in the device instead of the summary 
page at the end of the erase block.

Is there a fix for this issue? Admittedly my kernel is a little old. 
2.6.30.9, so I may not have the most up to date JFFS2 code.  Though I 
did some searching online and I haven't found mention of solution to 
this problem, or if it is something that I should be concerned about.

Thanks for your time

-- 
Andrew McKay
IDERS Inc.


From joakim.tjernlund at transmode.se  Sat Oct  9 12:36:38 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Sat, 9 Oct 2010 18:36:38 +0200
Subject: [PATCH] jffs2: Fix serious write stall due to erase
In-Reply-To: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>
References: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>
Message-ID: <OF75BA9795.D3DFC6A0-ONC12577B7.005B0CDA-C12577B7.005B3EA4@transmode.se>

David, pretty please :)

  Jocke
>
> Drop the alloc_sem before erasing flash in
> jffs2_garbage_collect_pass().
> Otherwise writes are put on hold until the erase
> has finised.
>
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> ---
>
>  I am fairly sure it is safe to unlock the alloc_sem before
>  calling jffs2_erase_pending_blocks(). Extra confirmation
>  would be great though.
>
>  This problem was introduced in 2.6.35
>
>  fs/jffs2/gc.c |    7 ++++---
>  1 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
> index f5e96bd..b5f7175 100644
> --- a/fs/jffs2/gc.c
> +++ b/fs/jffs2/gc.c
> @@ -218,13 +218,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
>     if (!list_empty(&c->erase_complete_list) ||
>         !list_empty(&c->erase_pending_list)) {
>        spin_unlock(&c->erase_completion_lock);
> +      mutex_unlock(&c->alloc_sem);
>        D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n"));
> -      if (jffs2_erase_pending_blocks(c, 1)) {
> -         mutex_unlock(&c->alloc_sem);
> +      if (jffs2_erase_pending_blocks(c, 1))
>           return 0;
> -      }
> +
>        D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
>        spin_lock(&c->erase_completion_lock);
> +      mutex_lock(&c->alloc_sem);
>     }
>
>     /* First, work out which block we're garbage-collecting */
> --
> 1.7.2.2
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/



From mason at postdiluvian.org  Sat Oct  9 13:42:46 2010
From: mason at postdiluvian.org (Mark Mason)
Date: Sat, 9 Oct 2010 13:42:46 -0400
Subject: Scheduler latency problems when using NAND
In-Reply-To: <4CA3D92E.9060109@call-direct.com.au>
References: <20100929221401.GA32583@postdiluvian.org>
	<4CA3D92E.9060109@call-direct.com.au>
Message-ID: <20101009174246.GA19591@postdiluvian.org>

Iwo Mergler <iwo at call-direct.com.au> wrote:

> Mark Mason wrote:
> > Hi all,
> > 
> > I hope this is the right place for this question.  I'm having some
> > problems with scheduler latency when using UBIFS, and I'm hoping for
> > some suggestions.
> <snip>
> > The application is storing streaming video, almost entirely large
> > sequential files, roughly 250K to 15M, to a 1.6G filesystem.  There's
> > no seeking or rewriting, just creat, write, close, repeat.  No
> > compression is used on the filesystem.
> > 
> > The problem I'm seeing is excessively large scheduler latency when
> > data is flushed to NAND.
> <snip>
> > Does anyone have any suggestions, ideas, hints, advice, etc?
> 
> The Linux block cache is optimised for mechanical hard drives,
> to minimise seek times. Some of the assumptions don't make much
> sense with FLASH and streaming storage.
> 
> Maybe try to flush data whenever you have written a few blocks'
> worth. Or have a look at the O_DIRECT flag (or madvise), although
> I don't know how it interacts with UBIFS.

I tried lowering dirty_writeback_centisecs and dirty_expire_centisecs,
the latency dropped when I used values around 1 or 2 (down from 500 &
3000), but it's still a problem.

> You could use a real filesystem to store the metadata for your
> circular storage partition (file name, length, offset).
> 
> Maybe use raw UBI so you don't have to worry about bad blocks.
> 
> Either way, the time to erase a block and write a single page
> is predictable and you can do it as soon as you get the data.

A custom filesystem would be good, but I still hold out hope that
somebody has already fought this battle for me.

Regardless, it looks like I have a genuine hardware problem on my
hands, and it's one that I would expect other people to have, although
I suspect it wouldn't be an issue with reasonable flash loads.

The flash driver (fsl_elbc_nand.c) goes to sleep right after it issues
a page program, and a context switch to another high priority thread
takes place promptly.  This thread is often one that reads from
another (video) chip on the same bus as the flash (the MPC8315 LBC).
The flash asserts its BUSY line while the page program is in
operation.  When the other thread comes along to read from video chip,
it's held off for the 200us duration of the page program (the LBC
controller for the video chip is running in UPM mode, so the BUSY line
is a BUSY line and not a TA line, in case any 83xx junkies are reading
this).

What I see on a logic analyzer is the BUSY line held by the flash for
200us, a single 32 bit read of the video chip (broken up into two 16
bit reads for the 16 bit bus), then another 200us BUSY from the flash,
two more 16 bit reads, etc, all the way to the end of the logic
analyzer screen.

What I think is happening is that the flash background thread is
running very efficiently - it comes in, issues a page program, and
relinquishes the CPU.  The thread reading the video chip then runs,
stalls for 200us waiting for a single read, gets its read, then is
preempted for the flash BGT.

My guess is that the scheduler sees the flash background thread as
running almost not at all, and the video thread as running a lot more,
although it's stalled for most of the first 200us of its time slice on
a single bus transaction, so it can't really do anything with its time
slice.  I further suspect that the scheduler is dynamically adjusting
the priorities to boost the flash BGT, since it's using much less CPU
time than the video thread, even though the video thread can't use
most of its time slice.  Can someone tell me if this makes sense?

I tried some messing with priorities, but ultimately the flash has to
run, and it has to run frequently in very short bursts to issue all of
the page programs.  The video chip needs to be serviced promptly, so
there is always a significant chance that it will run right after a
page program is issued.

I tried disabling preemption for the duration of a transfer in the
video driver so it wouldn't get preempted once it had waited its 200us
to get the bus.  It helped, but ultimately there's still a 200us delay
to perform a sequence of operations that usually take somewhere
between 5 and 30 us.

Most devices that would sit on the bus will only assert the BUSY line
while the chip select is held.  The NAND, however, asserts BUSY for
the duration of a page program.  So I could add a gate to the BUSY
line to gate it with the chip select.  This would require a respin of
the board, and I'm not 100% certain that it wouldn't confuse the
8315's NAND controller.  I'm going to try this next week.  I could
also take the bus controller out of flash (FCM) mode, depop the
resistors to the NAND's BUSY line, and have the NAND layer talk to the
NAND like it's just a chip on a plain old bus, and poll for BUSY.
This option might be better than it sounds, since the delays are very
predictable.

Any words of wisdom?


From joakim.tjernlund at transmode.se  Sun Oct 10 03:56:28 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Sun, 10 Oct 2010 09:56:28 +0200
Subject: Scheduler latency problems when using NAND
In-Reply-To: <20101009174246.GA19591@postdiluvian.org>
References: <20100929221401.GA32583@postdiluvian.org>	<4CA3D92E.9060109@call-direct.com.au>
	<20101009174246.GA19591@postdiluvian.org>
Message-ID: <OFF2D9931B.4A726CA8-ONC12577B8.002B195B-C12577B8.002B9F8C@transmode.se>


>
> Iwo Mergler <iwo at call-direct.com.au> wrote:
>
> > Mark Mason wrote:
> > > Hi all,
> > >
> > > I hope this is the right place for this question.  I'm having some
> > > problems with scheduler latency when using UBIFS, and I'm hoping for
> > > some suggestions.
> > <snip>
> > > The application is storing streaming video, almost entirely large
> > > sequential files, roughly 250K to 15M, to a 1.6G filesystem.  There's
> > > no seeking or rewriting, just creat, write, close, repeat.  No
> > > compression is used on the filesystem.
> > >
> > > The problem I'm seeing is excessively large scheduler latency when
> > > data is flushed to NAND.
> > <snip>
> > > Does anyone have any suggestions, ideas, hints, advice, etc?
> >
> > The Linux block cache is optimised for mechanical hard drives,
> > to minimise seek times. Some of the assumptions don't make much
> > sense with FLASH and streaming storage.
> >
> > Maybe try to flush data whenever you have written a few blocks'
> > worth. Or have a look at the O_DIRECT flag (or madvise), although
> > I don't know how it interacts with UBIFS.
>
> I tried lowering dirty_writeback_centisecs and dirty_expire_centisecs,
> the latency dropped when I used values around 1 or 2 (down from 500 &
> 3000), but it's still a problem.
>
> > You could use a real filesystem to store the metadata for your
> > circular storage partition (file name, length, offset).
> >
> > Maybe use raw UBI so you don't have to worry about bad blocks.
> >
> > Either way, the time to erase a block and write a single page
> > is predictable and you can do it as soon as you get the data.
>
> A custom filesystem would be good, but I still hold out hope that
> somebody has already fought this battle for me.
>
> Regardless, it looks like I have a genuine hardware problem on my
> hands, and it's one that I would expect other people to have, although
> I suspect it wouldn't be an issue with reasonable flash loads.
>
> The flash driver (fsl_elbc_nand.c) goes to sleep right after it issues
> a page program, and a context switch to another high priority thread
> takes place promptly.  This thread is often one that reads from
> another (video) chip on the same bus as the flash (the MPC8315 LBC).
> The flash asserts its BUSY line while the page program is in
> operation.  When the other thread comes along to read from video chip,
> it's held off for the 200us duration of the page program (the LBC
> controller for the video chip is running in UPM mode, so the BUSY line
> is a BUSY line and not a TA line, in case any 83xx junkies are reading
> this).
>
> What I see on a logic analyzer is the BUSY line held by the flash for
> 200us, a single 32 bit read of the video chip (broken up into two 16
> bit reads for the 16 bit bus), then another 200us BUSY from the flash,
> two more 16 bit reads, etc, all the way to the end of the logic
> analyzer screen.
>
> What I think is happening is that the flash background thread is
> running very efficiently - it comes in, issues a page program, and
> relinquishes the CPU.  The thread reading the video chip then runs,
> stalls for 200us waiting for a single read, gets its read, then is
> preempted for the flash BGT.
>
> My guess is that the scheduler sees the flash background thread as
> running almost not at all, and the video thread as running a lot more,
> although it's stalled for most of the first 200us of its time slice on
> a single bus transaction, so it can't really do anything with its time
> slice.  I further suspect that the scheduler is dynamically adjusting
> the priorities to boost the flash BGT, since it's using much less CPU
> time than the video thread, even though the video thread can't use
> most of its time slice.  Can someone tell me if this makes sense?
>
> I tried some messing with priorities, but ultimately the flash has to
> run, and it has to run frequently in very short bursts to issue all of
> the page programs.  The video chip needs to be serviced promptly, so
> there is always a significant chance that it will run right after a
> page program is issued.
>
> I tried disabling preemption for the duration of a transfer in the
> video driver so it wouldn't get preempted once it had waited its 200us
> to get the bus.  It helped, but ultimately there's still a 200us delay
> to perform a sequence of operations that usually take somewhere
> between 5 and 30 us.
>
> Most devices that would sit on the bus will only assert the BUSY line
> while the chip select is held.  The NAND, however, asserts BUSY for
> the duration of a page program.  So I could add a gate to the BUSY
> line to gate it with the chip select.  This would require a respin of
> the board, and I'm not 100% certain that it wouldn't confuse the
> 8315's NAND controller.  I'm going to try this next week.  I could
> also take the bus controller out of flash (FCM) mode, depop the
> resistors to the NAND's BUSY line, and have the NAND layer talk to the
> NAND like it's just a chip on a plain old bus, and poll for BUSY.
> This option might be better than it sounds, since the delays are very
> predictable.
>
> Any words of wisdom?

Freescale mentioned last time they visited us that there is a bus
problem with the NAND controller and it sounds similar to what
you are describing. They mentioned a workaround too so you
should contact them for details, I really can't say much more.

 Jocke



From baruch at tkos.co.il  Mon Oct 11 05:19:38 2010
From: baruch at tkos.co.il (Baruch Siach)
Date: Mon, 11 Oct 2010 11:19:38 +0200
Subject: [PATCH] nanddump: fix initialization of bad blocks oob data buffer
Message-ID: <0870ac8ab250ec91dceb2cc461fe82c0d7995bc8.1286788714.git.baruch@tkos.co.il>

When dumping oob data of a bad block, initialize oobbuf with 0xff, instead of
readbuf.  This avoids bogus oob data on output.

Signed-off-by: Baruch Siach <baruch at tkos.co.il>
---
 nanddump.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 3589931..0fdf736 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -452,7 +452,7 @@ int main(int argc, char * const argv[])
 			continue;
 
 		if (badblock) {
-			memset (readbuf, 0xff, meminfo.oobsize);
+			memset (oobbuf, 0xff, meminfo.oobsize);
 		} else {
 			/* Read OOB data and exit on failure */
 			oob.start = ofs;
-- 
1.7.1



From roman.tereshonkov at nokia.com  Mon Oct 11 07:47:32 2010
From: roman.tereshonkov at nokia.com (Roman Tereshonkov)
Date: Mon, 11 Oct 2010 14:47:32 +0300
Subject: [PATCH] mtd: onenand: fix 4KB page onenand chip recognition
Message-ID: <1286797652-13610-1-git-send-email-roman.tereshonkov@nokia.com>

For 4Gb non-DDP chip it does not follow that it is always 4KB page chip.
The number of data buffers is checked and if it is equal to 1
we suppose that it is 4KB page onenand chip.

Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
---
 drivers/mtd/onenand/onenand_base.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a2bb520..3684313 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3365,18 +3365,19 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
 static void onenand_check_features(struct mtd_info *mtd)
 {
 	struct onenand_chip *this = mtd->priv;
-	unsigned int density, process;
+	unsigned int density, process, numbufs;
 
 	/* Lock scheme depends on density and process */
 	density = onenand_get_density(this->device_id);
 	process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
+	numbufs = this->read_word(this->base + ONENAND_REG_NUM_BUFFERS) >> 8;
 
 	/* Lock scheme */
 	switch (density) {
 	case ONENAND_DEVICE_DENSITY_4Gb:
 		if (ONENAND_IS_DDP(this))
 			this->options |= ONENAND_HAS_2PLANE;
-		else
+		else if (numbufs == 1)
 			this->options |= ONENAND_HAS_4KB_PAGE;
 
 	case ONENAND_DEVICE_DENSITY_2Gb:
-- 
1.7.0.4



From kmpark at infradead.org  Mon Oct 11 08:04:10 2010
From: kmpark at infradead.org (Kyungmin Park)
Date: Mon, 11 Oct 2010 21:04:10 +0900
Subject: [PATCH] mtd: onenand: fix 4KB page onenand chip recognition
In-Reply-To: <1286797652-13610-1-git-send-email-roman.tereshonkov@nokia.com>
References: <1286797652-13610-1-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <AANLkTi=ZvB_5eWJyJW2s4DQpt1emASrxZGGnxyhw3KFm@mail.gmail.com>

Hi,

Good catch. I didn't know that.
My 4KiB pagesize has 0x0102
and 2KiB pagesize has 0x0202

Acked-by: Kyungmin Park <kyungmin.park at samsung.com>

On Mon, Oct 11, 2010 at 8:47 PM, Roman Tereshonkov
<roman.tereshonkov at nokia.com> wrote:
> For 4Gb non-DDP chip it does not follow that it is always 4KB page chip.
> The number of data buffers is checked and if it is equal to 1
> we suppose that it is 4KB page onenand chip.
>
> Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
> ---
> ?drivers/mtd/onenand/onenand_base.c | ? ?5 +++--
> ?1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
> index a2bb520..3684313 100644
> --- a/drivers/mtd/onenand/onenand_base.c
> +++ b/drivers/mtd/onenand/onenand_base.c
> @@ -3365,18 +3365,19 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
> ?static void onenand_check_features(struct mtd_info *mtd)
> ?{
> ? ? ? ?struct onenand_chip *this = mtd->priv;
> - ? ? ? unsigned int density, process;
> + ? ? ? unsigned int density, process, numbufs;
>
> ? ? ? ?/* Lock scheme depends on density and process */
> ? ? ? ?density = onenand_get_density(this->device_id);
> ? ? ? ?process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
> + ? ? ? numbufs = this->read_word(this->base + ONENAND_REG_NUM_BUFFERS) >> 8;
>
> ? ? ? ?/* Lock scheme */
> ? ? ? ?switch (density) {
> ? ? ? ?case ONENAND_DEVICE_DENSITY_4Gb:
> ? ? ? ? ? ? ? ?if (ONENAND_IS_DDP(this))
> ? ? ? ? ? ? ? ? ? ? ? ?this->options |= ONENAND_HAS_2PLANE;
> - ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? else if (numbufs == 1)
> ? ? ? ? ? ? ? ? ? ? ? ?this->options |= ONENAND_HAS_4KB_PAGE;
>
> ? ? ? ?case ONENAND_DEVICE_DENSITY_2Gb:
> --
> 1.7.0.4
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From vapier.adi at gmail.com  Mon Oct 11 13:07:03 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 11 Oct 2010 13:07:03 -0400
Subject: [PATCH] nanddump: fix initialization of bad blocks oob data buffer
In-Reply-To: <0870ac8ab250ec91dceb2cc461fe82c0d7995bc8.1286788714.git.baruch@tkos.co.il>
References: <0870ac8ab250ec91dceb2cc461fe82c0d7995bc8.1286788714.git.baruch@tkos.co.il>
Message-ID: <AANLkTikVHPH8KkpcfKHM9bSoqx2iCqNfx+4VZMLWP-RE@mail.gmail.com>

On Mon, Oct 11, 2010 at 05:19, Baruch Siach wrote:
> When dumping oob data of a bad block, initialize oobbuf with 0xff, instead of
> readbuf. ?This avoids bogus oob data on output.
>
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>

Acked-by: Mike Frysinger <vapier at gentoo.org>
-mike


From dedekind1 at gmail.com  Mon Oct 11 14:58:14 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 11 Oct 2010 21:58:14 +0300
Subject: [PATCH v3] OMAP: NAND: Fix static declaration warning
In-Reply-To: <1286315819-5906-1-git-send-email-manjugk@ti.com>
References: <1286315819-5906-1-git-send-email-manjugk@ti.com>
Message-ID: <1286823495.1742.0.camel@brekeke>

On Wed, 2010-10-06 at 03:26 +0530, G, Manjunath Kondaiah wrote:
> This patch fixes sparse warning for static declaration of variable "use_dma"
> 
> drivers/mtd/nand/omap2.c:114:11: warning: symbol 'use_dma' was not declared. Should it be static?
> 
> Signed-off-by: G, Manjunath Kondaiah <manjugk at ti.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mtd at lists.infradead.org
> Cc: Tony Lindgren <tony at atomide.com>
> Cc: Nishanth Menon <nm at ti.com>

I've pushed this patch to my l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Oct 11 14:59:20 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 11 Oct 2010 21:59:20 +0300
Subject: [PATCH v3] OMAP2/3: NAND: Convert write/read functions to raw
	read/write
In-Reply-To: <1286315819-5906-3-git-send-email-manjugk@ti.com>
References: <1286315819-5906-1-git-send-email-manjugk@ti.com>
	<1286315819-5906-3-git-send-email-manjugk@ti.com>
Message-ID: <1286823560.1742.2.camel@brekeke>

On Wed, 2010-10-06 at 03:26 +0530, G, Manjunath Kondaiah wrote:
> Following sparse warnings exists due to use of writel/w and readl/w functions.
> 
> This patch fixes the sparse warnings by converting readl/w functions usage into
> __raw_readl/__raw_readw functions.
> 
> drivers/mtd/nand/omap2.c:484:15: warning: symbol '__v' shadows an earlier one
> drivers/mtd/nand/omap2.c:484:15: originally declared here
> 
> drivers/mtd/onenand/omap2.c:86:9: warning: symbol '__v' shadows an earlier one
> drivers/mtd/onenand/omap2.c:86:9: originally declared here
> 
> Signed-off-by: G, Manjunath Kondaiah <manjugk at ti.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-mtd at lists.infradead.org

I've pushed this patch to my l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Oct 11 15:24:23 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 11 Oct 2010 22:24:23 +0300
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
Message-ID: <1286825063.1742.13.camel@brekeke>

On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
> Hi,
> 
> I have been using this tweak for some time now, and I am getting tired of 
> having to resort to it so often.
> It allows to pass such cmdline root as: 
>  "root=mtdb:ubivolx rootfstype=squashfs"
> I am pretty sure many people use squashfs/cramfs filesystems on top of nand, 
> for example, and I thought that this might initiate discussion.
> 
> -- 
> Karl
> 
> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
> ---
>  init/do_mounts.c |   15 +++++++++++++--
>  1 files changed, 13 insertions(+), 2 deletions(-)

Dunno... 

First of all, if you have to do this, let it be mtdblock, not mtdb - no
need to breed aliases.

But how about teaching squashfs to understand mtdX and mtd:name syntax
instead?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From iwo at call-direct.com.au  Mon Oct 11 18:54:08 2010
From: iwo at call-direct.com.au (Iwo Mergler)
Date: Tue, 12 Oct 2010 08:54:08 +1000
Subject: Scheduler latency problems when using NAND
In-Reply-To: <20101009174246.GA19591@postdiluvian.org>
References: <20100929221401.GA32583@postdiluvian.org>	<4CA3D92E.9060109@call-direct.com.au>
	<20101009174246.GA19591@postdiluvian.org>
Message-ID: <4CB39590.3070404@call-direct.com.au>

Mark Mason wrote:
> The flash driver (fsl_elbc_nand.c) goes to sleep right after it issues
> a page program, and a context switch to another high priority thread
> takes place promptly.  This thread is often one that reads from
> another (video) chip on the same bus as the flash (the MPC8315 LBC).
> The flash asserts its BUSY line while the page program is in
> operation.  When the other thread comes along to read from video chip,
> it's held off for the 200us duration of the page program (the LBC
> controller for the video chip is running in UPM mode, so the BUSY line
> is a BUSY line and not a TA line, in case any 83xx junkies are reading
> this).
> 
> What I see on a logic analyzer is the BUSY line held by the flash for
> 200us, a single 32 bit read of the video chip (broken up into two 16
> bit reads for the 16 bit bus), then another 200us BUSY from the flash,
> two more 16 bit reads, etc, all the way to the end of the logic
> analyzer screen.

I don't know your controller, but I'm surprised that the FLASH write
can stall the bus like that. It seems a high price to pay for not
having to implement some FLASH write interrupt or wait. Are you sure
that this is the recommended way to connect a FLASH?

As you said, it looks like it may be worthwhile to abandon the NAND
controller and implement a software driver via an SRAM bus mode.

Maybe even to the extent of reading the video controller *while*
polling the BUSY line. You could wake up the FLASH thread from the
video driver when the write is done.

> 
> What I think is happening is that the flash background thread is
> running very efficiently - it comes in, issues a page program, and
> relinquishes the CPU.  The thread reading the video chip then runs,
> stalls for 200us waiting for a single read, gets its read, then is
> preempted for the flash BGT.
> 
> My guess is that the scheduler sees the flash background thread as
> running almost not at all, and the video thread as running a lot more,
> although it's stalled for most of the first 200us of its time slice on
> a single bus transaction, so it can't really do anything with its time
> slice.  I further suspect that the scheduler is dynamically adjusting
> the priorities to boost the flash BGT, since it's using much less CPU
> time than the video thread, even though the video thread can't use
> most of its time slice.  Can someone tell me if this makes sense?

I'm not sure about this, but I thought the scheduler only does priority
escalation when running userspace threads. For kernel thread scheduling,
you get extra priority levels where the higher priority thread always
wins if its ready to run.


Best regards,

Iwo




From baruch at tkos.co.il  Tue Oct 12 04:23:55 2010
From: baruch at tkos.co.il (Baruch Siach)
Date: Tue, 12 Oct 2010 10:23:55 +0200
Subject: [PATCH 2/2] nanddump: always check the first erase block
In-Reply-To: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>
References: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>
Message-ID: <c0bf28b432c6f1e6e5ed634ff64afcf46762503a.1286871735.git.baruch@tkos.co.il>

Check the first block even when start_addr is not eraseblock aligned.

Signed-off-by: Baruch Siach <baruch at tkos.co.il>
---
 nanddump.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index d6d1352..9267a1c 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -283,7 +283,7 @@ int main(int argc, char * const argv[])
 	struct mtd_oob_buf oob = {0, 16, oobbuf};
 	mtd_info_t meminfo;
 	char pretty_buf[PRETTY_BUF_LEN];
-	int oobinfochanged = 0 ;
+	int oobinfochanged = 0, firstblock = 1;
 	struct nand_oobinfo old_oobinfo;
 	struct mtd_ecc_stats stat1, stat2;
 	bool eccstats = false;
@@ -405,8 +405,10 @@ int main(int argc, char * const argv[])
 		// new eraseblock , check for bad block
 		if (noskipbad) {
 			badblock = 0;
-		} else if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
+		} else if (blockstart != (ofs & (~meminfo.erasesize + 1)) ||
+				firstblock) {
 			blockstart = ofs & (~meminfo.erasesize + 1);
+			firstblock = 0;
 			if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
 				perror("ioctl(MEMGETBADBLOCK)");
 				goto closeall;
-- 
1.7.1



From baruch at tkos.co.il  Tue Oct 12 04:23:54 2010
From: baruch at tkos.co.il (Baruch Siach)
Date: Tue, 12 Oct 2010 10:23:54 +0200
Subject: [PATCH 1/2] nanddump: verify that start address is page aligned
Message-ID: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>

Make nanddump consistent with nandwrite, which does not accept non page aligned
start addresses. Thus, non page aligned dumps are useless.

Signed-off-by: Baruch Siach <baruch at tkos.co.il>
---
 nanddump.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 0fdf736..d6d1352 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -377,6 +377,12 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Initialize start/end addresses and block size */
+	if (start_addr & (meminfo.writesize - 1)) {
+		fprintf(stderr, "The start address is not page-aligned !\n"
+				"The pagesize of this NAND Flash is 0x%x.\n",
+				meminfo.writesize);
+		goto closeall;
+	}
 	if (length)
 		end_addr = start_addr + length;
 	if (!length || end_addr > meminfo.size)
-- 
1.7.1



From dedekind1 at gmail.com  Tue Oct 12 04:42:39 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 11:42:39 +0300
Subject: [PATCH] jffs2: Fix serious write stall due to erase
In-Reply-To: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>
References: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>
Message-ID: <1286872959.2164.5.camel@localhost>

On Thu, 2010-10-07 at 18:01 +0200, Joakim Tjernlund wrote:
> Drop the alloc_sem before erasing flash in
> jffs2_garbage_collect_pass().
> Otherwise writes are put on hold until the erase
> has finised.
> 
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> ---
> 
>  I am fairly sure it is safe to unlock the alloc_sem before
>  calling jffs2_erase_pending_blocks(). Extra confirmation
>  would be great though.
> 
>  This problem was introduced in 2.6.35

This looks safe for me as well, but I do not remember JFFS2 locking
rules anymore, so I'm not 100% sure. I've pushed your patch to my
l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Oct 12 04:48:57 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 11:48:57 +0300
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
Message-ID: <1286873337.2164.6.camel@localhost>

On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> Test if it did and then abort.
> 
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> ---
>  fs/jffs2/nodemgmt.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From joakim.tjernlund at transmode.se  Tue Oct 12 04:55:29 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Tue, 12 Oct 2010 10:55:29 +0200
Subject: [PATCH] jffs2: Fix serious write stall due to erase
In-Reply-To: <1286872959.2164.5.camel@localhost>
References: <1286467304-23370-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1286872959.2164.5.camel@localhost>
Message-ID: <OFA79EFC65.D894AD39-ONC12577BA.0030F160-C12577BA.00310669@transmode.se>

Artem Bityutskiy <dedekind1 at gmail.com> wrote on 2010/10/12 10:42:39:
>
> On Thu, 2010-10-07 at 18:01 +0200, Joakim Tjernlund wrote:
> > Drop the alloc_sem before erasing flash in
> > jffs2_garbage_collect_pass().
> > Otherwise writes are put on hold until the erase
> > has finised.
> >
> > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> > ---
> >
> >  I am fairly sure it is safe to unlock the alloc_sem before
> >  calling jffs2_erase_pending_blocks(). Extra confirmation
> >  would be great though.
> >
> >  This problem was introduced in 2.6.35
>
> This looks safe for me as well, but I do not remember JFFS2 locking
> rules anymore, so I'm not 100% sure. I've pushed your patch to my
> l2-mtd-2.6.git.

Thanks, now if just David could weigh in :)

      Jocke



From dedekind1 at gmail.com  Tue Oct 12 04:54:33 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 11:54:33 +0300
Subject: [PATCH] jffs2: Reduce excessive scan of empty blocks
In-Reply-To: <1286471374-25840-1-git-send-email-Joakim.Tjernlund@transmode.se>
References: <1286471374-25840-1-git-send-email-Joakim.Tjernlund@transmode.se>
Message-ID: <1286873673.2164.7.camel@localhost>

On Thu, 2010-10-07 at 19:09 +0200, Joakim Tjernlund wrote:
> Scanning 1024 bytes to see if an EB is empty is a bit much.
> Lower it to 256 bytes and make sure the while loop is
> optimized.
> 
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> ---
>  fs/jffs2/scan.c |   12 ++++++------
>  1 files changed, 6 insertions(+), 6 deletions(-)

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Oct 12 04:55:03 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 11:55:03 +0300
Subject: [PATCH] mtd: physmap_of: Loop through all "reg" tuples for mapping
In-Reply-To: <1286541687-5706-1-git-send-email-sr@denx.de>
References: <1286541687-5706-1-git-send-email-sr@denx.de>
Message-ID: <1286873703.2164.8.camel@localhost>

On Fri, 2010-10-08 at 14:41 +0200, Stefan Roese wrote:
> This patch changes the loop over the "reg" tuples to not exit
> directly upon of_address_to_resource() failure but to continue
> with the next "reg" tuple instead. This failure could be due to
> size = 0, which might be passed via the device-tree.
> 
> This is needed for boards, where a "reg" tuple might have size 0
> (of_address_to_resource() returns with EINVAL when size = 0).
> 
> Example:
> 
> Fully equipped board:
> 
> 	reg = <0 0x00000000 0x00400000
> 	       0 0x00400000 0x00400000>;
> 
> Partially equipped board:
> 
> 	reg = <0 0x00000000 0x00400000
> 	       0 0x00400000 0x00000000>;
> 
> This could be the case on boards with runtime detection of
> multiple NOR flash configurations where the detected flash size
> is inserted into the dtb in U-Boot.
> 
> Signed-off-by: Stefan Roese <sr at denx.de>
> ---
>  drivers/mtd/maps/physmap_of.c |    8 +++++---
>  1 files changed, 5 insertions(+), 3 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Oct 12 05:02:57 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 12:02:57 +0300
Subject: [RFC] mtd: add MEMSETGOODBLOCK ioctl
In-Reply-To: <1286335318-17542-1-git-send-email-jon.povey@racelogic.co.uk>
References: <1286335318-17542-1-git-send-email-jon.povey@racelogic.co.uk>
Message-ID: <1286874177.2164.14.camel@localhost>

On Wed, 2010-10-06 at 12:21 +0900, Jon Povey wrote:
> Adds the MEMSETGOODBLOCK ioctl, inverse operation of MEMSETBADBLOCK for
> times when you really are sure that a block is good, but was marked bad
> in error.
> 
> WARNING: This ioctl should not be casually used, you can't magically
> fix unreliable blocks, and causing the system to try and use them may
> cause you problems. Manufacturer-marked bad blocks may be forgotten
> and impossible to find again later. Be careful.
> 
> This ioctl is for situations where you know what you are doing, for
> example your bootloader has to be written with a different OOB layout
> and scanned as bad when the BBT was generated, but you know it's good
> and want to rewrite it from Linux.
> 
> Signed-off-by: Jon Povey <jon.povey at racelogic.co.uk>
> ---
> This is a request for comment on this approach to bad blocks, this patch
> only considers the nand driver and only versions with a BBT on flash.
> 
> This works for me on davinci DM355 with 2K page NAND flash.
> 
>  drivers/mtd/mtdchar.c        |   13 +++++++++
>  drivers/mtd/mtdpart.c        |   18 ++++++++++++
>  drivers/mtd/nand/nand_base.c |   60 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/mtd.h      |    1 +
>  include/linux/mtd/nand.h     |    2 +
>  include/mtd/mtd-abi.h        |    1 +
>  6 files changed, 95 insertions(+), 0 deletions(-)

Briefly looked - you do not have any locking. You should have some
nand_get_device() calls.

Also, did you investigate whether it is possible to distinguish between
factory-marked bad eraseblocks and user-marked bad eraseblocks?

Also, if this patch to go in, I'd really like to see some Reviewed-by
and Tested by. Or some good list of setups where you tested this
yourself and how you did this. Is this possible?

Let's CC Mike who was interested in this and Brian who was doing great
job in the BBT area recently and could review this patch.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Jon.Povey at racelogic.co.uk  Tue Oct 12 05:24:44 2010
From: Jon.Povey at racelogic.co.uk (Jon Povey)
Date: Tue, 12 Oct 2010 10:24:44 +0100
Subject: [RFC] mtd: add MEMSETGOODBLOCK ioctl
In-Reply-To: <1286874177.2164.14.camel@localhost>
Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093EEAAB3A@Cloud.RL.local>

Just to make clear, this patch should NOT go in in the present form.
I am just posting it to see if some discussion starts about how this
should be done.

In the current form, it's just a hack that works for me.

Artem Bityutskiy wrote:
> On Wed, 2010-10-06 at 12:21 +0900, Jon Povey wrote:
>> Adds the MEMSETGOODBLOCK ioctl, inverse operation of MEMSETBADBLOCK
>> for times when you really are sure that a block is good, but was
>> marked bad in error.

> Briefly looked - you do not have any locking. You should have some
> nand_get_device() calls.

I pretty much copy-pasted from the existing SETBADBLOCK support, maybe
I missed something or maybe they are missing locking too.

> Also, did you investigate whether it is possible to
> distinguish between
> factory-marked bad eraseblocks and user-marked bad eraseblocks?

Yes, that can be done. They have different bits in the BBT. This ioctl
ignores them though, for my purposes sometimes MTD thinks blocks are
factory-bad when they are not. This ioctl says "I don't care why you
think this block is bad, I know better".

Thinking about this, to handle well in userland software,
MEMGETBADBLOCK should return more than just boolean BAD or GOOD, maybe
it should return different values for factory bad, reserved, went-bad.

The mtd-abi.h doesn't seem to have any spec, it looks like it comes
from nand_bbt.c:nand_isbad_bbt() which returns only 0 or 1.
Don't know if this could be quietly extended without breaking ABI.

> Also, if this patch to go in, I'd really like to see some Reviewed-by
> and Tested by. Or some good list of setups where you tested this
> yourself and how you did this. Is this possible?

Sure. But this isn't even ready for that kind of testing in my opinion.
Like I say it's a hack and conversation-starter.

> Let's CC Mike who was interested in this and Brian who was doing great
> job in the BBT area recently and could review this patch.



--
Jon Povey
jon.povey at racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 .
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB .

The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network




From dedekind1 at gmail.com  Tue Oct 12 05:42:59 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 12:42:59 +0300
Subject: [PATCH] mtd: onenand: fix 4KB page onenand chip recognition
In-Reply-To: <1286797652-13610-1-git-send-email-roman.tereshonkov@nokia.com>
References: <1286797652-13610-1-git-send-email-roman.tereshonkov@nokia.com>
Message-ID: <1286876579.2164.30.camel@localhost>

On Mon, 2010-10-11 at 14:47 +0300, Roman Tereshonkov wrote:
> For 4Gb non-DDP chip it does not follow that it is always 4KB page chip.
> The number of data buffers is checked and if it is equal to 1
> we suppose that it is 4KB page onenand chip.
> 
> Signed-off-by: Roman Tereshonkov <roman.tereshonkov at nokia.com>
> ---
>  drivers/mtd/onenand/onenand_base.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Oct 12 06:02:22 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 13:02:22 +0300
Subject: [PATCH] nanddump: fix initialization of bad blocks oob data buffer
In-Reply-To: <0870ac8ab250ec91dceb2cc461fe82c0d7995bc8.1286788714.git.baruch@tkos.co.il>
References: <0870ac8ab250ec91dceb2cc461fe82c0d7995bc8.1286788714.git.baruch@tkos.co.il>
Message-ID: <1286877742.2164.40.camel@localhost>

On Mon, 2010-10-11 at 11:19 +0200, Baruch Siach wrote:
> When dumping oob data of a bad block, initialize oobbuf with 0xff, instead of
> readbuf.  This avoids bogus oob data on output.
> 
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
>  nanddump.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/nanddump.c b/nanddump.c
> index 3589931..0fdf736 100644
> --- a/nanddump.c
> +++ b/nanddump.c
> @@ -452,7 +452,7 @@ int main(int argc, char * const argv[])
>  			continue;
>  
>  		if (badblock) {
> -			memset (readbuf, 0xff, meminfo.oobsize);
> +			memset (oobbuf, 0xff, meminfo.oobsize);
Removed junk white-space
>  		} else {
>  			/* Read OOB data and exit on failure */
>  			oob.start = ofs;

and push to mtd-utils.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Mingkai.hu at freescale.com  Tue Oct 12 06:18:29 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:29 +0800
Subject: [PATCH v4 0/5] refactor spi_mpc8xxx.c and add eSPI controller support
Message-ID: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>

This patchset refactor the file spi_mpc8xxx.c to abstract some common 
code as a lib used by the SPI/eSPI controller driver, move the SPI 
controller driver code to spi_fsl_spi.c, and add the eSPI controller 
support with spi_fsl_espi.c.

v4 main change:
 - Update to the latest kernel base(Linux 2.6.36-rc7).
 - Add support to the transaction that the length is grater than 0xFFFF
   in the eSPI controller's driver.
 - Some changes according to Grant and Anton's comments.

Tested on P4080DS and MPC8536DS board.

[PATCH v4 1/5] spi/mpc8xxx: rename spi_mpc8xxx.c to spi_fsl_spi.c
[PATCH v4 2/5] spi/mpc8xxx: refactor the common code for SPI/eSPI controller
[PATCH v4 3/5] eSPI: add eSPI controller support
[PATCH v4 4/5] powerpc/of: add eSPI controller dts bindings and DTS modification
[PATCH v4 5/5] mtd: m25p80: add support to parse the partitions by OF node

Thanks,
Mingkai



From Mingkai.hu at freescale.com  Tue Oct 12 06:18:33 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:33 +0800
Subject: [PATCH v4 4/5] powerpc/of: add eSPI controller dts bindings and DTS
	modification
In-Reply-To: <1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>

Also modifiy the document of cell-index in SPI controller. Add the
SPI flash(s25fl128p01) support on p4080ds and mpc8536ds board.

Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
---
v4:
 - Updated to latest kernel base(Linux 2.6.36-rc7).

 Documentation/powerpc/dts-bindings/fsl/spi.txt |   24 ++++++++++-
 arch/powerpc/boot/dts/mpc8536ds.dts            |   52 ++++++++++++++++++++++++
 arch/powerpc/boot/dts/p4080ds.dts              |   11 ++---
 3 files changed, 79 insertions(+), 8 deletions(-)

diff --git a/Documentation/powerpc/dts-bindings/fsl/spi.txt b/Documentation/powerpc/dts-bindings/fsl/spi.txt
index 80510c0..777abd7 100644
--- a/Documentation/powerpc/dts-bindings/fsl/spi.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/spi.txt
@@ -1,7 +1,9 @@
 * SPI (Serial Peripheral Interface)
 
 Required properties:
-- cell-index : SPI controller index.
+- cell-index : QE SPI subblock index.
+		0: QE subblock SPI1
+		1: QE subblock SPI2
 - compatible : should be "fsl,spi".
 - mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
 - reg : Offset and length of the register set for the device
@@ -29,3 +31,23 @@ Example:
 		gpios = <&gpio 18 1	// device reg=<0>
 			 &gpio 19 1>;	// device reg=<1>
 	};
+
+
+* eSPI (Enhanced Serial Peripheral Interface)
+
+Required properties:
+- compatible : should be "fsl,mpc8536-espi".
+- reg : Offset and length of the register set for the device.
+- interrupts : should contain eSPI interrupt, the device has one interrupt.
+- fsl,espi-num-chipselects : the number of the chipselect signals.
+
+Example:
+	spi at 110000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,mpc8536-espi";
+		reg = <0x110000 0x1000>;
+		interrupts = <53 0x2>;
+		interrupt-parent = <&mpic>;
+		fsl,espi-num-chipselects = <4>;
+	};
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
index 815cebb..a75c10e 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dts
+++ b/arch/powerpc/boot/dts/mpc8536ds.dts
@@ -108,6 +108,58 @@
 			};
 		};
 
+		spi at 7000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc8536-espi";
+			reg = <0x7000 0x1000>;
+			interrupts = <59 0x2>;
+			interrupt-parent = <&mpic>;
+			fsl,espi-num-chipselects = <4>;
+
+			flash at 0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>;
+				partition at u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+					read-only;
+				};
+				partition at kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+					read-only;
+				};
+				partition at dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+					read-only;
+				};
+				partition at fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+			flash at 1 {
+				compatible = "spansion,s25sl12801";
+				reg = <1>;
+				spi-max-frequency = <40000000>;
+			};
+			flash at 2 {
+				compatible = "spansion,s25sl12801";
+				reg = <2>;
+				spi-max-frequency = <40000000>;
+			};
+			flash at 3 {
+				compatible = "spansion,s25sl12801";
+				reg = <3>;
+				spi-max-frequency = <40000000>;
+			};
+		};
+
 		dma at 21300 {
 			#address-cells = <1>;
 			#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 2f0de24..5b7fc29 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -236,22 +236,19 @@
 		};
 
 		spi at 110000 {
-			cell-index = <0>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			compatible = "fsl,espi";
+			compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
 			reg = <0x110000 0x1000>;
 			interrupts = <53 0x2>;
 			interrupt-parent = <&mpic>;
-			espi,num-ss-bits = <4>;
-			mode = "cpu";
+			fsl,espi-num-chipselects = <4>;
 
-			fsl_m25p80 at 0 {
+			flash at 0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "fsl,espi-flash";
+				compatible = "spansion,s25sl12801";
 				reg = <0>;
-				linux,modalias = "fsl_m25p80";
 				spi-max-frequency = <40000000>; /* input clock */
 				partition at u-boot {
 					label = "u-boot";
-- 
1.6.4




From Mingkai.hu at freescale.com  Tue Oct 12 06:18:34 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:34 +0800
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the partitions by OF
	node
In-Reply-To: <1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>

Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
Acked-by: Grant Likely <grant.likely at secretlab.ca>
---
v4:
 - Updated to latest kernel base(Linux 2.6.36-rc7).
 - Made changes according to Grant's comments.

 drivers/mtd/devices/m25p80.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 6f512b5..9d20738 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -924,6 +924,11 @@ static int __devinit m25p_probe(struct spi_device *spi)
 			nr_parts = data->nr_parts;
 		}
 
+		if (nr_parts <= 0 && spi->dev.of_node) {
+			nr_parts = of_mtd_parse_partitions(&spi->dev,
+					spi->dev.of_node, &parts);
+		}
+
 		if (nr_parts > 0) {
 			for (i = 0; i < nr_parts; i++) {
 				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.6.4




From Mingkai.hu at freescale.com  Tue Oct 12 06:18:31 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:31 +0800
Subject: [PATCH v4 2/5] spi/mpc8xxx: refactor the common code for SPI/eSPI
	controller
In-Reply-To: <1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>

Refactor the common code in file spi_fsl_spi.c to spi_fsl_lib.c used
by SPI/eSPI controller driver as a library, and leave the QE/CPM SPI
controller code in the SPI controller driver spi_fsl_spi.c.

Because the register map of the SPI controller and eSPI controller
is so different, also leave the code operated the register to the
driver code, not the common code.

Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
---
v4:
 - Updated to latest kernel base(Linux 2.6.36-rc7).

 drivers/spi/Kconfig       |    5 +
 drivers/spi/Makefile      |    1 +
 drivers/spi/spi_fsl_lib.c |  237 +++++++++++++++++++
 drivers/spi/spi_fsl_lib.h |  119 ++++++++++
 drivers/spi/spi_fsl_spi.c |  552 +++++++++++++--------------------------------
 5 files changed, 522 insertions(+), 392 deletions(-)
 create mode 100644 drivers/spi/spi_fsl_lib.c
 create mode 100644 drivers/spi/spi_fsl_lib.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6af34c6..79ad06f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -182,9 +182,14 @@ config SPI_MPC512x_PSC
 	  This enables using the Freescale MPC5121 Programmable Serial
 	  Controller in SPI master mode.
 
+config SPI_FSL_LIB
+	tristate
+	depends on FSL_SOC
+
 config SPI_FSL_SPI
 	tristate "Freescale SPI controller"
 	depends on FSL_SOC
+	select SPI_FSL_LIB
 	help
 	  This enables using the Freescale SPI controllers in master mode.
 	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 770817c..7974c21 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
+obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
 obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
new file mode 100644
index 0000000..5cd741f
--- /dev/null
+++ b/drivers/spi/spi_fsl_lib.c
@@ -0,0 +1,237 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
+ *
+ * Copyright 2010 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 <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+#define MPC8XXX_SPI_RX_BUF(type) 					  \
+void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
+{									  \
+	type *rx = mpc8xxx_spi->rx;					  \
+	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
+	mpc8xxx_spi->rx = rx;						  \
+}
+
+#define MPC8XXX_SPI_TX_BUF(type)				\
+u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
+{								\
+	u32 data;						\
+	const type *tx = mpc8xxx_spi->tx;			\
+	if (!tx)						\
+		return 0;					\
+	data = *tx++ << mpc8xxx_spi->tx_shift;			\
+	mpc8xxx_spi->tx = tx;					\
+	return data;						\
+}
+
+MPC8XXX_SPI_RX_BUF(u8)
+MPC8XXX_SPI_RX_BUF(u16)
+MPC8XXX_SPI_RX_BUF(u32)
+MPC8XXX_SPI_TX_BUF(u8)
+MPC8XXX_SPI_TX_BUF(u16)
+MPC8XXX_SPI_TX_BUF(u32)
+
+struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
+{
+	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
+}
+
+void mpc8xxx_spi_work(struct work_struct *work)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
+						       work);
+
+	spin_lock_irq(&mpc8xxx_spi->lock);
+	while (!list_empty(&mpc8xxx_spi->queue)) {
+		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
+						   struct spi_message, queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mpc8xxx_spi->lock);
+
+		if (mpc8xxx_spi->spi_do_one_msg)
+			mpc8xxx_spi->spi_do_one_msg(m);
+
+		spin_lock_irq(&mpc8xxx_spi->lock);
+	}
+	spin_unlock_irq(&mpc8xxx_spi->lock);
+}
+
+int mpc8xxx_spi_transfer(struct spi_device *spi,
+				struct spi_message *m)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
+	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
+	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
+	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+
+	return 0;
+}
+
+void mpc8xxx_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+	if (flags & SPI_QE_CPU_MODE) {
+		return "QE CPU";
+	} else if (flags & SPI_CPM_MODE) {
+		if (flags & SPI_QE)
+			return "QE";
+		else if (flags & SPI_CPM2)
+			return "CPM2";
+		else
+			return "CPM1";
+	}
+	return "CPU";
+}
+
+int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+			unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int ret = 0;
+
+	master = dev_get_drvdata(dev);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
+			| SPI_LSB_FIRST | SPI_LOOP;
+
+	master->transfer = mpc8xxx_spi_transfer;
+	master->cleanup = mpc8xxx_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->dev = dev;
+	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
+	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+	mpc8xxx_spi->flags = pdata->flags;
+	mpc8xxx_spi->spibrg = pdata->sysclk;
+	mpc8xxx_spi->irq = irq;
+
+	mpc8xxx_spi->rx_shift = 0;
+	mpc8xxx_spi->tx_shift = 0;
+
+	init_completion(&mpc8xxx_spi->done);
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->max_chipselect;
+
+	spin_lock_init(&mpc8xxx_spi->lock);
+	init_completion(&mpc8xxx_spi->done);
+	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
+	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+		dev_name(master->dev.parent));
+	if (mpc8xxx_spi->workqueue == NULL) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+int __devexit mpc8xxx_spi_remove(struct device *dev)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct spi_master *master;
+
+	master = dev_get_drvdata(dev);
+	mpc8xxx_spi = spi_master_get_devdata(master);
+
+	flush_workqueue(mpc8xxx_spi->workqueue);
+	destroy_workqueue(mpc8xxx_spi->workqueue);
+	spi_unregister_master(master);
+
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+
+	if (mpc8xxx_spi->spi_remove)
+		mpc8xxx_spi->spi_remove(mpc8xxx_spi);
+
+	return 0;
+}
+
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct mpc8xxx_spi_probe_info *pinfo;
+	struct fsl_spi_platform_data *pdata;
+	const void *prop;
+	int ret = -ENOMEM;
+
+	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	pdata = &pinfo->pdata;
+	dev->platform_data = pdata;
+
+	/* Allocate bus num dynamically. */
+	pdata->bus_num = -1;
+
+	/* SPI controller is either clocked from QE or SoC clock. */
+	pdata->sysclk = get_brgfreq();
+	if (pdata->sysclk == -1) {
+		pdata->sysclk = fsl_get_sys_freq();
+		if (pdata->sysclk == -1) {
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+
+	prop = of_get_property(np, "mode", NULL);
+	if (prop && !strcmp(prop, "cpu-qe"))
+		pdata->flags = SPI_QE_CPU_MODE;
+	else if (prop && !strcmp(prop, "qe"))
+		pdata->flags = SPI_CPM_MODE | SPI_QE;
+	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+
+	return 0;
+
+err:
+	kfree(pinfo);
+	return ret;
+}
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
new file mode 100644
index 0000000..6ae8949
--- /dev/null
+++ b/drivers/spi/spi_fsl_lib.h
@@ -0,0 +1,119 @@
+/*
+ * Freescale SPI/eSPI controller driver library.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __SPI_FSL_LIB_H__
+#define __SPI_FSL_LIB_H__
+
+/* SPI/eSPI Controller driver's private data. */
+struct mpc8xxx_spi {
+	struct device *dev;
+	void *reg_base;
+
+	/* rx & tx bufs from the spi_transfer */
+	const void *tx;
+	void *rx;
+
+	int subblock;
+	struct spi_pram __iomem *pram;
+	struct cpm_buf_desc __iomem *tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd;
+
+	struct spi_transfer *xfer_in_progress;
+
+	/* dma addresses for CPM transfers */
+	dma_addr_t tx_dma;
+	dma_addr_t rx_dma;
+	bool map_tx_dma;
+	bool map_rx_dma;
+
+	dma_addr_t dma_dummy_tx;
+	dma_addr_t dma_dummy_rx;
+
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32(*get_tx) (struct mpc8xxx_spi *);
+
+	/* hooks for different controller driver */
+	void (*spi_do_one_msg) (struct spi_message *m);
+	void (*spi_remove) (struct mpc8xxx_spi *mspi);
+
+	unsigned int count;
+	unsigned int irq;
+
+	unsigned nsecs;		/* (clock cycle time)/2 */
+
+	u32 spibrg;		/* SPIBRG input clock */
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	unsigned int flags;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+struct spi_mpc8xxx_cs {
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32 (*get_tx) (struct mpc8xxx_spi *);
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+	u32 hw_mode;		/* Holds HW mode register settings */
+};
+
+static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
+{
+	out_be32(reg, val);
+}
+
+static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
+{
+	return in_be32(reg);
+}
+
+struct mpc8xxx_spi_probe_info {
+	struct fsl_spi_platform_data pdata;
+	int *gpios;
+	bool *alow_flags;
+};
+
+extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
+extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
+
+extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
+		struct fsl_spi_platform_data *pdata);
+extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
+		struct spi_transfer *t, unsigned int len);
+extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
+extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
+extern const char *mpc8xxx_spi_strmode(unsigned int flags);
+extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
+		unsigned int irq);
+extern int mpc8xxx_spi_remove(struct device *dev);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+				const struct of_device_id *ofid);
+
+#endif /* __SPI_FSL_LIB_H__ */
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
index 1dd86b8..7ca52d3 100644
--- a/drivers/spi/spi_fsl_spi.c
+++ b/drivers/spi/spi_fsl_spi.c
@@ -1,9 +1,10 @@
 /*
- * MPC8xxx SPI controller driver.
+ * Freescale SPI controller driver.
  *
  * Maintainer: Kumar Gala
  *
  * Copyright (C) 2006 Polycom, Inc.
+ * Copyright 2010 Freescale Semiconductor, Inc.
  *
  * CPM SPI and QE buffer descriptors mode support:
  * Copyright (c) 2009  MontaVista Software, Inc.
@@ -15,18 +16,11 @@
  * option) any later version.
  */
 #include <linux/module.h>
-#include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/completion.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
-#include <linux/device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/platform_device.h>
@@ -38,12 +32,12 @@
 #include <linux/of_platform.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
-#include <linux/slab.h>
 
 #include <sysdev/fsl_soc.h>
 #include <asm/cpm.h>
 #include <asm/qe.h>
-#include <asm/irq.h>
+
+#include "spi_fsl_lib.h"
 
 /* CPM1 and CPM2 are mutually exclusive. */
 #ifdef CONFIG_CPM1
@@ -55,7 +49,7 @@
 #endif
 
 /* SPI Controller registers */
-struct mpc8xxx_spi_reg {
+struct fsl_spi_reg {
 	u8 res1[0x20];
 	__be32 mode;
 	__be32 event;
@@ -80,7 +74,7 @@ struct mpc8xxx_spi_reg {
 
 /*
  * Default for SPI Mode:
- * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ *	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
  */
 #define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
 			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
@@ -102,112 +96,16 @@ struct mpc8xxx_spi_reg {
 #define	SPI_PRAM_SIZE	0x100
 #define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
 
-/* SPI Controller driver's private data. */
-struct mpc8xxx_spi {
-	struct device *dev;
-	struct mpc8xxx_spi_reg __iomem *base;
-
-	/* rx & tx bufs from the spi_transfer */
-	const void *tx;
-	void *rx;
-
-	int subblock;
-	struct spi_pram __iomem *pram;
-	struct cpm_buf_desc __iomem *tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd;
-
-	struct spi_transfer *xfer_in_progress;
-
-	/* dma addresses for CPM transfers */
-	dma_addr_t tx_dma;
-	dma_addr_t rx_dma;
-	bool map_tx_dma;
-	bool map_rx_dma;
-
-	dma_addr_t dma_dummy_tx;
-	dma_addr_t dma_dummy_rx;
-
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32(*get_tx) (struct mpc8xxx_spi *);
-
-	unsigned int count;
-	unsigned int irq;
-
-	unsigned nsecs;		/* (clock cycle time)/2 */
-
-	u32 spibrg;		/* SPIBRG input clock */
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-
-	unsigned int flags;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;
-
-	struct completion done;
-};
-
-static void *mpc8xxx_dummy_rx;
-static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
-static int mpc8xxx_dummy_rx_refcnt;
-
-struct spi_mpc8xxx_cs {
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32 (*get_tx) (struct mpc8xxx_spi *);
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-	u32 hw_mode;		/* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
-	out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
-	return in_be32(reg);
-}
-
-#define MPC83XX_SPI_RX_BUF(type) 					  \
-static									  \
-void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
-{									  \
-	type *rx = mpc8xxx_spi->rx;					  \
-	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
-	mpc8xxx_spi->rx = rx;						  \
-}
-
-#define MPC83XX_SPI_TX_BUF(type)				\
-static								\
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
-{								\
-	u32 data;						\
-	const type *tx = mpc8xxx_spi->tx;			\
-	if (!tx)						\
-		return 0;					\
-	data = *tx++ << mpc8xxx_spi->tx_shift;			\
-	mpc8xxx_spi->tx = tx;					\
-	return data;						\
-}
+static void *fsl_dummy_rx;
+static DEFINE_MUTEX(fsl_dummy_rx_lock);
+static int fsl_dummy_rx_refcnt;
 
-MPC83XX_SPI_RX_BUF(u8)
-MPC83XX_SPI_RX_BUF(u16)
-MPC83XX_SPI_RX_BUF(u32)
-MPC83XX_SPI_TX_BUF(u8)
-MPC83XX_SPI_TX_BUF(u16)
-MPC83XX_SPI_TX_BUF(u32)
-
-static void mpc8xxx_spi_change_mode(struct spi_device *spi)
+static void fsl_spi_change_mode(struct spi_device *spi)
 {
 	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
 	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-	__be32 __iomem *mode = &mspi->base->mode;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->mode;
 	unsigned long flags;
 
 	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
@@ -238,7 +136,7 @@ static void mpc8xxx_spi_change_mode(struct spi_device *spi)
 	local_irq_restore(flags);
 }
 
-static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
+static void fsl_spi_chipselect(struct spi_device *spi, int value)
 {
 	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
 	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
@@ -256,18 +154,17 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
 		mpc8xxx_spi->get_rx = cs->get_rx;
 		mpc8xxx_spi->get_tx = cs->get_tx;
 
-		mpc8xxx_spi_change_mode(spi);
+		fsl_spi_change_mode(spi);
 
 		if (pdata->cs_control)
 			pdata->cs_control(spi, pol);
 	}
 }
 
-static int
-mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			   struct spi_device *spi,
-			   struct mpc8xxx_spi *mpc8xxx_spi,
-			   int bits_per_word)
+static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				struct mpc8xxx_spi *mpc8xxx_spi,
+				int bits_per_word)
 {
 	cs->rx_shift = 0;
 	cs->tx_shift = 0;
@@ -307,10 +204,9 @@ mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
 	return bits_per_word;
 }
 
-static int
-mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			  struct spi_device *spi,
-			  int bits_per_word)
+static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+				struct spi_device *spi,
+				int bits_per_word)
 {
 	/* QE uses Little Endian for words > 8
 	 * so transform all words > 8 into 8 bits
@@ -326,13 +222,13 @@ mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
 	return bits_per_word;
 }
 
-static
-int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+static int fsl_spi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
 {
 	struct mpc8xxx_spi *mpc8xxx_spi;
-	int bits_per_word;
+	int bits_per_word = 0;
 	u8 pm;
-	u32 hz;
+	u32 hz = 0;
 	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
 
 	mpc8xxx_spi = spi_master_get_devdata(spi->master);
@@ -340,9 +236,6 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 	if (t) {
 		bits_per_word = t->bits_per_word;
 		hz = t->speed_hz;
-	} else {
-		bits_per_word = 0;
-		hz = 0;
 	}
 
 	/* spi_transfer level calls that work per-word */
@@ -388,23 +281,25 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
 			  hz, mpc8xxx_spi->spibrg / 1024);
 		if (pm > 16)
 			pm = 16;
-	} else
+	} else {
 		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
 	if (pm)
 		pm--;
 
 	cs->hw_mode |= SPMODE_PM(pm);
 
-	mpc8xxx_spi_change_mode(spi);
+	fsl_spi_change_mode(spi);
 	return 0;
 }
 
-static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
 {
 	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
 	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
 	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
 	unsigned int xfer_ofs;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
 
 	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
 
@@ -424,13 +319,14 @@ static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
 				 BD_SC_LAST);
 
 	/* start transfer */
-	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
+	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
 }
 
-static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
 				struct spi_transfer *t, bool is_dma_mapped)
 {
 	struct device *dev = mspi->dev;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
 
 	if (is_dma_mapped) {
 		mspi->map_tx_dma = 0;
@@ -475,13 +371,13 @@ static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
 	}
 
 	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
 
 	mspi->xfer_in_progress = t;
 	mspi->count = t->len;
 
 	/* start CPM transfers */
-	mpc8xxx_spi_cpm_bufs_start(mspi);
+	fsl_spi_cpm_bufs_start(mspi);
 
 	return 0;
 
@@ -491,7 +387,7 @@ err_rx_dma:
 	return -ENOMEM;
 }
 
-static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
 {
 	struct device *dev = mspi->dev;
 	struct spi_transfer *t = mspi->xfer_in_progress;
@@ -503,31 +399,34 @@ static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
 	mspi->xfer_in_progress = NULL;
 }
 
-static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
 				struct spi_transfer *t, unsigned int len)
 {
 	u32 word;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
 
 	mspi->count = len;
 
 	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
 
 	/* transmit word */
 	word = mspi->get_tx(mspi);
-	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
 
 	return 0;
 }
 
-static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
 			    bool is_dma_mapped)
 {
 	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_reg *reg_base;
 	unsigned int len = t->len;
 	u8 bits_per_word;
 	int ret;
 
+	reg_base = mpc8xxx_spi->reg_base;
 	bits_per_word = spi->bits_per_word;
 	if (t->bits_per_word)
 		bits_per_word = t->bits_per_word;
@@ -551,24 +450,24 @@ static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
 	INIT_COMPLETION(mpc8xxx_spi->done);
 
 	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
 	else
-		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
+		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
 	if (ret)
 		return ret;
 
 	wait_for_completion(&mpc8xxx_spi->done);
 
 	/* disable rx ints */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
 
 	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
+		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
 
 	return mpc8xxx_spi->count;
 }
 
-static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
+static void fsl_spi_do_one_msg(struct spi_message *m)
 {
 	struct spi_device *spi = m->spi;
 	struct spi_transfer *t;
@@ -584,18 +483,18 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
 			status = -EINVAL;
 
 			if (cs_change)
-				status = mpc8xxx_spi_setup_transfer(spi, t);
+				status = fsl_spi_setup_transfer(spi, t);
 			if (status < 0)
 				break;
 		}
 
 		if (cs_change) {
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
+			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
 			ndelay(nsecs);
 		}
 		cs_change = t->cs_change;
 		if (t->len)
-			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
+			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
 		if (status) {
 			status = -EMSGSIZE;
 			break;
@@ -607,7 +506,7 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
 
 		if (cs_change) {
 			ndelay(nsecs);
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
 			ndelay(nsecs);
 		}
 	}
@@ -617,35 +516,16 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
 
 	if (status || !cs_change) {
 		ndelay(nsecs);
-		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
 	}
 
-	mpc8xxx_spi_setup_transfer(spi, NULL);
-}
-
-static void mpc8xxx_spi_work(struct work_struct *work)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
-						       work);
-
-	spin_lock_irq(&mpc8xxx_spi->lock);
-	while (!list_empty(&mpc8xxx_spi->queue)) {
-		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
-						   struct spi_message, queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mpc8xxx_spi->lock);
-
-		mpc8xxx_spi_do_one_msg(m);
-
-		spin_lock_irq(&mpc8xxx_spi->lock);
-	}
-	spin_unlock_irq(&mpc8xxx_spi->lock);
+	fsl_spi_setup_transfer(spi, NULL);
 }
 
-static int mpc8xxx_spi_setup(struct spi_device *spi)
+static int fsl_spi_setup(struct spi_device *spi)
 {
 	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
 	int retval;
 	u32 hw_mode;
 	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
@@ -661,8 +541,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
 	}
 	mpc8xxx_spi = spi_master_get_devdata(spi->master);
 
+	reg_base = mpc8xxx_spi->reg_base;
+
 	hw_mode = cs->hw_mode; /* Save original settings */
-	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
+	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
 	/* mask out bits we are going to set */
 	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
 			 | SPMODE_REV | SPMODE_LOOP);
@@ -676,7 +558,7 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
 	if (spi->mode & SPI_LOOP)
 		cs->hw_mode |= SPMODE_LOOP;
 
-	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
+	retval = fsl_spi_setup_transfer(spi, NULL);
 	if (retval < 0) {
 		cs->hw_mode = hw_mode; /* Restore settings */
 		return retval;
@@ -684,9 +566,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
 	return 0;
 }
 
-static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
+static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
 	u16 len;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
 
 	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
 		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
@@ -698,20 +581,22 @@ static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 	}
 
 	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
 
 	mspi->count -= len;
 	if (mspi->count)
-		mpc8xxx_spi_cpm_bufs_start(mspi);
+		fsl_spi_cpm_bufs_start(mspi);
 	else
 		complete(&mspi->done);
 }
 
-static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
+
 	/* We need handle RX first */
 	if (events & SPIE_NE) {
-		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
+		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
 
 		if (mspi->rx)
 			mspi->get_rx(rx_data, mspi);
@@ -720,102 +605,80 @@ static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 	if ((events & SPIE_NF) == 0)
 		/* spin until TX is done */
 		while (((events =
-			mpc8xxx_spi_read_reg(&mspi->base->event)) &
+			mpc8xxx_spi_read_reg(&reg_base->event)) &
 						SPIE_NF) == 0)
 			cpu_relax();
 
 	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
 
 	mspi->count -= 1;
 	if (mspi->count) {
 		u32 word = mspi->get_tx(mspi);
 
-		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
 	} else {
 		complete(&mspi->done);
 	}
 }
 
-static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
+static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
 {
 	struct mpc8xxx_spi *mspi = context_data;
 	irqreturn_t ret = IRQ_NONE;
 	u32 events;
+	struct fsl_spi_reg *reg_base = mspi->reg_base;
 
 	/* Get interrupt events(tx/rx) */
-	events = mpc8xxx_spi_read_reg(&mspi->base->event);
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
 	if (events)
 		ret = IRQ_HANDLED;
 
 	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
 
 	if (mspi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_irq(mspi, events);
+		fsl_spi_cpm_irq(mspi, events);
 	else
-		mpc8xxx_spi_cpu_irq(mspi, events);
+		fsl_spi_cpu_irq(mspi, events);
 
 	return ret;
 }
 
-static int mpc8xxx_spi_transfer(struct spi_device *spi,
-				struct spi_message *m)
+static void *fsl_spi_alloc_dummy_rx(void)
 {
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned long flags;
+	mutex_lock(&fsl_dummy_rx_lock);
 
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
+	if (!fsl_dummy_rx)
+		fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+	if (fsl_dummy_rx)
+		fsl_dummy_rx_refcnt++;
 
-	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
-	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
-	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
-	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+	mutex_unlock(&fsl_dummy_rx_lock);
 
-	return 0;
+	return fsl_dummy_rx;
 }
 
-
-static void mpc8xxx_spi_cleanup(struct spi_device *spi)
+static void fsl_spi_free_dummy_rx(void)
 {
-	kfree(spi->controller_state);
-}
+	mutex_lock(&fsl_dummy_rx_lock);
 
-static void *mpc8xxx_spi_alloc_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	if (!mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
-	if (mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx_refcnt++;
-
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
-
-	return mpc8xxx_dummy_rx;
-}
-
-static void mpc8xxx_spi_free_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	switch (mpc8xxx_dummy_rx_refcnt) {
+	switch (fsl_dummy_rx_refcnt) {
 	case 0:
 		WARN_ON(1);
 		break;
 	case 1:
-		kfree(mpc8xxx_dummy_rx);
-		mpc8xxx_dummy_rx = NULL;
+		kfree(fsl_dummy_rx);
+		fsl_dummy_rx = NULL;
 		/* fall through */
 	default:
-		mpc8xxx_dummy_rx_refcnt--;
+		fsl_dummy_rx_refcnt--;
 		break;
 	}
 
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
+	mutex_unlock(&fsl_dummy_rx_lock);
 }
 
-static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 {
 	struct device *dev = mspi->dev;
 	struct device_node *np = dev->of_node;
@@ -869,7 +732,7 @@ static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
 	return pram_ofs;
 }
 
-static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
+static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
 {
 	struct device *dev = mspi->dev;
 	struct device_node *np = dev->of_node;
@@ -881,7 +744,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
 	if (!(mspi->flags & SPI_CPM_MODE))
 		return 0;
 
-	if (!mpc8xxx_spi_alloc_dummy_rx())
+	if (!fsl_spi_alloc_dummy_rx())
 		return -ENOMEM;
 
 	if (mspi->flags & SPI_QE) {
@@ -902,7 +765,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
 		}
 	}
 
-	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
+	pram_ofs = fsl_spi_cpm_get_pram(mspi);
 	if (IS_ERR_VALUE(pram_ofs)) {
 		dev_err(dev, "can't allocate spi parameter ram\n");
 		goto err_pram;
@@ -922,7 +785,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
 		goto err_dummy_tx;
 	}
 
-	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
+	mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
 					    DMA_FROM_DEVICE);
 	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
 		dev_err(dev, "unable to map dummy rx buffer\n");
@@ -960,11 +823,11 @@ err_dummy_tx:
 err_bds:
 	cpm_muram_free(pram_ofs);
 err_pram:
-	mpc8xxx_spi_free_dummy_rx();
+	fsl_spi_free_dummy_rx();
 	return -ENOMEM;
 }
 
-static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
+static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
 {
 	struct device *dev = mspi->dev;
 
@@ -972,30 +835,22 @@ static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
 	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
 	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
 	cpm_muram_free(cpm_muram_offset(mspi->pram));
-	mpc8xxx_spi_free_dummy_rx();
+	fsl_spi_free_dummy_rx();
 }
 
-static const char *mpc8xxx_spi_strmode(unsigned int flags)
+static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
 {
-	if (flags & SPI_QE_CPU_MODE) {
-		return "QE CPU";
-	} else if (flags & SPI_CPM_MODE) {
-		if (flags & SPI_QE)
-			return "QE";
-		else if (flags & SPI_CPM2)
-			return "CPM2";
-		else
-			return "CPM1";
-	}
-	return "CPU";
+	iounmap(mspi->reg_base);
+	fsl_spi_cpm_free(mspi);
 }
 
-static struct spi_master * __devinit
-mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
+static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
 {
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
 	struct spi_master *master;
 	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_spi_reg *reg_base;
 	u32 regval;
 	int ret = 0;
 
@@ -1007,132 +862,77 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
 
 	dev_set_drvdata(dev, master);
 
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
-			| SPI_LSB_FIRST | SPI_LOOP;
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
 
-	master->setup = mpc8xxx_spi_setup;
-	master->transfer = mpc8xxx_spi_transfer;
-	master->cleanup = mpc8xxx_spi_cleanup;
-	master->dev.of_node = dev->of_node;
+	master->setup = fsl_spi_setup;
 
 	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->dev = dev;
-	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
-	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
-	mpc8xxx_spi->flags = pdata->flags;
-	mpc8xxx_spi->spibrg = pdata->sysclk;
+	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_spi_remove;
+
 
-	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
+	ret = fsl_spi_cpm_init(mpc8xxx_spi);
 	if (ret)
 		goto err_cpm_init;
 
-	mpc8xxx_spi->rx_shift = 0;
-	mpc8xxx_spi->tx_shift = 0;
 	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
 		mpc8xxx_spi->rx_shift = 16;
 		mpc8xxx_spi->tx_shift = 24;
 	}
 
-	init_completion(&mpc8xxx_spi->done);
-
-	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
-	if (mpc8xxx_spi->base == NULL) {
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (mpc8xxx_spi->reg_base == NULL) {
 		ret = -ENOMEM;
 		goto err_ioremap;
 	}
 
-	mpc8xxx_spi->irq = irq;
-
 	/* Register for SPI Interrupt */
-	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
-			  0, "mpc8xxx_spi", mpc8xxx_spi);
+	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
+			  0, "fsl_spi", mpc8xxx_spi);
 
 	if (ret != 0)
-		goto unmap_io;
+		goto free_irq;
 
-	master->bus_num = pdata->bus_num;
-	master->num_chipselect = pdata->max_chipselect;
+	reg_base = mpc8xxx_spi->reg_base;
 
 	/* SPI controller initializations */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
 
 	/* Enable SPI interface */
 	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
 	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
 		regval |= SPMODE_OP;
 
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
-	spin_lock_init(&mpc8xxx_spi->lock);
-	init_completion(&mpc8xxx_spi->done);
-	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
-	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
-	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
-		dev_name(master->dev.parent));
-	if (mpc8xxx_spi->workqueue == NULL) {
-		ret = -EBUSY;
-		goto free_irq;
-	}
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
 
 	ret = spi_register_master(master);
 	if (ret < 0)
 		goto unreg_master;
 
-	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
+	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
 		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
 
 	return master;
 
 unreg_master:
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-free_irq:
 	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-unmap_io:
-	iounmap(mpc8xxx_spi->base);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
 err_ioremap:
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
+	fsl_spi_cpm_free(mpc8xxx_spi);
 err_cpm_init:
+err_probe:
 	spi_master_put(master);
 err:
 	return ERR_PTR(ret);
 }
 
-static int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct spi_master *master;
-
-	master = dev_get_drvdata(dev);
-	mpc8xxx_spi = spi_master_get_devdata(master);
-
-	flush_workqueue(mpc8xxx_spi->workqueue);
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-	spi_unregister_master(master);
-
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-	iounmap(mpc8xxx_spi->base);
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-
-	return 0;
-}
-
-struct mpc8xxx_spi_probe_info {
-	struct fsl_spi_platform_data pdata;
-	int *gpios;
-	bool *alow_flags;
-};
-
-static struct mpc8xxx_spi_probe_info *
-to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
-	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
+static void fsl_spi_cs_control(struct spi_device *spi, bool on)
 {
 	struct device *dev = spi->dev.parent;
 	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
@@ -1143,7 +943,7 @@ static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
 	gpio_set_value(gpio, on ^ alow);
 }
 
-static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
+static int of_fsl_spi_get_chipselects(struct device *dev)
 {
 	struct device_node *np = dev->of_node;
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
@@ -1204,7 +1004,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
 	}
 
 	pdata->max_chipselect = ngpios;
-	pdata->cs_control = mpc8xxx_spi_cs_control;
+	pdata->cs_control = fsl_spi_cs_control;
 
 	return 0;
 
@@ -1223,7 +1023,7 @@ err_alloc_flags:
 	return ret;
 }
 
-static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
+static int of_fsl_spi_free_chipselects(struct device *dev)
 {
 	struct fsl_spi_platform_data *pdata = dev->platform_data;
 	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
@@ -1242,50 +1042,21 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
 	return 0;
 }
 
-static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-					  const struct of_device_id *ofid)
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
-	struct mpc8xxx_spi_probe_info *pinfo;
-	struct fsl_spi_platform_data *pdata;
 	struct spi_master *master;
 	struct resource mem;
 	struct resource irq;
-	const void *prop;
 	int ret = -ENOMEM;
 
-	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-	if (!pinfo)
-		return -ENOMEM;
-
-	pdata = &pinfo->pdata;
-	dev->platform_data = pdata;
-
-	/* Allocate bus num dynamically. */
-	pdata->bus_num = -1;
-
-	/* SPI controller is either clocked from QE or SoC clock. */
-	pdata->sysclk = get_brgfreq();
-	if (pdata->sysclk == -1) {
-		pdata->sysclk = fsl_get_sys_freq();
-		if (pdata->sysclk == -1) {
-			ret = -ENODEV;
-			goto err_clk;
-		}
-	}
+	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	if (ret)
+		return ret;
 
-	prop = of_get_property(np, "mode", NULL);
-	if (prop && !strcmp(prop, "cpu-qe"))
-		pdata->flags = SPI_QE_CPU_MODE;
-	else if (prop && !strcmp(prop, "qe"))
-		pdata->flags = SPI_CPM_MODE | SPI_QE;
-	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
-	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
-	ret = of_mpc8xxx_spi_get_chipselects(dev);
+	ret = of_fsl_spi_get_chipselects(dev);
 	if (ret)
 		goto err;
 
@@ -1299,7 +1070,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
 		goto err;
 	}
 
-	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
+	master = fsl_spi_probe(dev, &mem, irq.start);
 	if (IS_ERR(master)) {
 		ret = PTR_ERR(master);
 		goto err;
@@ -1308,42 +1079,40 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
 	return 0;
 
 err:
-	of_mpc8xxx_spi_free_chipselects(dev);
-err_clk:
-	kfree(pinfo);
+	of_fsl_spi_free_chipselects(dev);
 	return ret;
 }
 
-static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
+static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
 {
 	int ret;
 
 	ret = mpc8xxx_spi_remove(&ofdev->dev);
 	if (ret)
 		return ret;
-	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
+	of_fsl_spi_free_chipselects(&ofdev->dev);
 	return 0;
 }
 
-static const struct of_device_id of_mpc8xxx_spi_match[] = {
+static const struct of_device_id of_fsl_spi_match[] = {
 	{ .compatible = "fsl,spi" },
-	{},
+	{}
 };
-MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
+MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
 
-static struct of_platform_driver of_mpc8xxx_spi_driver = {
+static struct of_platform_driver of_fsl_spi_driver = {
 	.driver = {
-		.name = "mpc8xxx_spi",
+		.name = "fsl_spi",
 		.owner = THIS_MODULE,
-		.of_match_table = of_mpc8xxx_spi_match,
+		.of_match_table = of_fsl_spi_match,
 	},
-	.probe		= of_mpc8xxx_spi_probe,
-	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
+	.probe		= of_fsl_spi_probe,
+	.remove		= __devexit_p(of_fsl_spi_remove),
 };
 
 #ifdef CONFIG_MPC832x_RDB
 /*
- * 				XXX XXX XXX
+ * XXX XXX XXX
  * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
  * only. The driver should go away soon, since newer MPC8323E-RDB's device
  * tree can work with OpenFirmware driver. But for now we support old trees
@@ -1366,7 +1135,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
 	if (irq <= 0)
 		return -EINVAL;
 
-	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
+	master = fsl_spi_probe(&pdev->dev, mem, irq);
 	if (IS_ERR(master))
 		return PTR_ERR(master);
 	return 0;
@@ -1405,21 +1174,20 @@ static void __init legacy_driver_register(void) {}
 static void __exit legacy_driver_unregister(void) {}
 #endif /* CONFIG_MPC832x_RDB */
 
-static int __init mpc8xxx_spi_init(void)
+static int __init fsl_spi_init(void)
 {
 	legacy_driver_register();
-	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
+	return of_register_platform_driver(&of_fsl_spi_driver);
 }
+module_init(fsl_spi_init);
 
-static void __exit mpc8xxx_spi_exit(void)
+static void __exit fsl_spi_exit(void)
 {
-	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
+	of_unregister_platform_driver(&of_fsl_spi_driver);
 	legacy_driver_unregister();
 }
-
-module_init(mpc8xxx_spi_init);
-module_exit(mpc8xxx_spi_exit);
+module_exit(fsl_spi_exit);
 
 MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
+MODULE_DESCRIPTION("Simple Freescale SPI Driver");
 MODULE_LICENSE("GPL");
-- 
1.6.4




From Mingkai.hu at freescale.com  Tue Oct 12 06:18:30 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:30 +0800
Subject: [PATCH v4 1/5] spi/mpc8xxx: rename spi_mpc8xxx.c to spi_fsl_spi.c
In-Reply-To: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>

This will pave the way to refactor out the common code which can be used
by the eSPI controller driver, and rename the SPI controller dirver to the
file spi_fsl_spi.c.

Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
---
v4:
 - Updated to latest kernel base(Linux 2.6.36-rc7).

 drivers/spi/Kconfig       |    9 +-
 drivers/spi/Makefile      |    2 +-
 drivers/spi/spi_fsl_spi.c | 1425 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/spi/spi_mpc8xxx.c | 1425 ---------------------------------------------
 4 files changed, 1431 insertions(+), 1430 deletions(-)
 create mode 100644 drivers/spi/spi_fsl_spi.c
 delete mode 100644 drivers/spi/spi_mpc8xxx.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 91c2f4f..6af34c6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -182,12 +182,13 @@ config SPI_MPC512x_PSC
 	  This enables using the Freescale MPC5121 Programmable Serial
 	  Controller in SPI master mode.
 
-config SPI_MPC8xxx
-	tristate "Freescale MPC8xxx SPI controller"
+config SPI_FSL_SPI
+	tristate "Freescale SPI controller"
 	depends on FSL_SOC
 	help
-	  This enables using the Freescale MPC8xxx SPI controllers in master
-	  mode.
+	  This enables using the Freescale SPI controllers in master mode.
+	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
+	  MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
 
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e9cbd18..770817c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,7 +34,7 @@ obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
-obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
+obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
new file mode 100644
index 0000000..1dd86b8
--- /dev/null
+++ b/drivers/spi/spi_fsl_spi.c
@@ -0,0 +1,1425 @@
+/*
+ * MPC8xxx SPI controller driver.
+ *
+ * Maintainer: Kumar Gala
+ *
+ * Copyright (C) 2006 Polycom, Inc.
+ *
+ * CPM SPI and QE buffer descriptors mode support:
+ * Copyright (c) 2009  MontaVista Software, Inc.
+ * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/slab.h>
+
+#include <sysdev/fsl_soc.h>
+#include <asm/cpm.h>
+#include <asm/qe.h>
+#include <asm/irq.h>
+
+/* CPM1 and CPM2 are mutually exclusive. */
+#ifdef CONFIG_CPM1
+#include <asm/cpm1.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
+#else
+#include <asm/cpm2.h>
+#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
+#endif
+
+/* SPI Controller registers */
+struct mpc8xxx_spi_reg {
+	u8 res1[0x20];
+	__be32 mode;
+	__be32 event;
+	__be32 mask;
+	__be32 command;
+	__be32 transmit;
+	__be32 receive;
+};
+
+/* SPI Controller mode register definitions */
+#define	SPMODE_LOOP		(1 << 30)
+#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
+#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
+#define	SPMODE_DIV16		(1 << 27)
+#define	SPMODE_REV		(1 << 26)
+#define	SPMODE_MS		(1 << 25)
+#define	SPMODE_ENABLE		(1 << 24)
+#define	SPMODE_LEN(x)		((x) << 20)
+#define	SPMODE_PM(x)		((x) << 16)
+#define	SPMODE_OP		(1 << 14)
+#define	SPMODE_CG(x)		((x) << 7)
+
+/*
+ * Default for SPI Mode:
+ * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
+ */
+#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
+			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+
+#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
+#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
+
+/* SPCOM register values */
+#define	SPCOM_STR	(1 << 23)	/* Start transmit */
+
+#define	SPI_PRAM_SIZE	0x100
+#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
+
+/* SPI Controller driver's private data. */
+struct mpc8xxx_spi {
+	struct device *dev;
+	struct mpc8xxx_spi_reg __iomem *base;
+
+	/* rx & tx bufs from the spi_transfer */
+	const void *tx;
+	void *rx;
+
+	int subblock;
+	struct spi_pram __iomem *pram;
+	struct cpm_buf_desc __iomem *tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd;
+
+	struct spi_transfer *xfer_in_progress;
+
+	/* dma addresses for CPM transfers */
+	dma_addr_t tx_dma;
+	dma_addr_t rx_dma;
+	bool map_tx_dma;
+	bool map_rx_dma;
+
+	dma_addr_t dma_dummy_tx;
+	dma_addr_t dma_dummy_rx;
+
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32(*get_tx) (struct mpc8xxx_spi *);
+
+	unsigned int count;
+	unsigned int irq;
+
+	unsigned nsecs;		/* (clock cycle time)/2 */
+
+	u32 spibrg;		/* SPIBRG input clock */
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+
+	unsigned int flags;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+static void *mpc8xxx_dummy_rx;
+static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
+static int mpc8xxx_dummy_rx_refcnt;
+
+struct spi_mpc8xxx_cs {
+	/* functions to deal with different sized buffers */
+	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
+	u32 (*get_tx) (struct mpc8xxx_spi *);
+	u32 rx_shift;		/* RX data reg shift when in qe mode */
+	u32 tx_shift;		/* TX data reg shift when in qe mode */
+	u32 hw_mode;		/* Holds HW mode register settings */
+};
+
+static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
+{
+	out_be32(reg, val);
+}
+
+static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
+{
+	return in_be32(reg);
+}
+
+#define MPC83XX_SPI_RX_BUF(type) 					  \
+static									  \
+void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
+{									  \
+	type *rx = mpc8xxx_spi->rx;					  \
+	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
+	mpc8xxx_spi->rx = rx;						  \
+}
+
+#define MPC83XX_SPI_TX_BUF(type)				\
+static								\
+u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
+{								\
+	u32 data;						\
+	const type *tx = mpc8xxx_spi->tx;			\
+	if (!tx)						\
+		return 0;					\
+	data = *tx++ << mpc8xxx_spi->tx_shift;			\
+	mpc8xxx_spi->tx = tx;					\
+	return data;						\
+}
+
+MPC83XX_SPI_RX_BUF(u8)
+MPC83XX_SPI_RX_BUF(u16)
+MPC83XX_SPI_RX_BUF(u32)
+MPC83XX_SPI_TX_BUF(u8)
+MPC83XX_SPI_TX_BUF(u16)
+MPC83XX_SPI_TX_BUF(u32)
+
+static void mpc8xxx_spi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	__be32 __iomem *mode = &mspi->base->mode;
+	unsigned long flags;
+
+	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
+		return;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
+
+	/* When in CPM mode, we need to reinit tx and rx. */
+	if (mspi->flags & SPI_CPM_MODE) {
+		if (mspi->flags & SPI_QE) {
+			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
+				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
+		} else {
+			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
+			if (mspi->flags & SPI_CPM1) {
+				out_be16(&mspi->pram->rbptr,
+					 in_be16(&mspi->pram->rbase));
+				out_be16(&mspi->pram->tbptr,
+					 in_be16(&mspi->pram->tbase));
+			}
+		}
+	}
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	local_irq_restore(flags);
+}
+
+static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+	bool pol = spi->mode & SPI_CS_HIGH;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (value == BITBANG_CS_INACTIVE) {
+		if (pdata->cs_control)
+			pdata->cs_control(spi, !pol);
+	}
+
+	if (value == BITBANG_CS_ACTIVE) {
+		mpc8xxx_spi->rx_shift = cs->rx_shift;
+		mpc8xxx_spi->tx_shift = cs->tx_shift;
+		mpc8xxx_spi->get_rx = cs->get_rx;
+		mpc8xxx_spi->get_tx = cs->get_tx;
+
+		mpc8xxx_spi_change_mode(spi);
+
+		if (pdata->cs_control)
+			pdata->cs_control(spi, pol);
+	}
+}
+
+static int
+mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
+			   struct spi_device *spi,
+			   struct mpc8xxx_spi *mpc8xxx_spi,
+			   int bits_per_word)
+{
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	if (bits_per_word <= 8) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 24;
+		}
+	} else if (bits_per_word <= 16) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
+		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+			cs->rx_shift = 16;
+			cs->tx_shift = 16;
+		}
+	} else if (bits_per_word <= 32) {
+		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	} else
+		return -EINVAL;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
+	    spi->mode & SPI_LSB_FIRST) {
+		cs->tx_shift = 0;
+		if (bits_per_word <= 8)
+			cs->rx_shift = 8;
+		else
+			cs->rx_shift = 0;
+	}
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	return bits_per_word;
+}
+
+static int
+mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+			  struct spi_device *spi,
+			  int bits_per_word)
+{
+	/* QE uses Little Endian for words > 8
+	 * so transform all words > 8 into 8 bits
+	 * Unfortnatly that doesn't work for LSB so
+	 * reject these for now */
+	/* Note: 32 bits word, LSB works iff
+	 * tfcr/rfcr is set to CPMFCR_GBL */
+	if (spi->mode & SPI_LSB_FIRST &&
+	    bits_per_word > 8)
+		return -EINVAL;
+	if (bits_per_word > 8)
+		return 8; /* pretend its 8 bits */
+	return bits_per_word;
+}
+
+static
+int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int bits_per_word;
+	u8 pm;
+	u32 hz;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	} else {
+		bits_per_word = 0;
+		hz = 0;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16, 32] */
+	if ((bits_per_word < 4)
+	    || ((bits_per_word > 16) && (bits_per_word != 32)))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
+		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
+							   mpc8xxx_spi,
+							   bits_per_word);
+	else if (mpc8xxx_spi->flags & SPI_QE)
+		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
+							  bits_per_word);
+
+	if (bits_per_word < 0)
+		return bits_per_word;
+
+	if (bits_per_word == 32)
+		bits_per_word = 0;
+	else
+		bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
+				  | SPMODE_PM(0xF));
+
+	cs->hw_mode |= SPMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= SPMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= SPMODE_PM(pm);
+
+	mpc8xxx_spi_change_mode(spi);
+	return 0;
+}
+
+static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
+{
+	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
+	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
+	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
+	unsigned int xfer_ofs;
+
+	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
+
+	if (mspi->rx_dma == mspi->dma_dummy_rx)
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
+	else
+		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
+	out_be16(&rx_bd->cbd_datlen, 0);
+	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
+
+	if (mspi->tx_dma == mspi->dma_dummy_tx)
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
+	else
+		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
+	out_be16(&tx_bd->cbd_datlen, xfer_len);
+	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
+				 BD_SC_LAST);
+
+	/* start transfer */
+	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
+}
+
+static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, bool is_dma_mapped)
+{
+	struct device *dev = mspi->dev;
+
+	if (is_dma_mapped) {
+		mspi->map_tx_dma = 0;
+		mspi->map_rx_dma = 0;
+	} else {
+		mspi->map_tx_dma = 1;
+		mspi->map_rx_dma = 1;
+	}
+
+	if (!t->tx_buf) {
+		mspi->tx_dma = mspi->dma_dummy_tx;
+		mspi->map_tx_dma = 0;
+	}
+
+	if (!t->rx_buf) {
+		mspi->rx_dma = mspi->dma_dummy_rx;
+		mspi->map_rx_dma = 0;
+	}
+
+	if (mspi->map_tx_dma) {
+		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
+
+		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
+					      DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, mspi->tx_dma)) {
+			dev_err(dev, "unable to map tx dma\n");
+			return -ENOMEM;
+		}
+	} else if (t->tx_buf) {
+		mspi->tx_dma = t->tx_dma;
+	}
+
+	if (mspi->map_rx_dma) {
+		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
+					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(dev, mspi->rx_dma)) {
+			dev_err(dev, "unable to map rx dma\n");
+			goto err_rx_dma;
+		}
+	} else if (t->rx_buf) {
+		mspi->rx_dma = t->rx_dma;
+	}
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
+
+	mspi->xfer_in_progress = t;
+	mspi->count = t->len;
+
+	/* start CPM transfers */
+	mpc8xxx_spi_cpm_bufs_start(mspi);
+
+	return 0;
+
+err_rx_dma:
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	return -ENOMEM;
+}
+
+static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct spi_transfer *t = mspi->xfer_in_progress;
+
+	if (mspi->map_tx_dma)
+		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
+	if (mspi->map_rx_dma)
+		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
+	mspi->xfer_in_progress = NULL;
+}
+
+static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
+				struct spi_transfer *t, unsigned int len)
+{
+	u32 word;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+
+	return 0;
+}
+
+static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
+			    bool is_dma_mapped)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	if (bits_per_word > 8) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+	if (bits_per_word > 16) {
+		/* invalid length? */
+		if (len & 1)
+			return -EINVAL;
+		len /= 2;
+	}
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
+	else
+		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
+
+	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
+		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
+
+	return mpc8xxx_spi->count;
+}
+
+static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
+{
+	struct spi_device *spi = m->spi;
+	struct spi_transfer *t;
+	unsigned int cs_change;
+	const int nsecs = 50;
+	int status;
+
+	cs_change = 1;
+	status = 0;
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			/* Don't allow changes if CS is active */
+			status = -EINVAL;
+
+			if (cs_change)
+				status = mpc8xxx_spi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (cs_change) {
+			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
+			ndelay(nsecs);
+		}
+		cs_change = t->cs_change;
+		if (t->len)
+			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+		m->actual_length += t->len;
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+
+		if (cs_change) {
+			ndelay(nsecs);
+			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+			ndelay(nsecs);
+		}
+	}
+
+	m->status = status;
+	m->complete(m->context);
+
+	if (status || !cs_change) {
+		ndelay(nsecs);
+		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
+	}
+
+	mpc8xxx_spi_setup_transfer(spi, NULL);
+}
+
+static void mpc8xxx_spi_work(struct work_struct *work)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
+						       work);
+
+	spin_lock_irq(&mpc8xxx_spi->lock);
+	while (!list_empty(&mpc8xxx_spi->queue)) {
+		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
+						   struct spi_message, queue);
+
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mpc8xxx_spi->lock);
+
+		mpc8xxx_spi_do_one_msg(m);
+
+		spin_lock_irq(&mpc8xxx_spi->lock);
+	}
+	spin_unlock_irq(&mpc8xxx_spi->lock);
+}
+
+static int mpc8xxx_spi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	int retval;
+	u32 hw_mode;
+	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+
+	hw_mode = cs->hw_mode; /* Save original settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
+			 | SPMODE_REV | SPMODE_LOOP);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= SPMODE_REV;
+	if (spi->mode & SPI_LOOP)
+		cs->hw_mode |= SPMODE_LOOP;
+
+	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	u16 len;
+
+	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
+		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
+
+	len = in_be16(&mspi->rx_bd->cbd_datlen);
+	if (len > mspi->count) {
+		WARN_ON(1);
+		len = mspi->count;
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&mspi->base->event, events);
+
+	mspi->count -= len;
+	if (mspi->count)
+		mpc8xxx_spi_cpm_bufs_start(mspi);
+	else
+		complete(&mspi->done);
+}
+
+static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if ((events & SPIE_NF) == 0)
+		/* spin until TX is done */
+		while (((events =
+			mpc8xxx_spi_read_reg(&mspi->base->event)) &
+						SPIE_NF) == 0)
+			cpu_relax();
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&mspi->base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&mspi->base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	if (mspi->flags & SPI_CPM_MODE)
+		mpc8xxx_spi_cpm_irq(mspi, events);
+	else
+		mpc8xxx_spi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static int mpc8xxx_spi_transfer(struct spi_device *spi,
+				struct spi_message *m)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
+	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
+	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
+	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
+
+	return 0;
+}
+
+
+static void mpc8xxx_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static void *mpc8xxx_spi_alloc_dummy_rx(void)
+{
+	mutex_lock(&mpc8xxx_dummy_rx_lock);
+
+	if (!mpc8xxx_dummy_rx)
+		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
+	if (mpc8xxx_dummy_rx)
+		mpc8xxx_dummy_rx_refcnt++;
+
+	mutex_unlock(&mpc8xxx_dummy_rx_lock);
+
+	return mpc8xxx_dummy_rx;
+}
+
+static void mpc8xxx_spi_free_dummy_rx(void)
+{
+	mutex_lock(&mpc8xxx_dummy_rx_lock);
+
+	switch (mpc8xxx_dummy_rx_refcnt) {
+	case 0:
+		WARN_ON(1);
+		break;
+	case 1:
+		kfree(mpc8xxx_dummy_rx);
+		mpc8xxx_dummy_rx = NULL;
+		/* fall through */
+	default:
+		mpc8xxx_dummy_rx_refcnt--;
+		break;
+	}
+
+	mutex_unlock(&mpc8xxx_dummy_rx_lock);
+}
+
+static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	unsigned long spi_base_ofs;
+	unsigned long pram_ofs = -ENOMEM;
+
+	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
+	iprop = of_get_property(np, "reg", &size);
+
+	/* QE with a fixed pram location? */
+	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
+		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
+
+	/* QE but with a dynamic pram location? */
+	if (mspi->flags & SPI_QE) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
+				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
+		return pram_ofs;
+	}
+
+	/* CPM1 and CPM2 pram must be at a fixed addr. */
+	if (!iprop || size != sizeof(*iprop) * 4)
+		return -ENOMEM;
+
+	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
+	if (IS_ERR_VALUE(spi_base_ofs))
+		return -ENOMEM;
+
+	if (mspi->flags & SPI_CPM2) {
+		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
+		if (!IS_ERR_VALUE(pram_ofs)) {
+			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
+
+			out_be16(spi_base, pram_ofs);
+		}
+	} else {
+		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
+		u16 rpbase = in_be16(&pram->rpbase);
+
+		/* Microcode relocation patch applied? */
+		if (rpbase)
+			pram_ofs = rpbase;
+		else
+			return spi_base_ofs;
+	}
+
+	cpm_muram_free(spi_base_ofs);
+	return pram_ofs;
+}
+
+static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+	struct device_node *np = dev->of_node;
+	const u32 *iprop;
+	int size;
+	unsigned long pram_ofs;
+	unsigned long bds_ofs;
+
+	if (!(mspi->flags & SPI_CPM_MODE))
+		return 0;
+
+	if (!mpc8xxx_spi_alloc_dummy_rx())
+		return -ENOMEM;
+
+	if (mspi->flags & SPI_QE) {
+		iprop = of_get_property(np, "cell-index", &size);
+		if (iprop && size == sizeof(*iprop))
+			mspi->subblock = *iprop;
+
+		switch (mspi->subblock) {
+		default:
+			dev_warn(dev, "cell-index unspecified, assuming SPI1");
+			/* fall through */
+		case 0:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
+			break;
+		case 1:
+			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
+			break;
+		}
+	}
+
+	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
+	if (IS_ERR_VALUE(pram_ofs)) {
+		dev_err(dev, "can't allocate spi parameter ram\n");
+		goto err_pram;
+	}
+
+	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
+				  sizeof(*mspi->rx_bd), 8);
+	if (IS_ERR_VALUE(bds_ofs)) {
+		dev_err(dev, "can't allocate bds\n");
+		goto err_bds;
+	}
+
+	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
+					    DMA_TO_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
+		dev_err(dev, "unable to map dummy tx buffer\n");
+		goto err_dummy_tx;
+	}
+
+	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
+					    DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
+		dev_err(dev, "unable to map dummy rx buffer\n");
+		goto err_dummy_rx;
+	}
+
+	mspi->pram = cpm_muram_addr(pram_ofs);
+
+	mspi->tx_bd = cpm_muram_addr(bds_ofs);
+	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
+
+	/* Initialize parameter ram. */
+	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
+	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
+	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
+	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
+	out_be32(&mspi->pram->rstate, 0);
+	out_be32(&mspi->pram->rdp, 0);
+	out_be16(&mspi->pram->rbptr, 0);
+	out_be16(&mspi->pram->rbc, 0);
+	out_be32(&mspi->pram->rxtmp, 0);
+	out_be32(&mspi->pram->tstate, 0);
+	out_be32(&mspi->pram->tdp, 0);
+	out_be16(&mspi->pram->tbptr, 0);
+	out_be16(&mspi->pram->tbc, 0);
+	out_be32(&mspi->pram->txtmp, 0);
+
+	return 0;
+
+err_dummy_rx:
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+err_dummy_tx:
+	cpm_muram_free(bds_ofs);
+err_bds:
+	cpm_muram_free(pram_ofs);
+err_pram:
+	mpc8xxx_spi_free_dummy_rx();
+	return -ENOMEM;
+}
+
+static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
+{
+	struct device *dev = mspi->dev;
+
+	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
+	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
+	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
+	cpm_muram_free(cpm_muram_offset(mspi->pram));
+	mpc8xxx_spi_free_dummy_rx();
+}
+
+static const char *mpc8xxx_spi_strmode(unsigned int flags)
+{
+	if (flags & SPI_QE_CPU_MODE) {
+		return "QE CPU";
+	} else if (flags & SPI_CPM_MODE) {
+		if (flags & SPI_QE)
+			return "QE";
+		else if (flags & SPI_CPM2)
+			return "CPM2";
+		else
+			return "CPM1";
+	}
+	return "CPU";
+}
+
+static struct spi_master * __devinit
+mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	u32 regval;
+	int ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (master == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	/* the spi->mode bits understood by this driver: */
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
+			| SPI_LSB_FIRST | SPI_LOOP;
+
+	master->setup = mpc8xxx_spi_setup;
+	master->transfer = mpc8xxx_spi_transfer;
+	master->cleanup = mpc8xxx_spi_cleanup;
+	master->dev.of_node = dev->of_node;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->dev = dev;
+	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
+	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
+	mpc8xxx_spi->flags = pdata->flags;
+	mpc8xxx_spi->spibrg = pdata->sysclk;
+
+	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
+	if (ret)
+		goto err_cpm_init;
+
+	mpc8xxx_spi->rx_shift = 0;
+	mpc8xxx_spi->tx_shift = 0;
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	init_completion(&mpc8xxx_spi->done);
+
+	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
+	if (mpc8xxx_spi->base == NULL) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	mpc8xxx_spi->irq = irq;
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
+			  0, "mpc8xxx_spi", mpc8xxx_spi);
+
+	if (ret != 0)
+		goto unmap_io;
+
+	master->bus_num = pdata->bus_num;
+	master->num_chipselect = pdata->max_chipselect;
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
+		regval |= SPMODE_OP;
+
+	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
+	spin_lock_init(&mpc8xxx_spi->lock);
+	init_completion(&mpc8xxx_spi->done);
+	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
+	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
+
+	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
+		dev_name(master->dev.parent));
+	if (mpc8xxx_spi->workqueue == NULL) {
+		ret = -EBUSY;
+		goto free_irq;
+	}
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
+		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
+
+	return master;
+
+unreg_master:
+	destroy_workqueue(mpc8xxx_spi->workqueue);
+free_irq:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+unmap_io:
+	iounmap(mpc8xxx_spi->base);
+err_ioremap:
+	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
+err_cpm_init:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static int __devexit mpc8xxx_spi_remove(struct device *dev)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct spi_master *master;
+
+	master = dev_get_drvdata(dev);
+	mpc8xxx_spi = spi_master_get_devdata(master);
+
+	flush_workqueue(mpc8xxx_spi->workqueue);
+	destroy_workqueue(mpc8xxx_spi->workqueue);
+	spi_unregister_master(master);
+
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+	iounmap(mpc8xxx_spi->base);
+	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
+
+	return 0;
+}
+
+struct mpc8xxx_spi_probe_info {
+	struct fsl_spi_platform_data pdata;
+	int *gpios;
+	bool *alow_flags;
+};
+
+static struct mpc8xxx_spi_probe_info *
+to_of_pinfo(struct fsl_spi_platform_data *pdata)
+{
+	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
+}
+
+static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
+{
+	struct device *dev = spi->dev.parent;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
+	u16 cs = spi->chip_select;
+	int gpio = pinfo->gpios[cs];
+	bool alow = pinfo->alow_flags[cs];
+
+	gpio_set_value(gpio, on ^ alow);
+}
+
+static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	unsigned int ngpios;
+	int i = 0;
+	int ret;
+
+	ngpios = of_gpio_count(np);
+	if (!ngpios) {
+		/*
+		 * SPI w/o chip-select line. One SPI device is still permitted
+		 * though.
+		 */
+		pdata->max_chipselect = 1;
+		return 0;
+	}
+
+	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
+	if (!pinfo->gpios)
+		return -ENOMEM;
+	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
+
+	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
+				    GFP_KERNEL);
+	if (!pinfo->alow_flags) {
+		ret = -ENOMEM;
+		goto err_alloc_flags;
+	}
+
+	for (; i < ngpios; i++) {
+		int gpio;
+		enum of_gpio_flags flags;
+
+		gpio = of_get_gpio_flags(np, i, &flags);
+		if (!gpio_is_valid(gpio)) {
+			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
+			ret = gpio;
+			goto err_loop;
+		}
+
+		ret = gpio_request(gpio, dev_name(dev));
+		if (ret) {
+			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
+			goto err_loop;
+		}
+
+		pinfo->gpios[i] = gpio;
+		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
+
+		ret = gpio_direction_output(pinfo->gpios[i],
+					    pinfo->alow_flags[i]);
+		if (ret) {
+			dev_err(dev, "can't set output direction for gpio "
+				"#%d: %d\n", i, ret);
+			goto err_loop;
+		}
+	}
+
+	pdata->max_chipselect = ngpios;
+	pdata->cs_control = mpc8xxx_spi_cs_control;
+
+	return 0;
+
+err_loop:
+	while (i >= 0) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+		i--;
+	}
+
+	kfree(pinfo->alow_flags);
+	pinfo->alow_flags = NULL;
+err_alloc_flags:
+	kfree(pinfo->gpios);
+	pinfo->gpios = NULL;
+	return ret;
+}
+
+static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
+	int i;
+
+	if (!pinfo->gpios)
+		return 0;
+
+	for (i = 0; i < pdata->max_chipselect; i++) {
+		if (gpio_is_valid(pinfo->gpios[i]))
+			gpio_free(pinfo->gpios[i]);
+	}
+
+	kfree(pinfo->gpios);
+	kfree(pinfo->alow_flags);
+	return 0;
+}
+
+static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
+					  const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct mpc8xxx_spi_probe_info *pinfo;
+	struct fsl_spi_platform_data *pdata;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	const void *prop;
+	int ret = -ENOMEM;
+
+	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
+	if (!pinfo)
+		return -ENOMEM;
+
+	pdata = &pinfo->pdata;
+	dev->platform_data = pdata;
+
+	/* Allocate bus num dynamically. */
+	pdata->bus_num = -1;
+
+	/* SPI controller is either clocked from QE or SoC clock. */
+	pdata->sysclk = get_brgfreq();
+	if (pdata->sysclk == -1) {
+		pdata->sysclk = fsl_get_sys_freq();
+		if (pdata->sysclk == -1) {
+			ret = -ENODEV;
+			goto err_clk;
+		}
+	}
+
+	prop = of_get_property(np, "mode", NULL);
+	if (prop && !strcmp(prop, "cpu-qe"))
+		pdata->flags = SPI_QE_CPU_MODE;
+	else if (prop && !strcmp(prop, "qe"))
+		pdata->flags = SPI_CPM_MODE | SPI_QE;
+	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
+	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
+		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
+
+	ret = of_mpc8xxx_spi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	of_mpc8xxx_spi_free_chipselects(dev);
+err_clk:
+	kfree(pinfo);
+	return ret;
+}
+
+static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
+{
+	int ret;
+
+	ret = mpc8xxx_spi_remove(&ofdev->dev);
+	if (ret)
+		return ret;
+	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
+	return 0;
+}
+
+static const struct of_device_id of_mpc8xxx_spi_match[] = {
+	{ .compatible = "fsl,spi" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
+
+static struct of_platform_driver of_mpc8xxx_spi_driver = {
+	.driver = {
+		.name = "mpc8xxx_spi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_mpc8xxx_spi_match,
+	},
+	.probe		= of_mpc8xxx_spi_probe,
+	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
+};
+
+#ifdef CONFIG_MPC832x_RDB
+/*
+ * 				XXX XXX XXX
+ * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
+ * only. The driver should go away soon, since newer MPC8323E-RDB's device
+ * tree can work with OpenFirmware driver. But for now we support old trees
+ * as well.
+ */
+static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
+{
+	struct resource *mem;
+	int irq;
+	struct spi_master *master;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return -EINVAL;
+
+	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
+	if (IS_ERR(master))
+		return PTR_ERR(master);
+	return 0;
+}
+
+static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
+{
+	return mpc8xxx_spi_remove(&pdev->dev);
+}
+
+MODULE_ALIAS("platform:mpc8xxx_spi");
+static struct platform_driver mpc8xxx_spi_driver = {
+	.probe = plat_mpc8xxx_spi_probe,
+	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
+	.driver = {
+		.name = "mpc8xxx_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static bool legacy_driver_failed;
+
+static void __init legacy_driver_register(void)
+{
+	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
+}
+
+static void __exit legacy_driver_unregister(void)
+{
+	if (legacy_driver_failed)
+		return;
+	platform_driver_unregister(&mpc8xxx_spi_driver);
+}
+#else
+static void __init legacy_driver_register(void) {}
+static void __exit legacy_driver_unregister(void) {}
+#endif /* CONFIG_MPC832x_RDB */
+
+static int __init mpc8xxx_spi_init(void)
+{
+	legacy_driver_register();
+	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
+}
+
+static void __exit mpc8xxx_spi_exit(void)
+{
+	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
+	legacy_driver_unregister();
+}
+
+module_init(mpc8xxx_spi_init);
+module_exit(mpc8xxx_spi_exit);
+
+MODULE_AUTHOR("Kumar Gala");
+MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
deleted file mode 100644
index 1dd86b8..0000000
--- a/drivers/spi/spi_mpc8xxx.c
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*
- * MPC8xxx SPI controller driver.
- *
- * Maintainer: Kumar Gala
- *
- * Copyright (C) 2006 Polycom, Inc.
- *
- * CPM SPI and QE buffer descriptors mode support:
- * Copyright (c) 2009  MontaVista Software, Inc.
- * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/bug.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_bitbang.h>
-#include <linux/platform_device.h>
-#include <linux/fsl_devices.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/slab.h>
-
-#include <sysdev/fsl_soc.h>
-#include <asm/cpm.h>
-#include <asm/qe.h>
-#include <asm/irq.h>
-
-/* CPM1 and CPM2 are mutually exclusive. */
-#ifdef CONFIG_CPM1
-#include <asm/cpm1.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
-#else
-#include <asm/cpm2.h>
-#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
-#endif
-
-/* SPI Controller registers */
-struct mpc8xxx_spi_reg {
-	u8 res1[0x20];
-	__be32 mode;
-	__be32 event;
-	__be32 mask;
-	__be32 command;
-	__be32 transmit;
-	__be32 receive;
-};
-
-/* SPI Controller mode register definitions */
-#define	SPMODE_LOOP		(1 << 30)
-#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
-#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
-#define	SPMODE_DIV16		(1 << 27)
-#define	SPMODE_REV		(1 << 26)
-#define	SPMODE_MS		(1 << 25)
-#define	SPMODE_ENABLE		(1 << 24)
-#define	SPMODE_LEN(x)		((x) << 20)
-#define	SPMODE_PM(x)		((x) << 16)
-#define	SPMODE_OP		(1 << 14)
-#define	SPMODE_CG(x)		((x) << 7)
-
-/*
- * Default for SPI Mode:
- * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
- */
-#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
-			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
-
-/* SPIE register values */
-#define	SPIE_NE		0x00000200	/* Not empty */
-#define	SPIE_NF		0x00000100	/* Not full */
-
-/* SPIM register values */
-#define	SPIM_NE		0x00000200	/* Not empty */
-#define	SPIM_NF		0x00000100	/* Not full */
-
-#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
-#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
-
-/* SPCOM register values */
-#define	SPCOM_STR	(1 << 23)	/* Start transmit */
-
-#define	SPI_PRAM_SIZE	0x100
-#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
-
-/* SPI Controller driver's private data. */
-struct mpc8xxx_spi {
-	struct device *dev;
-	struct mpc8xxx_spi_reg __iomem *base;
-
-	/* rx & tx bufs from the spi_transfer */
-	const void *tx;
-	void *rx;
-
-	int subblock;
-	struct spi_pram __iomem *pram;
-	struct cpm_buf_desc __iomem *tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd;
-
-	struct spi_transfer *xfer_in_progress;
-
-	/* dma addresses for CPM transfers */
-	dma_addr_t tx_dma;
-	dma_addr_t rx_dma;
-	bool map_tx_dma;
-	bool map_rx_dma;
-
-	dma_addr_t dma_dummy_tx;
-	dma_addr_t dma_dummy_rx;
-
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32(*get_tx) (struct mpc8xxx_spi *);
-
-	unsigned int count;
-	unsigned int irq;
-
-	unsigned nsecs;		/* (clock cycle time)/2 */
-
-	u32 spibrg;		/* SPIBRG input clock */
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-
-	unsigned int flags;
-
-	struct workqueue_struct *workqueue;
-	struct work_struct work;
-
-	struct list_head queue;
-	spinlock_t lock;
-
-	struct completion done;
-};
-
-static void *mpc8xxx_dummy_rx;
-static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
-static int mpc8xxx_dummy_rx_refcnt;
-
-struct spi_mpc8xxx_cs {
-	/* functions to deal with different sized buffers */
-	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
-	u32 (*get_tx) (struct mpc8xxx_spi *);
-	u32 rx_shift;		/* RX data reg shift when in qe mode */
-	u32 tx_shift;		/* TX data reg shift when in qe mode */
-	u32 hw_mode;		/* Holds HW mode register settings */
-};
-
-static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
-{
-	out_be32(reg, val);
-}
-
-static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
-{
-	return in_be32(reg);
-}
-
-#define MPC83XX_SPI_RX_BUF(type) 					  \
-static									  \
-void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
-{									  \
-	type *rx = mpc8xxx_spi->rx;					  \
-	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
-	mpc8xxx_spi->rx = rx;						  \
-}
-
-#define MPC83XX_SPI_TX_BUF(type)				\
-static								\
-u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
-{								\
-	u32 data;						\
-	const type *tx = mpc8xxx_spi->tx;			\
-	if (!tx)						\
-		return 0;					\
-	data = *tx++ << mpc8xxx_spi->tx_shift;			\
-	mpc8xxx_spi->tx = tx;					\
-	return data;						\
-}
-
-MPC83XX_SPI_RX_BUF(u8)
-MPC83XX_SPI_RX_BUF(u16)
-MPC83XX_SPI_RX_BUF(u32)
-MPC83XX_SPI_TX_BUF(u8)
-MPC83XX_SPI_TX_BUF(u16)
-MPC83XX_SPI_TX_BUF(u32)
-
-static void mpc8xxx_spi_change_mode(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
-	struct spi_mpc8xxx_cs *cs = spi->controller_state;
-	__be32 __iomem *mode = &mspi->base->mode;
-	unsigned long flags;
-
-	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
-		return;
-
-	/* Turn off IRQs locally to minimize time that SPI is disabled. */
-	local_irq_save(flags);
-
-	/* Turn off SPI unit prior changing mode */
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
-
-	/* When in CPM mode, we need to reinit tx and rx. */
-	if (mspi->flags & SPI_CPM_MODE) {
-		if (mspi->flags & SPI_QE) {
-			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
-				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
-		} else {
-			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
-			if (mspi->flags & SPI_CPM1) {
-				out_be16(&mspi->pram->rbptr,
-					 in_be16(&mspi->pram->rbase));
-				out_be16(&mspi->pram->tbptr,
-					 in_be16(&mspi->pram->tbase));
-			}
-		}
-	}
-	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
-	local_irq_restore(flags);
-}
-
-static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
-	bool pol = spi->mode & SPI_CS_HIGH;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (value == BITBANG_CS_INACTIVE) {
-		if (pdata->cs_control)
-			pdata->cs_control(spi, !pol);
-	}
-
-	if (value == BITBANG_CS_ACTIVE) {
-		mpc8xxx_spi->rx_shift = cs->rx_shift;
-		mpc8xxx_spi->tx_shift = cs->tx_shift;
-		mpc8xxx_spi->get_rx = cs->get_rx;
-		mpc8xxx_spi->get_tx = cs->get_tx;
-
-		mpc8xxx_spi_change_mode(spi);
-
-		if (pdata->cs_control)
-			pdata->cs_control(spi, pol);
-	}
-}
-
-static int
-mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			   struct spi_device *spi,
-			   struct mpc8xxx_spi *mpc8xxx_spi,
-			   int bits_per_word)
-{
-	cs->rx_shift = 0;
-	cs->tx_shift = 0;
-	if (bits_per_word <= 8) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 24;
-		}
-	} else if (bits_per_word <= 16) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
-		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-			cs->rx_shift = 16;
-			cs->tx_shift = 16;
-		}
-	} else if (bits_per_word <= 32) {
-		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
-		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
-	} else
-		return -EINVAL;
-
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
-	    spi->mode & SPI_LSB_FIRST) {
-		cs->tx_shift = 0;
-		if (bits_per_word <= 8)
-			cs->rx_shift = 8;
-		else
-			cs->rx_shift = 0;
-	}
-	mpc8xxx_spi->rx_shift = cs->rx_shift;
-	mpc8xxx_spi->tx_shift = cs->tx_shift;
-	mpc8xxx_spi->get_rx = cs->get_rx;
-	mpc8xxx_spi->get_tx = cs->get_tx;
-
-	return bits_per_word;
-}
-
-static int
-mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
-			  struct spi_device *spi,
-			  int bits_per_word)
-{
-	/* QE uses Little Endian for words > 8
-	 * so transform all words > 8 into 8 bits
-	 * Unfortnatly that doesn't work for LSB so
-	 * reject these for now */
-	/* Note: 32 bits word, LSB works iff
-	 * tfcr/rfcr is set to CPMFCR_GBL */
-	if (spi->mode & SPI_LSB_FIRST &&
-	    bits_per_word > 8)
-		return -EINVAL;
-	if (bits_per_word > 8)
-		return 8; /* pretend its 8 bits */
-	return bits_per_word;
-}
-
-static
-int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int bits_per_word;
-	u8 pm;
-	u32 hz;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	if (t) {
-		bits_per_word = t->bits_per_word;
-		hz = t->speed_hz;
-	} else {
-		bits_per_word = 0;
-		hz = 0;
-	}
-
-	/* spi_transfer level calls that work per-word */
-	if (!bits_per_word)
-		bits_per_word = spi->bits_per_word;
-
-	/* Make sure its a bit width we support [4..16, 32] */
-	if ((bits_per_word < 4)
-	    || ((bits_per_word > 16) && (bits_per_word != 32)))
-		return -EINVAL;
-
-	if (!hz)
-		hz = spi->max_speed_hz;
-
-	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
-		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
-							   mpc8xxx_spi,
-							   bits_per_word);
-	else if (mpc8xxx_spi->flags & SPI_QE)
-		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
-							  bits_per_word);
-
-	if (bits_per_word < 0)
-		return bits_per_word;
-
-	if (bits_per_word == 32)
-		bits_per_word = 0;
-	else
-		bits_per_word = bits_per_word - 1;
-
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
-				  | SPMODE_PM(0xF));
-
-	cs->hw_mode |= SPMODE_LEN(bits_per_word);
-
-	if ((mpc8xxx_spi->spibrg / hz) > 64) {
-		cs->hw_mode |= SPMODE_DIV16;
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
-
-		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
-			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
-			  hz, mpc8xxx_spi->spibrg / 1024);
-		if (pm > 16)
-			pm = 16;
-	} else
-		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
-	if (pm)
-		pm--;
-
-	cs->hw_mode |= SPMODE_PM(pm);
-
-	mpc8xxx_spi_change_mode(spi);
-	return 0;
-}
-
-static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
-{
-	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
-	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
-	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
-	unsigned int xfer_ofs;
-
-	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
-
-	if (mspi->rx_dma == mspi->dma_dummy_rx)
-		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
-	else
-		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
-	out_be16(&rx_bd->cbd_datlen, 0);
-	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
-
-	if (mspi->tx_dma == mspi->dma_dummy_tx)
-		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
-	else
-		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
-	out_be16(&tx_bd->cbd_datlen, xfer_len);
-	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
-				 BD_SC_LAST);
-
-	/* start transfer */
-	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
-}
-
-static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, bool is_dma_mapped)
-{
-	struct device *dev = mspi->dev;
-
-	if (is_dma_mapped) {
-		mspi->map_tx_dma = 0;
-		mspi->map_rx_dma = 0;
-	} else {
-		mspi->map_tx_dma = 1;
-		mspi->map_rx_dma = 1;
-	}
-
-	if (!t->tx_buf) {
-		mspi->tx_dma = mspi->dma_dummy_tx;
-		mspi->map_tx_dma = 0;
-	}
-
-	if (!t->rx_buf) {
-		mspi->rx_dma = mspi->dma_dummy_rx;
-		mspi->map_rx_dma = 0;
-	}
-
-	if (mspi->map_tx_dma) {
-		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
-
-		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
-					      DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, mspi->tx_dma)) {
-			dev_err(dev, "unable to map tx dma\n");
-			return -ENOMEM;
-		}
-	} else if (t->tx_buf) {
-		mspi->tx_dma = t->tx_dma;
-	}
-
-	if (mspi->map_rx_dma) {
-		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
-					      DMA_FROM_DEVICE);
-		if (dma_mapping_error(dev, mspi->rx_dma)) {
-			dev_err(dev, "unable to map rx dma\n");
-			goto err_rx_dma;
-		}
-	} else if (t->rx_buf) {
-		mspi->rx_dma = t->rx_dma;
-	}
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
-
-	mspi->xfer_in_progress = t;
-	mspi->count = t->len;
-
-	/* start CPM transfers */
-	mpc8xxx_spi_cpm_bufs_start(mspi);
-
-	return 0;
-
-err_rx_dma:
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	return -ENOMEM;
-}
-
-static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct spi_transfer *t = mspi->xfer_in_progress;
-
-	if (mspi->map_tx_dma)
-		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
-	if (mspi->map_rx_dma)
-		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
-	mspi->xfer_in_progress = NULL;
-}
-
-static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
-				struct spi_transfer *t, unsigned int len)
-{
-	u32 word;
-
-	mspi->count = len;
-
-	/* enable rx ints */
-	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
-
-	/* transmit word */
-	word = mspi->get_tx(mspi);
-	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
-
-	return 0;
-}
-
-static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
-			    bool is_dma_mapped)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned int len = t->len;
-	u8 bits_per_word;
-	int ret;
-
-	bits_per_word = spi->bits_per_word;
-	if (t->bits_per_word)
-		bits_per_word = t->bits_per_word;
-
-	if (bits_per_word > 8) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-	if (bits_per_word > 16) {
-		/* invalid length? */
-		if (len & 1)
-			return -EINVAL;
-		len /= 2;
-	}
-
-	mpc8xxx_spi->tx = t->tx_buf;
-	mpc8xxx_spi->rx = t->rx_buf;
-
-	INIT_COMPLETION(mpc8xxx_spi->done);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
-	else
-		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
-	if (ret)
-		return ret;
-
-	wait_for_completion(&mpc8xxx_spi->done);
-
-	/* disable rx ints */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-
-	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
-
-	return mpc8xxx_spi->count;
-}
-
-static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
-{
-	struct spi_device *spi = m->spi;
-	struct spi_transfer *t;
-	unsigned int cs_change;
-	const int nsecs = 50;
-	int status;
-
-	cs_change = 1;
-	status = 0;
-	list_for_each_entry(t, &m->transfers, transfer_list) {
-		if (t->bits_per_word || t->speed_hz) {
-			/* Don't allow changes if CS is active */
-			status = -EINVAL;
-
-			if (cs_change)
-				status = mpc8xxx_spi_setup_transfer(spi, t);
-			if (status < 0)
-				break;
-		}
-
-		if (cs_change) {
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
-			ndelay(nsecs);
-		}
-		cs_change = t->cs_change;
-		if (t->len)
-			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
-		if (status) {
-			status = -EMSGSIZE;
-			break;
-		}
-		m->actual_length += t->len;
-
-		if (t->delay_usecs)
-			udelay(t->delay_usecs);
-
-		if (cs_change) {
-			ndelay(nsecs);
-			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-			ndelay(nsecs);
-		}
-	}
-
-	m->status = status;
-	m->complete(m->context);
-
-	if (status || !cs_change) {
-		ndelay(nsecs);
-		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
-	}
-
-	mpc8xxx_spi_setup_transfer(spi, NULL);
-}
-
-static void mpc8xxx_spi_work(struct work_struct *work)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
-						       work);
-
-	spin_lock_irq(&mpc8xxx_spi->lock);
-	while (!list_empty(&mpc8xxx_spi->queue)) {
-		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
-						   struct spi_message, queue);
-
-		list_del_init(&m->queue);
-		spin_unlock_irq(&mpc8xxx_spi->lock);
-
-		mpc8xxx_spi_do_one_msg(m);
-
-		spin_lock_irq(&mpc8xxx_spi->lock);
-	}
-	spin_unlock_irq(&mpc8xxx_spi->lock);
-}
-
-static int mpc8xxx_spi_setup(struct spi_device *spi)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	int retval;
-	u32 hw_mode;
-	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
-
-	if (!spi->max_speed_hz)
-		return -EINVAL;
-
-	if (!cs) {
-		cs = kzalloc(sizeof *cs, GFP_KERNEL);
-		if (!cs)
-			return -ENOMEM;
-		spi->controller_state = cs;
-	}
-	mpc8xxx_spi = spi_master_get_devdata(spi->master);
-
-	hw_mode = cs->hw_mode; /* Save original settings */
-	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
-	/* mask out bits we are going to set */
-	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
-			 | SPMODE_REV | SPMODE_LOOP);
-
-	if (spi->mode & SPI_CPHA)
-		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
-	if (spi->mode & SPI_CPOL)
-		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
-	if (!(spi->mode & SPI_LSB_FIRST))
-		cs->hw_mode |= SPMODE_REV;
-	if (spi->mode & SPI_LOOP)
-		cs->hw_mode |= SPMODE_LOOP;
-
-	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
-	if (retval < 0) {
-		cs->hw_mode = hw_mode; /* Restore settings */
-		return retval;
-	}
-	return 0;
-}
-
-static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	u16 len;
-
-	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
-		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
-
-	len = in_be16(&mspi->rx_bd->cbd_datlen);
-	if (len > mspi->count) {
-		WARN_ON(1);
-		len = mspi->count;
-	}
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
-
-	mspi->count -= len;
-	if (mspi->count)
-		mpc8xxx_spi_cpm_bufs_start(mspi);
-	else
-		complete(&mspi->done);
-}
-
-static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
-{
-	/* We need handle RX first */
-	if (events & SPIE_NE) {
-		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
-
-		if (mspi->rx)
-			mspi->get_rx(rx_data, mspi);
-	}
-
-	if ((events & SPIE_NF) == 0)
-		/* spin until TX is done */
-		while (((events =
-			mpc8xxx_spi_read_reg(&mspi->base->event)) &
-						SPIE_NF) == 0)
-			cpu_relax();
-
-	/* Clear the events */
-	mpc8xxx_spi_write_reg(&mspi->base->event, events);
-
-	mspi->count -= 1;
-	if (mspi->count) {
-		u32 word = mspi->get_tx(mspi);
-
-		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
-	} else {
-		complete(&mspi->done);
-	}
-}
-
-static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
-{
-	struct mpc8xxx_spi *mspi = context_data;
-	irqreturn_t ret = IRQ_NONE;
-	u32 events;
-
-	/* Get interrupt events(tx/rx) */
-	events = mpc8xxx_spi_read_reg(&mspi->base->event);
-	if (events)
-		ret = IRQ_HANDLED;
-
-	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
-
-	if (mspi->flags & SPI_CPM_MODE)
-		mpc8xxx_spi_cpm_irq(mspi, events);
-	else
-		mpc8xxx_spi_cpu_irq(mspi, events);
-
-	return ret;
-}
-
-static int mpc8xxx_spi_transfer(struct spi_device *spi,
-				struct spi_message *m)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
-	unsigned long flags;
-
-	m->actual_length = 0;
-	m->status = -EINPROGRESS;
-
-	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
-	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
-	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
-	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
-
-	return 0;
-}
-
-
-static void mpc8xxx_spi_cleanup(struct spi_device *spi)
-{
-	kfree(spi->controller_state);
-}
-
-static void *mpc8xxx_spi_alloc_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	if (!mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
-	if (mpc8xxx_dummy_rx)
-		mpc8xxx_dummy_rx_refcnt++;
-
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
-
-	return mpc8xxx_dummy_rx;
-}
-
-static void mpc8xxx_spi_free_dummy_rx(void)
-{
-	mutex_lock(&mpc8xxx_dummy_rx_lock);
-
-	switch (mpc8xxx_dummy_rx_refcnt) {
-	case 0:
-		WARN_ON(1);
-		break;
-	case 1:
-		kfree(mpc8xxx_dummy_rx);
-		mpc8xxx_dummy_rx = NULL;
-		/* fall through */
-	default:
-		mpc8xxx_dummy_rx_refcnt--;
-		break;
-	}
-
-	mutex_unlock(&mpc8xxx_dummy_rx_lock);
-}
-
-static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long spi_base_ofs;
-	unsigned long pram_ofs = -ENOMEM;
-
-	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
-	iprop = of_get_property(np, "reg", &size);
-
-	/* QE with a fixed pram location? */
-	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
-		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
-
-	/* QE but with a dynamic pram location? */
-	if (mspi->flags & SPI_QE) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
-				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
-		return pram_ofs;
-	}
-
-	/* CPM1 and CPM2 pram must be at a fixed addr. */
-	if (!iprop || size != sizeof(*iprop) * 4)
-		return -ENOMEM;
-
-	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
-	if (IS_ERR_VALUE(spi_base_ofs))
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_CPM2) {
-		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
-		if (!IS_ERR_VALUE(pram_ofs)) {
-			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
-
-			out_be16(spi_base, pram_ofs);
-		}
-	} else {
-		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
-		u16 rpbase = in_be16(&pram->rpbase);
-
-		/* Microcode relocation patch applied? */
-		if (rpbase)
-			pram_ofs = rpbase;
-		else
-			return spi_base_ofs;
-	}
-
-	cpm_muram_free(spi_base_ofs);
-	return pram_ofs;
-}
-
-static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-	struct device_node *np = dev->of_node;
-	const u32 *iprop;
-	int size;
-	unsigned long pram_ofs;
-	unsigned long bds_ofs;
-
-	if (!(mspi->flags & SPI_CPM_MODE))
-		return 0;
-
-	if (!mpc8xxx_spi_alloc_dummy_rx())
-		return -ENOMEM;
-
-	if (mspi->flags & SPI_QE) {
-		iprop = of_get_property(np, "cell-index", &size);
-		if (iprop && size == sizeof(*iprop))
-			mspi->subblock = *iprop;
-
-		switch (mspi->subblock) {
-		default:
-			dev_warn(dev, "cell-index unspecified, assuming SPI1");
-			/* fall through */
-		case 0:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
-			break;
-		case 1:
-			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
-			break;
-		}
-	}
-
-	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
-	if (IS_ERR_VALUE(pram_ofs)) {
-		dev_err(dev, "can't allocate spi parameter ram\n");
-		goto err_pram;
-	}
-
-	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
-				  sizeof(*mspi->rx_bd), 8);
-	if (IS_ERR_VALUE(bds_ofs)) {
-		dev_err(dev, "can't allocate bds\n");
-		goto err_bds;
-	}
-
-	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
-					    DMA_TO_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
-		dev_err(dev, "unable to map dummy tx buffer\n");
-		goto err_dummy_tx;
-	}
-
-	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
-					    DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
-		dev_err(dev, "unable to map dummy rx buffer\n");
-		goto err_dummy_rx;
-	}
-
-	mspi->pram = cpm_muram_addr(pram_ofs);
-
-	mspi->tx_bd = cpm_muram_addr(bds_ofs);
-	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
-
-	/* Initialize parameter ram. */
-	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
-	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
-	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
-	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
-	out_be32(&mspi->pram->rstate, 0);
-	out_be32(&mspi->pram->rdp, 0);
-	out_be16(&mspi->pram->rbptr, 0);
-	out_be16(&mspi->pram->rbc, 0);
-	out_be32(&mspi->pram->rxtmp, 0);
-	out_be32(&mspi->pram->tstate, 0);
-	out_be32(&mspi->pram->tdp, 0);
-	out_be16(&mspi->pram->tbptr, 0);
-	out_be16(&mspi->pram->tbc, 0);
-	out_be32(&mspi->pram->txtmp, 0);
-
-	return 0;
-
-err_dummy_rx:
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-err_dummy_tx:
-	cpm_muram_free(bds_ofs);
-err_bds:
-	cpm_muram_free(pram_ofs);
-err_pram:
-	mpc8xxx_spi_free_dummy_rx();
-	return -ENOMEM;
-}
-
-static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
-{
-	struct device *dev = mspi->dev;
-
-	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
-	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
-	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
-	cpm_muram_free(cpm_muram_offset(mspi->pram));
-	mpc8xxx_spi_free_dummy_rx();
-}
-
-static const char *mpc8xxx_spi_strmode(unsigned int flags)
-{
-	if (flags & SPI_QE_CPU_MODE) {
-		return "QE CPU";
-	} else if (flags & SPI_CPM_MODE) {
-		if (flags & SPI_QE)
-			return "QE";
-		else if (flags & SPI_CPM2)
-			return "CPM2";
-		else
-			return "CPM1";
-	}
-	return "CPU";
-}
-
-static struct spi_master * __devinit
-mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct spi_master *master;
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	u32 regval;
-	int ret = 0;
-
-	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
-	if (master == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	dev_set_drvdata(dev, master);
-
-	/* the spi->mode bits understood by this driver: */
-	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
-			| SPI_LSB_FIRST | SPI_LOOP;
-
-	master->setup = mpc8xxx_spi_setup;
-	master->transfer = mpc8xxx_spi_transfer;
-	master->cleanup = mpc8xxx_spi_cleanup;
-	master->dev.of_node = dev->of_node;
-
-	mpc8xxx_spi = spi_master_get_devdata(master);
-	mpc8xxx_spi->dev = dev;
-	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
-	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
-	mpc8xxx_spi->flags = pdata->flags;
-	mpc8xxx_spi->spibrg = pdata->sysclk;
-
-	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
-	if (ret)
-		goto err_cpm_init;
-
-	mpc8xxx_spi->rx_shift = 0;
-	mpc8xxx_spi->tx_shift = 0;
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
-		mpc8xxx_spi->rx_shift = 16;
-		mpc8xxx_spi->tx_shift = 24;
-	}
-
-	init_completion(&mpc8xxx_spi->done);
-
-	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
-	if (mpc8xxx_spi->base == NULL) {
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	mpc8xxx_spi->irq = irq;
-
-	/* Register for SPI Interrupt */
-	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
-			  0, "mpc8xxx_spi", mpc8xxx_spi);
-
-	if (ret != 0)
-		goto unmap_io;
-
-	master->bus_num = pdata->bus_num;
-	master->num_chipselect = pdata->max_chipselect;
-
-	/* SPI controller initializations */
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
-
-	/* Enable SPI interface */
-	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
-	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
-		regval |= SPMODE_OP;
-
-	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
-	spin_lock_init(&mpc8xxx_spi->lock);
-	init_completion(&mpc8xxx_spi->done);
-	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
-	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
-
-	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
-		dev_name(master->dev.parent));
-	if (mpc8xxx_spi->workqueue == NULL) {
-		ret = -EBUSY;
-		goto free_irq;
-	}
-
-	ret = spi_register_master(master);
-	if (ret < 0)
-		goto unreg_master;
-
-	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
-		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
-
-	return master;
-
-unreg_master:
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-free_irq:
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-unmap_io:
-	iounmap(mpc8xxx_spi->base);
-err_ioremap:
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-err_cpm_init:
-	spi_master_put(master);
-err:
-	return ERR_PTR(ret);
-}
-
-static int __devexit mpc8xxx_spi_remove(struct device *dev)
-{
-	struct mpc8xxx_spi *mpc8xxx_spi;
-	struct spi_master *master;
-
-	master = dev_get_drvdata(dev);
-	mpc8xxx_spi = spi_master_get_devdata(master);
-
-	flush_workqueue(mpc8xxx_spi->workqueue);
-	destroy_workqueue(mpc8xxx_spi->workqueue);
-	spi_unregister_master(master);
-
-	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-	iounmap(mpc8xxx_spi->base);
-	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
-
-	return 0;
-}
-
-struct mpc8xxx_spi_probe_info {
-	struct fsl_spi_platform_data pdata;
-	int *gpios;
-	bool *alow_flags;
-};
-
-static struct mpc8xxx_spi_probe_info *
-to_of_pinfo(struct fsl_spi_platform_data *pdata)
-{
-	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
-}
-
-static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
-{
-	struct device *dev = spi->dev.parent;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
-	u16 cs = spi->chip_select;
-	int gpio = pinfo->gpios[cs];
-	bool alow = pinfo->alow_flags[cs];
-
-	gpio_set_value(gpio, on ^ alow);
-}
-
-static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
-{
-	struct device_node *np = dev->of_node;
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	unsigned int ngpios;
-	int i = 0;
-	int ret;
-
-	ngpios = of_gpio_count(np);
-	if (!ngpios) {
-		/*
-		 * SPI w/o chip-select line. One SPI device is still permitted
-		 * though.
-		 */
-		pdata->max_chipselect = 1;
-		return 0;
-	}
-
-	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
-	if (!pinfo->gpios)
-		return -ENOMEM;
-	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
-
-	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
-				    GFP_KERNEL);
-	if (!pinfo->alow_flags) {
-		ret = -ENOMEM;
-		goto err_alloc_flags;
-	}
-
-	for (; i < ngpios; i++) {
-		int gpio;
-		enum of_gpio_flags flags;
-
-		gpio = of_get_gpio_flags(np, i, &flags);
-		if (!gpio_is_valid(gpio)) {
-			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
-			ret = gpio;
-			goto err_loop;
-		}
-
-		ret = gpio_request(gpio, dev_name(dev));
-		if (ret) {
-			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
-			goto err_loop;
-		}
-
-		pinfo->gpios[i] = gpio;
-		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
-
-		ret = gpio_direction_output(pinfo->gpios[i],
-					    pinfo->alow_flags[i]);
-		if (ret) {
-			dev_err(dev, "can't set output direction for gpio "
-				"#%d: %d\n", i, ret);
-			goto err_loop;
-		}
-	}
-
-	pdata->max_chipselect = ngpios;
-	pdata->cs_control = mpc8xxx_spi_cs_control;
-
-	return 0;
-
-err_loop:
-	while (i >= 0) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-		i--;
-	}
-
-	kfree(pinfo->alow_flags);
-	pinfo->alow_flags = NULL;
-err_alloc_flags:
-	kfree(pinfo->gpios);
-	pinfo->gpios = NULL;
-	return ret;
-}
-
-static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
-{
-	struct fsl_spi_platform_data *pdata = dev->platform_data;
-	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
-	int i;
-
-	if (!pinfo->gpios)
-		return 0;
-
-	for (i = 0; i < pdata->max_chipselect; i++) {
-		if (gpio_is_valid(pinfo->gpios[i]))
-			gpio_free(pinfo->gpios[i]);
-	}
-
-	kfree(pinfo->gpios);
-	kfree(pinfo->alow_flags);
-	return 0;
-}
-
-static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-					  const struct of_device_id *ofid)
-{
-	struct device *dev = &ofdev->dev;
-	struct device_node *np = ofdev->dev.of_node;
-	struct mpc8xxx_spi_probe_info *pinfo;
-	struct fsl_spi_platform_data *pdata;
-	struct spi_master *master;
-	struct resource mem;
-	struct resource irq;
-	const void *prop;
-	int ret = -ENOMEM;
-
-	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
-	if (!pinfo)
-		return -ENOMEM;
-
-	pdata = &pinfo->pdata;
-	dev->platform_data = pdata;
-
-	/* Allocate bus num dynamically. */
-	pdata->bus_num = -1;
-
-	/* SPI controller is either clocked from QE or SoC clock. */
-	pdata->sysclk = get_brgfreq();
-	if (pdata->sysclk == -1) {
-		pdata->sysclk = fsl_get_sys_freq();
-		if (pdata->sysclk == -1) {
-			ret = -ENODEV;
-			goto err_clk;
-		}
-	}
-
-	prop = of_get_property(np, "mode", NULL);
-	if (prop && !strcmp(prop, "cpu-qe"))
-		pdata->flags = SPI_QE_CPU_MODE;
-	else if (prop && !strcmp(prop, "qe"))
-		pdata->flags = SPI_CPM_MODE | SPI_QE;
-	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
-	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
-		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
-
-	ret = of_mpc8xxx_spi_get_chipselects(dev);
-	if (ret)
-		goto err;
-
-	ret = of_address_to_resource(np, 0, &mem);
-	if (ret)
-		goto err;
-
-	ret = of_irq_to_resource(np, 0, &irq);
-	if (!ret) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
-	if (IS_ERR(master)) {
-		ret = PTR_ERR(master);
-		goto err;
-	}
-
-	return 0;
-
-err:
-	of_mpc8xxx_spi_free_chipselects(dev);
-err_clk:
-	kfree(pinfo);
-	return ret;
-}
-
-static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
-{
-	int ret;
-
-	ret = mpc8xxx_spi_remove(&ofdev->dev);
-	if (ret)
-		return ret;
-	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
-	return 0;
-}
-
-static const struct of_device_id of_mpc8xxx_spi_match[] = {
-	{ .compatible = "fsl,spi" },
-	{},
-};
-MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
-
-static struct of_platform_driver of_mpc8xxx_spi_driver = {
-	.driver = {
-		.name = "mpc8xxx_spi",
-		.owner = THIS_MODULE,
-		.of_match_table = of_mpc8xxx_spi_match,
-	},
-	.probe		= of_mpc8xxx_spi_probe,
-	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
-};
-
-#ifdef CONFIG_MPC832x_RDB
-/*
- * 				XXX XXX XXX
- * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
- * only. The driver should go away soon, since newer MPC8323E-RDB's device
- * tree can work with OpenFirmware driver. But for now we support old trees
- * as well.
- */
-static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
-{
-	struct resource *mem;
-	int irq;
-	struct spi_master *master;
-
-	if (!pdev->dev.platform_data)
-		return -EINVAL;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		return -EINVAL;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
-		return -EINVAL;
-
-	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
-	if (IS_ERR(master))
-		return PTR_ERR(master);
-	return 0;
-}
-
-static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
-{
-	return mpc8xxx_spi_remove(&pdev->dev);
-}
-
-MODULE_ALIAS("platform:mpc8xxx_spi");
-static struct platform_driver mpc8xxx_spi_driver = {
-	.probe = plat_mpc8xxx_spi_probe,
-	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
-	.driver = {
-		.name = "mpc8xxx_spi",
-		.owner = THIS_MODULE,
-	},
-};
-
-static bool legacy_driver_failed;
-
-static void __init legacy_driver_register(void)
-{
-	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
-}
-
-static void __exit legacy_driver_unregister(void)
-{
-	if (legacy_driver_failed)
-		return;
-	platform_driver_unregister(&mpc8xxx_spi_driver);
-}
-#else
-static void __init legacy_driver_register(void) {}
-static void __exit legacy_driver_unregister(void) {}
-#endif /* CONFIG_MPC832x_RDB */
-
-static int __init mpc8xxx_spi_init(void)
-{
-	legacy_driver_register();
-	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
-}
-
-static void __exit mpc8xxx_spi_exit(void)
-{
-	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
-	legacy_driver_unregister();
-}
-
-module_init(mpc8xxx_spi_init);
-module_exit(mpc8xxx_spi_exit);
-
-MODULE_AUTHOR("Kumar Gala");
-MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
-MODULE_LICENSE("GPL");
-- 
1.6.4




From Mingkai.hu at freescale.com  Tue Oct 12 06:18:32 2010
From: Mingkai.hu at freescale.com (Mingkai Hu)
Date: Tue, 12 Oct 2010 18:18:32 +0800
Subject: [PATCH v4 3/5] eSPI: add eSPI controller support
In-Reply-To: <1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>

Add eSPI controller support based on the library code spi_fsl_lib.c.

The eSPI controller is newer controller 85xx/Pxxx devices supported.
There're some differences comparing to the SPI controller:

1. Has different register map and different bit definition
   So leave the code operated the register to the driver code, not
   the common code.

2. Support 4 dedicated chip selects
   The software can't controll the chip selects directly, The SPCOM[CS]
   field is used to select which chip selects is used, and the
   SPCOM[TRANLEN] field is set to tell the controller how long the CS
   signal need to be asserted. So the driver doesn't need the chipselect
   related function when transfering data, just set corresponding register
   fields to controll the chipseclect.

3. Different Transmit/Receive FIFO access register behavior
   For SPI controller, the Tx/Rx FIFO access register can hold only
   one character regardless of the character length, but for eSPI
   controller, the register can hold 4 or 2 characters according to
   the character lengths. Access the Tx/Rx FIFO access register of the
   eSPI controller will shift out/in 4/2 characters one time. For SPI
   subsystem, the command and data are put into different transfers, so
   we need to combine all the transfers to one transfer in order to pass
   the transfer to eSPI controller.

4. The max transaction length limitation
   The max transaction length one time is limitted by the SPCOM[TRANSLEN]
   field which is 0xFFFF. When used mkfs.ext2 command to create ext2
   filesystem on the flash, the read length will exceed the max value of
   the SPCOM[TRANSLEN] field.

Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
---
v4:
 - Updated to latest kernel base(Linux 2.6.36-rc7).
 - Added support to the transaction that the length is grater than 0xFFFF.
 - Made some changes according to Anton's comments.

 drivers/spi/Kconfig        |    9 +
 drivers/spi/Makefile       |    1 +
 drivers/spi/spi_fsl_espi.c |  748 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/spi/spi_fsl_lib.h  |    3 +
 4 files changed, 761 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/spi_fsl_espi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 79ad06f..f6888af 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -195,6 +195,15 @@ config SPI_FSL_SPI
 	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
 	  MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
 
+config SPI_FSL_ESPI
+	tristate "Freescale eSPI controller"
+	depends on FSL_SOC
+	select SPI_FSL_LIB
+	help
+	  This enables using the Freescale eSPI controllers in master mode.
+	  From MPC8536, 85xx platform uses the controller, and all P10xx,
+	  P20xx, P30xx,P40xx, P50xx uses this controller.
+
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
 	depends on ARCH_OMAP1
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 7974c21..833d17e 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
 obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
+obj-$(CONFIG_SPI_FSL_ESPI)		+= spi_fsl_espi.o
 obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
 obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
new file mode 100644
index 0000000..e3b4f64
--- /dev/null
+++ b/drivers/spi/spi_fsl_espi.c
@@ -0,0 +1,748 @@
+/*
+ * Freescale eSPI controller driver.
+ *
+ * Copyright 2010 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 <linux/module.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_spi.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <sysdev/fsl_soc.h>
+
+#include "spi_fsl_lib.h"
+
+/* eSPI Controller registers */
+struct fsl_espi_reg {
+	__be32 mode;		/* 0x000 - eSPI mode register */
+	__be32 event;		/* 0x004 - eSPI event register */
+	__be32 mask;		/* 0x008 - eSPI mask register */
+	__be32 command;		/* 0x00c - eSPI command register */
+	__be32 transmit;	/* 0x010 - eSPI transmit FIFO access register*/
+	__be32 receive;		/* 0x014 - eSPI receive FIFO access register*/
+	u8 res[8];		/* 0x018 - 0x01c reserved */
+	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode register */
+};
+
+struct fsl_espi_transfer {
+	const void *tx_buf;
+	void *rx_buf;
+	unsigned len;
+	unsigned n_tx;
+	unsigned n_rx;
+	unsigned actual_length;
+	int status;
+};
+
+/* eSPI Controller mode register definitions */
+#define SPMODE_ENABLE		(1 << 31)
+#define SPMODE_LOOP		(1 << 30)
+#define SPMODE_TXTHR(x)		((x) << 8)
+#define SPMODE_RXTHR(x)		((x) << 0)
+
+/* eSPI Controller CS mode register definitions */
+#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
+#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
+#define CSMODE_REV		(1 << 29)
+#define CSMODE_DIV16		(1 << 28)
+#define CSMODE_PM(x)		((x) << 24)
+#define CSMODE_POL_1		(1 << 20)
+#define CSMODE_LEN(x)		((x) << 16)
+#define CSMODE_BEF(x)		((x) << 12)
+#define CSMODE_AFT(x)		((x) << 8)
+#define CSMODE_CG(x)		((x) << 3)
+
+/* Default mode/csmode for eSPI controller */
+#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
+#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
+		| CSMODE_AFT(0) | CSMODE_CG(1))
+
+/* SPIE register values */
+#define	SPIE_NE		0x00000200	/* Not empty */
+#define	SPIE_NF		0x00000100	/* Not full */
+
+/* SPIM register values */
+#define	SPIM_NE		0x00000200	/* Not empty */
+#define	SPIM_NF		0x00000100	/* Not full */
+#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
+#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
+
+/* SPCOM register values */
+#define SPCOM_CS(x)		((x) << 30)
+#define SPCOM_TRANLEN(x)	((x) << 0)
+#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max transaction length */
+
+static void fsl_espi_change_mode(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	__be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
+	__be32 __iomem *espi_mode = &reg_base->mode;
+	u32 tmp;
+	unsigned long flags;
+
+	/* Turn off IRQs locally to minimize time that SPI is disabled. */
+	local_irq_save(flags);
+
+	/* Turn off SPI unit prior changing mode */
+	tmp = mpc8xxx_spi_read_reg(espi_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
+	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
+	mpc8xxx_spi_write_reg(espi_mode, tmp);
+
+	local_irq_restore(flags);
+}
+
+static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
+{
+	u32 data;
+	u16 data_h;
+	u16 data_l;
+	const u32 *tx = mpc8xxx_spi->tx;
+
+	if (!tx)
+		return 0;
+
+	data = *tx++ << mpc8xxx_spi->tx_shift;
+	data_l = data & 0xffff;
+	data_h = (data >> 16) & 0xffff;
+	swab16s(&data_l);
+	swab16s(&data_h);
+	data = data_h | data_l;
+
+	mpc8xxx_spi->tx = tx;
+	return data;
+}
+
+static int fsl_espi_setup_transfer(struct spi_device *spi,
+					struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	int bits_per_word = 0;
+	u8 pm;
+	u32 hz = 0;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (t) {
+		bits_per_word = t->bits_per_word;
+		hz = t->speed_hz;
+	}
+
+	/* spi_transfer level calls that work per-word */
+	if (!bits_per_word)
+		bits_per_word = spi->bits_per_word;
+
+	/* Make sure its a bit width we support [4..16] */
+	if ((bits_per_word < 4) || (bits_per_word > 16))
+		return -EINVAL;
+
+	if (!hz)
+		hz = spi->max_speed_hz;
+
+	cs->rx_shift = 0;
+	cs->tx_shift = 0;
+	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
+	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
+	if (bits_per_word <= 8) {
+		cs->rx_shift = 8 - bits_per_word;
+	} else if (bits_per_word <= 16) {
+		cs->rx_shift = 16 - bits_per_word;
+		if (spi->mode & SPI_LSB_FIRST)
+			cs->get_tx = fsl_espi_tx_buf_lsb;
+	} else {
+		return -EINVAL;
+	}
+
+	mpc8xxx_spi->rx_shift = cs->rx_shift;
+	mpc8xxx_spi->tx_shift = cs->tx_shift;
+	mpc8xxx_spi->get_rx = cs->get_rx;
+	mpc8xxx_spi->get_tx = cs->get_tx;
+
+	bits_per_word = bits_per_word - 1;
+
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
+
+	cs->hw_mode |= CSMODE_LEN(bits_per_word);
+
+	if ((mpc8xxx_spi->spibrg / hz) > 64) {
+		cs->hw_mode |= CSMODE_DIV16;
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
+
+		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
+			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
+			  hz, mpc8xxx_spi->spibrg / 1024);
+		if (pm > 16)
+			pm = 16;
+	} else {
+		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
+	}
+	if (pm)
+		pm--;
+
+	cs->hw_mode |= CSMODE_PM(pm);
+
+	fsl_espi_change_mode(spi);
+	return 0;
+}
+
+static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
+		unsigned int len)
+{
+	u32 word;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	mspi->count = len;
+
+	/* enable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
+
+	/* transmit word */
+	word = mspi->get_tx(mspi);
+	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+
+	return 0;
+}
+
+static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
+	unsigned int len = t->len;
+	u8 bits_per_word;
+	int ret;
+
+	bits_per_word = spi->bits_per_word;
+	if (t->bits_per_word)
+		bits_per_word = t->bits_per_word;
+
+	mpc8xxx_spi->len = t->len;
+	len = roundup(len, 4) / 4;
+
+	mpc8xxx_spi->tx = t->tx_buf;
+	mpc8xxx_spi->rx = t->rx_buf;
+
+	INIT_COMPLETION(mpc8xxx_spi->done);
+
+	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
+	if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
+		dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
+				" beyond the SPCOM[TRANLEN] field\n", t->len);
+		return -EINVAL;
+	}
+	mpc8xxx_spi_write_reg(&reg_base->command,
+		(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
+
+	ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&mpc8xxx_spi->done);
+
+	/* disable rx ints */
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+
+	return mpc8xxx_spi->count;
+}
+
+static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
+{
+	if (cmd[1] && cmd[2] && cmd[3]) {
+		cmd[1] = (u8)(addr >> 16);
+		cmd[2] = (u8)(addr >> 8);
+		cmd[3] = (u8)(addr >> 0);
+	}
+}
+
+static unsigned int fsl_espi_cmd2addr(u8 *cmd)
+{
+	if (cmd[1] && cmd[2] && cmd[3])
+		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
+
+	return 0;
+}
+
+static void fsl_espi_do_trans(struct spi_message *m,
+				struct fsl_espi_transfer *tr)
+{
+	struct spi_device *spi = m->spi;
+	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
+	struct fsl_espi_transfer *espi_trans = tr;
+	struct spi_message message;
+	struct spi_transfer *t, *first, trans;
+	int status = 0;
+
+	spi_message_init(&message);
+	memset(&trans, 0, sizeof(trans));
+
+	first = list_first_entry(&m->transfers, struct spi_transfer,
+			transfer_list);
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if ((first->bits_per_word != t->bits_per_word) ||
+			(first->speed_hz != t->speed_hz)) {
+			espi_trans->status = -EINVAL;
+			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
+					" same for the same SPI transfer\n");
+			return;
+		}
+
+		trans.speed_hz = t->speed_hz;
+		trans.bits_per_word = t->bits_per_word;
+		trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
+	}
+
+	trans.len = espi_trans->len;
+	trans.tx_buf = espi_trans->tx_buf;
+	trans.rx_buf = espi_trans->rx_buf;
+	spi_message_add_tail(&trans, &message);
+
+	list_for_each_entry(t, &message.transfers, transfer_list) {
+		if (t->bits_per_word || t->speed_hz) {
+			status = -EINVAL;
+
+			status = fsl_espi_setup_transfer(spi, t);
+			if (status < 0)
+				break;
+		}
+
+		if (t->len)
+			status = fsl_espi_bufs(spi, t);
+
+		if (status) {
+			status = -EMSGSIZE;
+			break;
+		}
+
+		if (t->delay_usecs)
+			udelay(t->delay_usecs);
+	}
+
+	espi_trans->status = status;
+	fsl_espi_setup_transfer(spi, NULL);
+}
+
+static void fsl_espi_cmd_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct spi_transfer *t;
+	u8 *local_buf;
+	int i = 0;
+	struct fsl_espi_transfer *espi_trans = trans;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf) {
+			memcpy(local_buf + i, t->tx_buf, t->len);
+			i += t->len;
+		}
+	}
+
+	espi_trans->tx_buf = local_buf;
+	espi_trans->rx_buf = local_buf + espi_trans->n_tx;
+	fsl_espi_do_trans(m, espi_trans);
+
+	espi_trans->actual_length = espi_trans->len;
+	kfree(local_buf);
+}
+
+static void fsl_espi_rw_trans(struct spi_message *m,
+				struct fsl_espi_transfer *trans, u8 *rx_buff)
+{
+	struct fsl_espi_transfer *espi_trans = trans;
+	unsigned int n_tx = espi_trans->n_tx;
+	unsigned int n_rx = espi_trans->n_rx;
+	struct spi_transfer *t;
+	u8 *local_buf;
+	u8 *rx_buf = rx_buff;
+	unsigned int trans_len;
+	unsigned int addr;
+	int i, pos, loop;
+
+	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
+	if (!local_buf) {
+		espi_trans->status = -ENOMEM;
+		return;
+	}
+
+	for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
+		trans_len = n_rx - pos;
+		if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
+			trans_len = SPCOM_TRANLEN_MAX - n_tx;
+
+		i = 0;
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			if (t->tx_buf) {
+				memcpy(local_buf + i, t->tx_buf, t->len);
+				i += t->len;
+			}
+		}
+
+		addr = fsl_espi_cmd2addr(local_buf);
+		addr += pos;
+		fsl_espi_addr2cmd(addr, local_buf);
+
+		espi_trans->n_tx = n_tx;
+		espi_trans->n_rx = trans_len;
+		espi_trans->len = trans_len + n_tx;
+		espi_trans->tx_buf = local_buf;
+		espi_trans->rx_buf = local_buf + n_tx;
+		fsl_espi_do_trans(m, espi_trans);
+
+		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
+
+		if (loop > 0)
+			espi_trans->actual_length += espi_trans->len - n_tx;
+		else
+			espi_trans->actual_length += espi_trans->len;
+	}
+
+	kfree(local_buf);
+}
+
+static void fsl_espi_do_one_msg(struct spi_message *m)
+{
+	struct spi_transfer *t;
+	u8 *rx_buf = NULL;
+	unsigned int n_tx = 0;
+	unsigned int n_rx = 0;
+	struct fsl_espi_transfer espi_trans;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->tx_buf)
+			n_tx += t->len;
+		if (t->rx_buf) {
+			n_rx += t->len;
+			rx_buf = t->rx_buf;
+		}
+	}
+
+	espi_trans.n_tx = n_tx;
+	espi_trans.n_rx = n_rx;
+	espi_trans.len = n_tx + n_rx;
+	espi_trans.actual_length = 0;
+	espi_trans.status = 0;
+
+	if (!rx_buf)
+		fsl_espi_cmd_trans(m, &espi_trans, NULL);
+	else
+		fsl_espi_rw_trans(m, &espi_trans, rx_buf);
+
+	m->actual_length = espi_trans.actual_length;
+	m->status = espi_trans.status;
+	m->complete(m->context);
+}
+
+static int fsl_espi_setup(struct spi_device *spi)
+{
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	int retval;
+	u32 hw_mode;
+	u32 loop_mode;
+	struct spi_mpc8xxx_cs *cs = spi->controller_state;
+
+	if (!spi->max_speed_hz)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	mpc8xxx_spi = spi_master_get_devdata(spi->master);
+	reg_base = mpc8xxx_spi->reg_base;
+
+	hw_mode = cs->hw_mode; /* Save orginal settings */
+	cs->hw_mode = mpc8xxx_spi_read_reg(
+			&reg_base->csmode[spi->chip_select]);
+	/* mask out bits we are going to set */
+	cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
+			 | CSMODE_REV);
+
+	if (spi->mode & SPI_CPHA)
+		cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
+	if (spi->mode & SPI_CPOL)
+		cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
+	if (!(spi->mode & SPI_LSB_FIRST))
+		cs->hw_mode |= CSMODE_REV;
+
+	/* Handle the loop mode */
+	loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
+	loop_mode &= ~SPMODE_LOOP;
+	if (spi->mode & SPI_LOOP)
+		loop_mode |= SPMODE_LOOP;
+	mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
+
+	retval = fsl_espi_setup_transfer(spi, NULL);
+	if (retval < 0) {
+		cs->hw_mode = hw_mode; /* Restore settings */
+		return retval;
+	}
+	return 0;
+}
+
+void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
+{
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+
+	/* We need handle RX first */
+	if (events & SPIE_NE) {
+		u32 rx_data;
+
+		/* Spin until RX is done */
+		while (SPIE_RXCNT(events) < min(4, mspi->len)) {
+			cpu_relax();
+			events = mpc8xxx_spi_read_reg(&reg_base->event);
+		}
+		mspi->len -= 4;
+
+		rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+
+		if (mspi->rx)
+			mspi->get_rx(rx_data, mspi);
+	}
+
+	if (!(events & SPIE_NF)) {
+		int ret;
+
+		/* spin until TX is done */
+		ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
+				&reg_base->event)) & SPIE_NF) == 0, 1000, 0);
+		if (!ret) {
+			dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
+			return;
+		}
+	}
+
+	/* Clear the events */
+	mpc8xxx_spi_write_reg(&reg_base->event, events);
+
+	mspi->count -= 1;
+	if (mspi->count) {
+		u32 word = mspi->get_tx(mspi);
+
+		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
+	} else {
+		complete(&mspi->done);
+	}
+}
+
+static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
+{
+	struct mpc8xxx_spi *mspi = context_data;
+	struct fsl_espi_reg *reg_base = mspi->reg_base;
+	irqreturn_t ret = IRQ_NONE;
+	u32 events;
+
+	/* Get interrupt events(tx/rx) */
+	events = mpc8xxx_spi_read_reg(&reg_base->event);
+	if (events)
+		ret = IRQ_HANDLED;
+
+	dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
+
+	fsl_espi_cpu_irq(mspi, events);
+
+	return ret;
+}
+
+static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+{
+	iounmap(mspi->reg_base);
+}
+
+static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
+		struct resource *mem, unsigned int irq)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct spi_master *master;
+	struct mpc8xxx_spi *mpc8xxx_spi;
+	struct fsl_espi_reg *reg_base;
+	u32 regval;
+	int i, ret = 0;
+
+	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
+	if (!master) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	dev_set_drvdata(dev, master);
+
+	ret = mpc8xxx_spi_probe(dev, mem, irq);
+	if (ret)
+		goto err_probe;
+
+	master->setup = fsl_espi_setup;
+
+	mpc8xxx_spi = spi_master_get_devdata(master);
+	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
+	mpc8xxx_spi->spi_remove = fsl_espi_remove;
+
+	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
+	if (!mpc8xxx_spi->reg_base) {
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+
+	reg_base = mpc8xxx_spi->reg_base;
+
+	/* Register for SPI Interrupt */
+	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+			  0, "fsl_espi", mpc8xxx_spi);
+	if (ret)
+		goto free_irq;
+
+	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
+		mpc8xxx_spi->rx_shift = 16;
+		mpc8xxx_spi->tx_shift = 24;
+	}
+
+	/* SPI controller initializations */
+	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+	mpc8xxx_spi_write_reg(&reg_base->command, 0);
+	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+	/* Init eSPI CS mode register */
+	for (i = 0; i < pdata->max_chipselect; i++)
+		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+	/* Enable SPI interface */
+	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+
+	return master;
+
+unreg_master:
+	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
+free_irq:
+	iounmap(mpc8xxx_spi->reg_base);
+err_probe:
+	spi_master_put(master);
+err:
+	return ERR_PTR(ret);
+}
+
+static int of_fsl_espi_get_chipselects(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	const u32 *prop;
+	int len;
+
+	prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
+	if (!prop || len < sizeof(*prop)) {
+		dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
+		return -EINVAL;
+	}
+
+	pdata->max_chipselect = *prop;
+	pdata->cs_control = NULL;
+
+	return 0;
+}
+
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
+					const struct of_device_id *ofid)
+{
+	struct device *dev = &ofdev->dev;
+	struct device_node *np = ofdev->dev.of_node;
+	struct spi_master *master;
+	struct resource mem;
+	struct resource irq;
+	int ret = -ENOMEM;
+
+	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	if (ret)
+		return ret;
+
+	ret = of_fsl_espi_get_chipselects(dev);
+	if (ret)
+		goto err;
+
+	ret = of_address_to_resource(np, 0, &mem);
+	if (ret)
+		goto err;
+
+	ret = of_irq_to_resource(np, 0, &irq);
+	if (!ret) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	master = fsl_espi_probe(dev, &mem, irq.start);
+	if (IS_ERR(master)) {
+		ret = PTR_ERR(master);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	return ret;
+}
+
+static int __devexit of_fsl_espi_remove(struct platform_device *dev)
+{
+	return mpc8xxx_spi_remove(&dev->dev);
+}
+
+static const struct of_device_id of_fsl_espi_match[] = {
+	{ .compatible = "fsl,mpc8536-espi" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
+
+static struct of_platform_driver fsl_espi_driver = {
+	.driver = {
+		.name = "fsl_espi",
+		.owner = THIS_MODULE,
+		.of_match_table = of_fsl_espi_match,
+	},
+	.probe		= of_fsl_espi_probe,
+	.remove		= __devexit_p(of_fsl_espi_remove),
+};
+
+static int __init fsl_espi_init(void)
+{
+	return of_register_platform_driver(&fsl_espi_driver);
+}
+module_init(fsl_espi_init);
+
+static void __exit fsl_espi_exit(void)
+{
+	of_unregister_platform_driver(&fsl_espi_driver);
+}
+module_exit(fsl_espi_exit);
+
+MODULE_AUTHOR("Mingkai Hu");
+MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
index 6ae8949..15aa6c2 100644
--- a/drivers/spi/spi_fsl_lib.h
+++ b/drivers/spi/spi_fsl_lib.h
@@ -26,6 +26,9 @@ struct mpc8xxx_spi {
 	/* rx & tx bufs from the spi_transfer */
 	const void *tx;
 	void *rx;
+#ifdef CONFIG_SPI_FSL_ESPI
+	int len;
+#endif
 
 	int subblock;
 	struct spi_pram __iomem *pram;
-- 
1.6.4




From glecerf at gmail.com  Tue Oct 12 06:48:44 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 12 Oct 2010 12:48:44 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <8129711D4006470194ABF97D154047CF@THOR>
References: <E73F778B634944A0B8D4333B7BD012E4@THOR>
	<AANLkTin2b-QovauogfjMZP_7KeChY5oWsMPFBAiC2ERE@mail.gmail.com>
	<74A5BE60138147F696E151AACD52EDEE@THOR>
	<AANLkTintkdKGpkUGMkgGbVK6Pb3cttspwnuPQR=DJxnm@mail.gmail.com>
	<D3A375B91F5944B38630B07214914DF8@THOR>
	<AANLkTinotjfB26VPmF7_vx8M1kX5cYMzygFMk8X6exww@mail.gmail.com>
	<341EADF720C14B4F86C63204D9C60723@THOR>
	<AANLkTikXbKZLFOCBDkrwgVPJEYTwF88xBtYFnwaTQH+5@mail.gmail.com>
	<6E1A182A06054C5A99BD3C0D3202C24F@THOR>
	<AANLkTi=qZ_wYcHHfKjaJsvf-ODgnECDOTEHmuorpA7K2@mail.gmail.com>
	<DB610A768D2B46C7A888B2DBECEBEC79@THOR>
	<AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com>
	<8129711D4006470194ABF97D154047CF@THOR>
Message-ID: <AANLkTi=cnQpszRyVXfCOF=kFwc5v8-2pKKnTJXm45_jK@mail.gmail.com>

2010/10/5 Fl?vio Silveira <fggs at terra.com.br>:
> Actually yes, I applied your patch to kernel 2.6.35.4 and it detects the
> chip.
> I just need to test without your patch to see the difference.

Up.

Did you had time to test without the patch to see if it's actually needed ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From karl.beldan at gmail.com  Tue Oct 12 09:16:40 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Tue, 12 Oct 2010 15:16:40 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <1286825063.1742.13.camel@brekeke>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
Message-ID: <AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>

On Mon, Oct 11, 2010 at 9:24 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
>> Hi,
>>
>> I have been using this tweak for some time now, and I am getting tired of
>> having to resort to it so often.
>> It allows to pass such cmdline root as:
>> ?"root=mtdb:ubivolx rootfstype=squashfs"
>> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
>> for example, and I thought that this might initiate discussion.
>>
>> --
>> Karl
>>
>> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
>> ---
>> ?init/do_mounts.c | ? 15 +++++++++++++--
>> ?1 files changed, 13 insertions(+), 2 deletions(-)
>
> Dunno...
>
> First of all, if you have to do this, let it be mtdblock, not mtdb - no
> need to breed aliases.
>
> But how about teaching squashfs to understand mtdX and mtd:name syntax
> instead?
>

Hi Artem,

I would not do that, squashfs and co just ask for a block device, putting mtdx
syntax awareness in each of them just does not seem a good fit to me.

BTW 'for-2.6.37' got https://patchwork.kernel.org/patch/145681/.



Regards,

-- 
Karl Beldan


From dedekind1 at gmail.com  Tue Oct 12 10:27:07 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 17:27:07 +0300
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
Message-ID: <1286893627.2164.65.camel@localhost>

On Tue, 2010-10-12 at 15:16 +0200, Karl Beldan wrote:
> On Mon, Oct 11, 2010 at 9:24 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
> >> Hi,
> >>
> >> I have been using this tweak for some time now, and I am getting tired of
> >> having to resort to it so often.
> >> It allows to pass such cmdline root as:
> >>  "root=mtdb:ubivolx rootfstype=squashfs"
> >> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
> >> for example, and I thought that this might initiate discussion.
> >>
> >> --
> >> Karl
> >>
> >> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
> >> ---
> >>  init/do_mounts.c |   15 +++++++++++++--
> >>  1 files changed, 13 insertions(+), 2 deletions(-)
> >
> > Dunno...
> >
> > First of all, if you have to do this, let it be mtdblock, not mtdb - no
> > need to breed aliases.
> >
> > But how about teaching squashfs to understand mtdX and mtd:name syntax
> > instead?
> >
> 
> Hi Artem,
> 
> I would not do that, squashfs and co just ask for a block device, putting mtdx
> syntax awareness in each of them just does not seem a good fit to me.

Right. But the same arguments applies to do_mounts.c which you hack:
mtdblock is just a block device, putting awareness of specific types of
block devices is not a good thing to do.

May be this is why I'm not too happy about your patch?

> BTW 'for-2.6.37' got https://patchwork.kernel.org/patch/145681/.

Yeah, it is better to have a generic approach which can be applied to
all block devices. Make UUID of your mtdblock to be equivalent to the
name of the underlying mtd device and you are done: use
PARTUUID=<mtd_device_name>. Right?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From karl.beldan at gmail.com  Tue Oct 12 11:11:27 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Tue, 12 Oct 2010 17:11:27 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <1286893627.2164.65.camel@localhost>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
	<1286893627.2164.65.camel@localhost>
Message-ID: <AANLkTikghhYSDY=EamGvPpWfc_FqBrBw7Ua6jnO8Xx+q@mail.gmail.com>

On Tue, Oct 12, 2010 at 4:27 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2010-10-12 at 15:16 +0200, Karl Beldan wrote:
>> On Mon, Oct 11, 2010 at 9:24 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
>> >> Hi,
>> >>
>> >> I have been using this tweak for some time now, and I am getting tired of
>> >> having to resort to it so often.
>> >> It allows to pass such cmdline root as:
>> >> ?"root=mtdb:ubivolx rootfstype=squashfs"
>> >> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
>> >> for example, and I thought that this might initiate discussion.
>> >>
>> >> --
>> >> Karl
>> >>
>> >> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
>> >> ---
>> >> ?init/do_mounts.c | ? 15 +++++++++++++--
>> >> ?1 files changed, 13 insertions(+), 2 deletions(-)
>> >
>> > Dunno...
>> >
>> > First of all, if you have to do this, let it be mtdblock, not mtdb - no
>> > need to breed aliases.
>> >
>> > But how about teaching squashfs to understand mtdX and mtd:name syntax
>> > instead?
>> >
>>
>> Hi Artem,
>>
>> I would not do that, squashfs and co just ask for a block device, putting mtdx
>> syntax awareness in each of them just does not seem a good fit to me.
>
> Right. But the same arguments applies to do_mounts.c which you hack:
To a far lesser extent, moreover do_mounts has similar hacks in that
regard, plus doing
this into squashfs you would have to do it everywhere else (e.g cramfs).
I just cannot agree, sorry.

> mtdblock is just a block device, putting awareness of specific types of
> block devices is not a good thing to do.
>
That was my point when you suggested hacking into squashfs to add mtd
names awareness.

> May be this is why I'm not too happy about your patch?
>
Neither am I, hence the way I tackled the matter.
This tweak, as I introduced it, is here to get better feedback.

>> BTW 'for-2.6.37' got https://patchwork.kernel.org/patch/145681/.
>
> Yeah, it is better to have a generic approach which can be applied to
> all block devices. Make UUID of your mtdblock to be equivalent to the
> name of the underlying mtd device and you are done: use
> PARTUUID=<mtd_device_name>. Right?
>
I put that link to bring back the discussion around something I would
more stick to
 as I anticipated the taste of the reply.

Maybe we'll come easierly to a way of handling this matter with 'next-'s.
Though the mtd subsystem is probably one that would benefit from such
a name scheme,
the solution is on its way to come from another subsystem.

Thanks,

-- 
Karl


From dedekind1 at gmail.com  Tue Oct 12 11:27:28 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 12 Oct 2010 18:27:28 +0300
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <AANLkTikghhYSDY=EamGvPpWfc_FqBrBw7Ua6jnO8Xx+q@mail.gmail.com>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
	<1286893627.2164.65.camel@localhost>
	<AANLkTikghhYSDY=EamGvPpWfc_FqBrBw7Ua6jnO8Xx+q@mail.gmail.com>
Message-ID: <1286897248.1742.28.camel@brekeke>

On Tue, 2010-10-12 at 17:11 +0200, Karl Beldan wrote:
> On Tue, Oct 12, 2010 at 4:27 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Tue, 2010-10-12 at 15:16 +0200, Karl Beldan wrote:
> >> On Mon, Oct 11, 2010 at 9:24 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >> > On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
> >> >> Hi,
> >> >>
> >> >> I have been using this tweak for some time now, and I am getting tired of
> >> >> having to resort to it so often.
> >> >> It allows to pass such cmdline root as:
> >> >>  "root=mtdb:ubivolx rootfstype=squashfs"
> >> >> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
> >> >> for example, and I thought that this might initiate discussion.
> >> >>
> >> >> --
> >> >> Karl
> >> >>
> >> >> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
> >> >> ---
> >> >>  init/do_mounts.c |   15 +++++++++++++--
> >> >>  1 files changed, 13 insertions(+), 2 deletions(-)
> >> >
> >> > Dunno...
> >> >
> >> > First of all, if you have to do this, let it be mtdblock, not mtdb - no
> >> > need to breed aliases.
> >> >
> >> > But how about teaching squashfs to understand mtdX and mtd:name syntax
> >> > instead?
> >> >
> >>
> >> Hi Artem,
> >>
> >> I would not do that, squashfs and co just ask for a block device, putting mtdx
> >> syntax awareness in each of them just does not seem a good fit to me.
> >
> > Right. But the same arguments applies to do_mounts.c which you hack:
> To a far lesser extent, moreover do_mounts has similar hacks in that
> regard, plus doing
> this into squashfs you would have to do it everywhere else (e.g cramfs).
> I just cannot agree, sorry.

No, they are not similar. They are for devices of different type, not
for _block_ devices. So those are about adding base support for MTD and
UBI devices.

In your case this is about block devices, which are already supported.
What you do is you say - mtd block devices are very special, they should
have own hack. Why not scsii block devices or any other types?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From karl.beldan at gmail.com  Tue Oct 12 11:51:38 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Tue, 12 Oct 2010 17:51:38 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <1286897248.1742.28.camel@brekeke>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
	<1286893627.2164.65.camel@localhost>
	<AANLkTikghhYSDY=EamGvPpWfc_FqBrBw7Ua6jnO8Xx+q@mail.gmail.com>
	<1286897248.1742.28.camel@brekeke>
Message-ID: <AANLkTimoFbf9Y9q4u32uFi8wvORsS6RFjY2P4MRmRNFZ@mail.gmail.com>

On Tue, Oct 12, 2010 at 5:27 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2010-10-12 at 17:11 +0200, Karl Beldan wrote:
>> On Tue, Oct 12, 2010 at 4:27 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > On Tue, 2010-10-12 at 15:16 +0200, Karl Beldan wrote:
>> >> On Mon, Oct 11, 2010 at 9:24 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> >> > On Wed, 2010-10-06 at 23:02 +0200, Karl Beldan wrote:
>> >> >> Hi,
>> >> >>
>> >> >> I have been using this tweak for some time now, and I am getting tired of
>> >> >> having to resort to it so often.
>> >> >> It allows to pass such cmdline root as:
>> >> >> ?"root=mtdb:ubivolx rootfstype=squashfs"
>> >> >> I am pretty sure many people use squashfs/cramfs filesystems on top of nand,
>> >> >> for example, and I thought that this might initiate discussion.
>> >> >>
>> >> >> --
>> >> >> Karl
>> >> >>
>> >> >> Signed-off-by: Karl Beldan <karl.beldan at gmail.com>
>> >> >> ---
>> >> >> ?init/do_mounts.c | ? 15 +++++++++++++--
>> >> >> ?1 files changed, 13 insertions(+), 2 deletions(-)
>> >> >
>> >> > Dunno...
>> >> >
>> >> > First of all, if you have to do this, let it be mtdblock, not mtdb - no
>> >> > need to breed aliases.
>> >> >
>> >> > But how about teaching squashfs to understand mtdX and mtd:name syntax
>> >> > instead?
>> >> >
>> >>
>> >> Hi Artem,
>> >>
>> >> I would not do that, squashfs and co just ask for a block device, putting mtdx
>> >> syntax awareness in each of them just does not seem a good fit to me.
>> >
>> > Right. But the same arguments applies to do_mounts.c which you hack:
>> To a far lesser extent, moreover do_mounts has similar hacks in that
>> regard, plus doing
>> this into squashfs you would have to do it everywhere else (e.g cramfs).
>> I just cannot agree, sorry.
>
> No, they are not similar. They are for devices of different type, not
> for _block_ devices. So those are about adding base support for MTD and
> UBI devices.
>
Well, I don't disagree with this one.

> In your case this is about block devices, which are already supported.
> What you do is you say - mtd block devices are very special, they should
> have own hack. Why not scsii block devices or any other types?
>
I am just throwing light on _a_ blatant example of the need of such
name handling.
My pointing you towards https://patchwork.kernel.org/patch/145681/,
which discusses uuids,
is explicit enough to show the pb this tweak addresses goes beyond mtd
block devices.
Said otherwise, pointing to the above patchwork patch was like 'please
don't go ''you are
assuming mtd block devices are very special'', see I checked other
people had similar issues
with different devices'.
Please, assume my pointing to the above patchwork is very
intentionnal, so that you do not
assume an 'a priori' misunderstanding nor mistake what is being discussed.


-- 
Karl


From mason at postdiluvian.org  Tue Oct 12 12:05:45 2010
From: mason at postdiluvian.org (Mark Mason)
Date: Tue, 12 Oct 2010 12:05:45 -0400
Subject: Scheduler latency problems when using NAND
In-Reply-To: <4CB39590.3070404@call-direct.com.au>
References: <20100929221401.GA32583@postdiluvian.org>
	<4CA3D92E.9060109@call-direct.com.au>
	<20101009174246.GA19591@postdiluvian.org>
	<4CB39590.3070404@call-direct.com.au>
Message-ID: <20101012160544.GB16683@postdiluvian.org>

Iwo Mergler <iwo at call-direct.com.au> wrote:

> Mark Mason wrote:
>
> > What I see on a logic analyzer is the BUSY line held by the flash for
> > 200us, a single 32 bit read of the video chip (broken up into two 16
> > bit reads for the 16 bit bus), then another 200us BUSY from the flash,
> > two more 16 bit reads, etc, all the way to the end of the logic
> > analyzer screen.
> 
> I don't know your controller, but I'm surprised that the FLASH write
> can stall the bus like that. It seems a high price to pay for not
> having to implement some FLASH write interrupt or wait. Are you sure
> that this is the recommended way to connect a FLASH?

I don't think it's the controller's fault, it's a signal provided by
the flash, and its purpose is to hold off the controller while the
NAND is busy.  It seems strange that the signal remains asserted when
the chip isn't selected, but if it didn't then the controller would
have to poll the chip by periodically selecting the chip and see if
BUSY had deasserted.  The controller, running in flash mode, requires
the BUSY line to work.

A saner approach might be to connect the BUSY line to an interrupt,
and have the interrupt wake the NAND BGT up, but it's too late for
that now, since the hardware's already built.

Usually NAND is used for things like booting, config and log files,
etc, which is just 200us every now and then, so this wouldn't be a
problem.  It's only a problem since we need really high bandwidth to
the flash.

I got a fast reply from Freescale - this is the way it works and there
is no workaround.

I'll try shutting the FCM off and acccessing the device as a plain
memory device.

Thanks for the help!


From scetin at mersin.edu.tr  Tue Oct 12 11:38:33 2010
From: scetin at mersin.edu.tr (=?utf-8?Q?Dr_Sibel_=C3=87etin?=)
Date: Tue, 12 Oct 2010 18:38:33 +0300 (EEST)
Subject: No subject
Message-ID: <788181025.45019.1286897913751.JavaMail.root@mail.mersin.edu.tr>



Mrs Cole told me to send you this mail stating that you should contact Her Lawyer. She told me this in the past weeks before she had gone into a state of Comma in the Hospital I almost forgot but please don't be angry with me not doing the only thing she asked of me please contact Her Lawyer through the below details.Name ? ?Barrister Morgan Owen? ? ? ? ? ? ?barr.owen at gala.net


From grant.likely at secretlab.ca  Tue Oct 12 23:40:41 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Tue, 12 Oct 2010 21:40:41 -0600
Subject: [PATCH v4 1/5] spi/mpc8xxx: rename spi_mpc8xxx.c to spi_fsl_spi.c
In-Reply-To: <1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101013034041.GA7254@angua.secretlab.ca>

On Tue, Oct 12, 2010 at 06:18:30PM +0800, Mingkai Hu wrote:
> This will pave the way to refactor out the common code which can be used
> by the eSPI controller driver, and rename the SPI controller dirver to the
> file spi_fsl_spi.c.
> 
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>

Applied, thanks.

g.

> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
> 
>  drivers/spi/Kconfig       |    9 +-
>  drivers/spi/Makefile      |    2 +-
>  drivers/spi/spi_fsl_spi.c | 1425 +++++++++++++++++++++++++++++++++++++++++++++
>  drivers/spi/spi_mpc8xxx.c | 1425 ---------------------------------------------
>  4 files changed, 1431 insertions(+), 1430 deletions(-)
>  create mode 100644 drivers/spi/spi_fsl_spi.c
>  delete mode 100644 drivers/spi/spi_mpc8xxx.c
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 91c2f4f..6af34c6 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -182,12 +182,13 @@ config SPI_MPC512x_PSC
>  	  This enables using the Freescale MPC5121 Programmable Serial
>  	  Controller in SPI master mode.
>  
> -config SPI_MPC8xxx
> -	tristate "Freescale MPC8xxx SPI controller"
> +config SPI_FSL_SPI
> +	tristate "Freescale SPI controller"
>  	depends on FSL_SOC
>  	help
> -	  This enables using the Freescale MPC8xxx SPI controllers in master
> -	  mode.
> +	  This enables using the Freescale SPI controllers in master mode.
> +	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
> +	  MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
>  
>  config SPI_OMAP_UWIRE
>  	tristate "OMAP1 MicroWire"
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index e9cbd18..770817c 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -34,7 +34,7 @@ obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
>  obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
> -obj-$(CONFIG_SPI_MPC8xxx)		+= spi_mpc8xxx.o
> +obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
>  obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
>  obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
>  obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
> diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
> new file mode 100644
> index 0000000..1dd86b8
> --- /dev/null
> +++ b/drivers/spi/spi_fsl_spi.c
> @@ -0,0 +1,1425 @@
> +/*
> + * MPC8xxx SPI controller driver.
> + *
> + * Maintainer: Kumar Gala
> + *
> + * Copyright (C) 2006 Polycom, Inc.
> + *
> + * CPM SPI and QE buffer descriptors mode support:
> + * Copyright (c) 2009  MontaVista Software, Inc.
> + * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/bug.h>
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/completion.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/device.h>
> +#include <linux/spi/spi.h>
> +#include <linux/spi/spi_bitbang.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mm.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/slab.h>
> +
> +#include <sysdev/fsl_soc.h>
> +#include <asm/cpm.h>
> +#include <asm/qe.h>
> +#include <asm/irq.h>
> +
> +/* CPM1 and CPM2 are mutually exclusive. */
> +#ifdef CONFIG_CPM1
> +#include <asm/cpm1.h>
> +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
> +#else
> +#include <asm/cpm2.h>
> +#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
> +#endif
> +
> +/* SPI Controller registers */
> +struct mpc8xxx_spi_reg {
> +	u8 res1[0x20];
> +	__be32 mode;
> +	__be32 event;
> +	__be32 mask;
> +	__be32 command;
> +	__be32 transmit;
> +	__be32 receive;
> +};
> +
> +/* SPI Controller mode register definitions */
> +#define	SPMODE_LOOP		(1 << 30)
> +#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
> +#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
> +#define	SPMODE_DIV16		(1 << 27)
> +#define	SPMODE_REV		(1 << 26)
> +#define	SPMODE_MS		(1 << 25)
> +#define	SPMODE_ENABLE		(1 << 24)
> +#define	SPMODE_LEN(x)		((x) << 20)
> +#define	SPMODE_PM(x)		((x) << 16)
> +#define	SPMODE_OP		(1 << 14)
> +#define	SPMODE_CG(x)		((x) << 7)
> +
> +/*
> + * Default for SPI Mode:
> + * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
> + */
> +#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
> +			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
> +
> +/* SPIE register values */
> +#define	SPIE_NE		0x00000200	/* Not empty */
> +#define	SPIE_NF		0x00000100	/* Not full */
> +
> +/* SPIM register values */
> +#define	SPIM_NE		0x00000200	/* Not empty */
> +#define	SPIM_NF		0x00000100	/* Not full */
> +
> +#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
> +#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
> +
> +/* SPCOM register values */
> +#define	SPCOM_STR	(1 << 23)	/* Start transmit */
> +
> +#define	SPI_PRAM_SIZE	0x100
> +#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
> +
> +/* SPI Controller driver's private data. */
> +struct mpc8xxx_spi {
> +	struct device *dev;
> +	struct mpc8xxx_spi_reg __iomem *base;
> +
> +	/* rx & tx bufs from the spi_transfer */
> +	const void *tx;
> +	void *rx;
> +
> +	int subblock;
> +	struct spi_pram __iomem *pram;
> +	struct cpm_buf_desc __iomem *tx_bd;
> +	struct cpm_buf_desc __iomem *rx_bd;
> +
> +	struct spi_transfer *xfer_in_progress;
> +
> +	/* dma addresses for CPM transfers */
> +	dma_addr_t tx_dma;
> +	dma_addr_t rx_dma;
> +	bool map_tx_dma;
> +	bool map_rx_dma;
> +
> +	dma_addr_t dma_dummy_tx;
> +	dma_addr_t dma_dummy_rx;
> +
> +	/* functions to deal with different sized buffers */
> +	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> +	u32(*get_tx) (struct mpc8xxx_spi *);
> +
> +	unsigned int count;
> +	unsigned int irq;
> +
> +	unsigned nsecs;		/* (clock cycle time)/2 */
> +
> +	u32 spibrg;		/* SPIBRG input clock */
> +	u32 rx_shift;		/* RX data reg shift when in qe mode */
> +	u32 tx_shift;		/* TX data reg shift when in qe mode */
> +
> +	unsigned int flags;
> +
> +	struct workqueue_struct *workqueue;
> +	struct work_struct work;
> +
> +	struct list_head queue;
> +	spinlock_t lock;
> +
> +	struct completion done;
> +};
> +
> +static void *mpc8xxx_dummy_rx;
> +static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
> +static int mpc8xxx_dummy_rx_refcnt;
> +
> +struct spi_mpc8xxx_cs {
> +	/* functions to deal with different sized buffers */
> +	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> +	u32 (*get_tx) (struct mpc8xxx_spi *);
> +	u32 rx_shift;		/* RX data reg shift when in qe mode */
> +	u32 tx_shift;		/* TX data reg shift when in qe mode */
> +	u32 hw_mode;		/* Holds HW mode register settings */
> +};
> +
> +static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
> +{
> +	out_be32(reg, val);
> +}
> +
> +static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
> +{
> +	return in_be32(reg);
> +}
> +
> +#define MPC83XX_SPI_RX_BUF(type) 					  \
> +static									  \
> +void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
> +{									  \
> +	type *rx = mpc8xxx_spi->rx;					  \
> +	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
> +	mpc8xxx_spi->rx = rx;						  \
> +}
> +
> +#define MPC83XX_SPI_TX_BUF(type)				\
> +static								\
> +u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
> +{								\
> +	u32 data;						\
> +	const type *tx = mpc8xxx_spi->tx;			\
> +	if (!tx)						\
> +		return 0;					\
> +	data = *tx++ << mpc8xxx_spi->tx_shift;			\
> +	mpc8xxx_spi->tx = tx;					\
> +	return data;						\
> +}
> +
> +MPC83XX_SPI_RX_BUF(u8)
> +MPC83XX_SPI_RX_BUF(u16)
> +MPC83XX_SPI_RX_BUF(u32)
> +MPC83XX_SPI_TX_BUF(u8)
> +MPC83XX_SPI_TX_BUF(u16)
> +MPC83XX_SPI_TX_BUF(u32)
> +
> +static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> +	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> +	__be32 __iomem *mode = &mspi->base->mode;
> +	unsigned long flags;
> +
> +	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
> +		return;
> +
> +	/* Turn off IRQs locally to minimize time that SPI is disabled. */
> +	local_irq_save(flags);
> +
> +	/* Turn off SPI unit prior changing mode */
> +	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
> +
> +	/* When in CPM mode, we need to reinit tx and rx. */
> +	if (mspi->flags & SPI_CPM_MODE) {
> +		if (mspi->flags & SPI_QE) {
> +			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
> +				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
> +		} else {
> +			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
> +			if (mspi->flags & SPI_CPM1) {
> +				out_be16(&mspi->pram->rbptr,
> +					 in_be16(&mspi->pram->rbase));
> +				out_be16(&mspi->pram->tbptr,
> +					 in_be16(&mspi->pram->tbase));
> +			}
> +		}
> +	}
> +	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> +	local_irq_restore(flags);
> +}
> +
> +static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
> +	bool pol = spi->mode & SPI_CS_HIGH;
> +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> +
> +	if (value == BITBANG_CS_INACTIVE) {
> +		if (pdata->cs_control)
> +			pdata->cs_control(spi, !pol);
> +	}
> +
> +	if (value == BITBANG_CS_ACTIVE) {
> +		mpc8xxx_spi->rx_shift = cs->rx_shift;
> +		mpc8xxx_spi->tx_shift = cs->tx_shift;
> +		mpc8xxx_spi->get_rx = cs->get_rx;
> +		mpc8xxx_spi->get_tx = cs->get_tx;
> +
> +		mpc8xxx_spi_change_mode(spi);
> +
> +		if (pdata->cs_control)
> +			pdata->cs_control(spi, pol);
> +	}
> +}
> +
> +static int
> +mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
> +			   struct spi_device *spi,
> +			   struct mpc8xxx_spi *mpc8xxx_spi,
> +			   int bits_per_word)
> +{
> +	cs->rx_shift = 0;
> +	cs->tx_shift = 0;
> +	if (bits_per_word <= 8) {
> +		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
> +		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
> +		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> +			cs->rx_shift = 16;
> +			cs->tx_shift = 24;
> +		}
> +	} else if (bits_per_word <= 16) {
> +		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
> +		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
> +		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> +			cs->rx_shift = 16;
> +			cs->tx_shift = 16;
> +		}
> +	} else if (bits_per_word <= 32) {
> +		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> +		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> +	} else
> +		return -EINVAL;
> +
> +	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
> +	    spi->mode & SPI_LSB_FIRST) {
> +		cs->tx_shift = 0;
> +		if (bits_per_word <= 8)
> +			cs->rx_shift = 8;
> +		else
> +			cs->rx_shift = 0;
> +	}
> +	mpc8xxx_spi->rx_shift = cs->rx_shift;
> +	mpc8xxx_spi->tx_shift = cs->tx_shift;
> +	mpc8xxx_spi->get_rx = cs->get_rx;
> +	mpc8xxx_spi->get_tx = cs->get_tx;
> +
> +	return bits_per_word;
> +}
> +
> +static int
> +mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
> +			  struct spi_device *spi,
> +			  int bits_per_word)
> +{
> +	/* QE uses Little Endian for words > 8
> +	 * so transform all words > 8 into 8 bits
> +	 * Unfortnatly that doesn't work for LSB so
> +	 * reject these for now */
> +	/* Note: 32 bits word, LSB works iff
> +	 * tfcr/rfcr is set to CPMFCR_GBL */
> +	if (spi->mode & SPI_LSB_FIRST &&
> +	    bits_per_word > 8)
> +		return -EINVAL;
> +	if (bits_per_word > 8)
> +		return 8; /* pretend its 8 bits */
> +	return bits_per_word;
> +}
> +
> +static
> +int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	int bits_per_word;
> +	u8 pm;
> +	u32 hz;
> +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> +
> +	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +
> +	if (t) {
> +		bits_per_word = t->bits_per_word;
> +		hz = t->speed_hz;
> +	} else {
> +		bits_per_word = 0;
> +		hz = 0;
> +	}
> +
> +	/* spi_transfer level calls that work per-word */
> +	if (!bits_per_word)
> +		bits_per_word = spi->bits_per_word;
> +
> +	/* Make sure its a bit width we support [4..16, 32] */
> +	if ((bits_per_word < 4)
> +	    || ((bits_per_word > 16) && (bits_per_word != 32)))
> +		return -EINVAL;
> +
> +	if (!hz)
> +		hz = spi->max_speed_hz;
> +
> +	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
> +		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
> +							   mpc8xxx_spi,
> +							   bits_per_word);
> +	else if (mpc8xxx_spi->flags & SPI_QE)
> +		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
> +							  bits_per_word);
> +
> +	if (bits_per_word < 0)
> +		return bits_per_word;
> +
> +	if (bits_per_word == 32)
> +		bits_per_word = 0;
> +	else
> +		bits_per_word = bits_per_word - 1;
> +
> +	/* mask out bits we are going to set */
> +	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
> +				  | SPMODE_PM(0xF));
> +
> +	cs->hw_mode |= SPMODE_LEN(bits_per_word);
> +
> +	if ((mpc8xxx_spi->spibrg / hz) > 64) {
> +		cs->hw_mode |= SPMODE_DIV16;
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> +
> +		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
> +			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
> +			  hz, mpc8xxx_spi->spibrg / 1024);
> +		if (pm > 16)
> +			pm = 16;
> +	} else
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> +	if (pm)
> +		pm--;
> +
> +	cs->hw_mode |= SPMODE_PM(pm);
> +
> +	mpc8xxx_spi_change_mode(spi);
> +	return 0;
> +}
> +
> +static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
> +{
> +	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
> +	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
> +	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
> +	unsigned int xfer_ofs;
> +
> +	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
> +
> +	if (mspi->rx_dma == mspi->dma_dummy_rx)
> +		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
> +	else
> +		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
> +	out_be16(&rx_bd->cbd_datlen, 0);
> +	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
> +
> +	if (mspi->tx_dma == mspi->dma_dummy_tx)
> +		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
> +	else
> +		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
> +	out_be16(&tx_bd->cbd_datlen, xfer_len);
> +	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
> +				 BD_SC_LAST);
> +
> +	/* start transfer */
> +	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
> +}
> +
> +static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
> +				struct spi_transfer *t, bool is_dma_mapped)
> +{
> +	struct device *dev = mspi->dev;
> +
> +	if (is_dma_mapped) {
> +		mspi->map_tx_dma = 0;
> +		mspi->map_rx_dma = 0;
> +	} else {
> +		mspi->map_tx_dma = 1;
> +		mspi->map_rx_dma = 1;
> +	}
> +
> +	if (!t->tx_buf) {
> +		mspi->tx_dma = mspi->dma_dummy_tx;
> +		mspi->map_tx_dma = 0;
> +	}
> +
> +	if (!t->rx_buf) {
> +		mspi->rx_dma = mspi->dma_dummy_rx;
> +		mspi->map_rx_dma = 0;
> +	}
> +
> +	if (mspi->map_tx_dma) {
> +		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
> +
> +		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
> +					      DMA_TO_DEVICE);
> +		if (dma_mapping_error(dev, mspi->tx_dma)) {
> +			dev_err(dev, "unable to map tx dma\n");
> +			return -ENOMEM;
> +		}
> +	} else if (t->tx_buf) {
> +		mspi->tx_dma = t->tx_dma;
> +	}
> +
> +	if (mspi->map_rx_dma) {
> +		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
> +					      DMA_FROM_DEVICE);
> +		if (dma_mapping_error(dev, mspi->rx_dma)) {
> +			dev_err(dev, "unable to map rx dma\n");
> +			goto err_rx_dma;
> +		}
> +	} else if (t->rx_buf) {
> +		mspi->rx_dma = t->rx_dma;
> +	}
> +
> +	/* enable rx ints */
> +	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
> +
> +	mspi->xfer_in_progress = t;
> +	mspi->count = t->len;
> +
> +	/* start CPM transfers */
> +	mpc8xxx_spi_cpm_bufs_start(mspi);
> +
> +	return 0;
> +
> +err_rx_dma:
> +	if (mspi->map_tx_dma)
> +		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
> +	return -ENOMEM;
> +}
> +
> +static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
> +{
> +	struct device *dev = mspi->dev;
> +	struct spi_transfer *t = mspi->xfer_in_progress;
> +
> +	if (mspi->map_tx_dma)
> +		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
> +	if (mspi->map_rx_dma)
> +		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
> +	mspi->xfer_in_progress = NULL;
> +}
> +
> +static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
> +				struct spi_transfer *t, unsigned int len)
> +{
> +	u32 word;
> +
> +	mspi->count = len;
> +
> +	/* enable rx ints */
> +	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
> +
> +	/* transmit word */
> +	word = mspi->get_tx(mspi);
> +	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> +
> +	return 0;
> +}
> +
> +static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
> +			    bool is_dma_mapped)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	unsigned int len = t->len;
> +	u8 bits_per_word;
> +	int ret;
> +
> +	bits_per_word = spi->bits_per_word;
> +	if (t->bits_per_word)
> +		bits_per_word = t->bits_per_word;
> +
> +	if (bits_per_word > 8) {
> +		/* invalid length? */
> +		if (len & 1)
> +			return -EINVAL;
> +		len /= 2;
> +	}
> +	if (bits_per_word > 16) {
> +		/* invalid length? */
> +		if (len & 1)
> +			return -EINVAL;
> +		len /= 2;
> +	}
> +
> +	mpc8xxx_spi->tx = t->tx_buf;
> +	mpc8xxx_spi->rx = t->rx_buf;
> +
> +	INIT_COMPLETION(mpc8xxx_spi->done);
> +
> +	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> +		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
> +	else
> +		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
> +	if (ret)
> +		return ret;
> +
> +	wait_for_completion(&mpc8xxx_spi->done);
> +
> +	/* disable rx ints */
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> +
> +	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> +		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
> +
> +	return mpc8xxx_spi->count;
> +}
> +
> +static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
> +{
> +	struct spi_device *spi = m->spi;
> +	struct spi_transfer *t;
> +	unsigned int cs_change;
> +	const int nsecs = 50;
> +	int status;
> +
> +	cs_change = 1;
> +	status = 0;
> +	list_for_each_entry(t, &m->transfers, transfer_list) {
> +		if (t->bits_per_word || t->speed_hz) {
> +			/* Don't allow changes if CS is active */
> +			status = -EINVAL;
> +
> +			if (cs_change)
> +				status = mpc8xxx_spi_setup_transfer(spi, t);
> +			if (status < 0)
> +				break;
> +		}
> +
> +		if (cs_change) {
> +			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
> +			ndelay(nsecs);
> +		}
> +		cs_change = t->cs_change;
> +		if (t->len)
> +			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
> +		if (status) {
> +			status = -EMSGSIZE;
> +			break;
> +		}
> +		m->actual_length += t->len;
> +
> +		if (t->delay_usecs)
> +			udelay(t->delay_usecs);
> +
> +		if (cs_change) {
> +			ndelay(nsecs);
> +			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> +			ndelay(nsecs);
> +		}
> +	}
> +
> +	m->status = status;
> +	m->complete(m->context);
> +
> +	if (status || !cs_change) {
> +		ndelay(nsecs);
> +		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> +	}
> +
> +	mpc8xxx_spi_setup_transfer(spi, NULL);
> +}
> +
> +static void mpc8xxx_spi_work(struct work_struct *work)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
> +						       work);
> +
> +	spin_lock_irq(&mpc8xxx_spi->lock);
> +	while (!list_empty(&mpc8xxx_spi->queue)) {
> +		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
> +						   struct spi_message, queue);
> +
> +		list_del_init(&m->queue);
> +		spin_unlock_irq(&mpc8xxx_spi->lock);
> +
> +		mpc8xxx_spi_do_one_msg(m);
> +
> +		spin_lock_irq(&mpc8xxx_spi->lock);
> +	}
> +	spin_unlock_irq(&mpc8xxx_spi->lock);
> +}
> +
> +static int mpc8xxx_spi_setup(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	int retval;
> +	u32 hw_mode;
> +	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> +
> +	if (!spi->max_speed_hz)
> +		return -EINVAL;
> +
> +	if (!cs) {
> +		cs = kzalloc(sizeof *cs, GFP_KERNEL);
> +		if (!cs)
> +			return -ENOMEM;
> +		spi->controller_state = cs;
> +	}
> +	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +
> +	hw_mode = cs->hw_mode; /* Save original settings */
> +	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
> +	/* mask out bits we are going to set */
> +	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
> +			 | SPMODE_REV | SPMODE_LOOP);
> +
> +	if (spi->mode & SPI_CPHA)
> +		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
> +	if (spi->mode & SPI_CPOL)
> +		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
> +	if (!(spi->mode & SPI_LSB_FIRST))
> +		cs->hw_mode |= SPMODE_REV;
> +	if (spi->mode & SPI_LOOP)
> +		cs->hw_mode |= SPMODE_LOOP;
> +
> +	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
> +	if (retval < 0) {
> +		cs->hw_mode = hw_mode; /* Restore settings */
> +		return retval;
> +	}
> +	return 0;
> +}
> +
> +static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
> +{
> +	u16 len;
> +
> +	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
> +		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
> +
> +	len = in_be16(&mspi->rx_bd->cbd_datlen);
> +	if (len > mspi->count) {
> +		WARN_ON(1);
> +		len = mspi->count;
> +	}
> +
> +	/* Clear the events */
> +	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> +
> +	mspi->count -= len;
> +	if (mspi->count)
> +		mpc8xxx_spi_cpm_bufs_start(mspi);
> +	else
> +		complete(&mspi->done);
> +}
> +
> +static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
> +{
> +	/* We need handle RX first */
> +	if (events & SPIE_NE) {
> +		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
> +
> +		if (mspi->rx)
> +			mspi->get_rx(rx_data, mspi);
> +	}
> +
> +	if ((events & SPIE_NF) == 0)
> +		/* spin until TX is done */
> +		while (((events =
> +			mpc8xxx_spi_read_reg(&mspi->base->event)) &
> +						SPIE_NF) == 0)
> +			cpu_relax();
> +
> +	/* Clear the events */
> +	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> +
> +	mspi->count -= 1;
> +	if (mspi->count) {
> +		u32 word = mspi->get_tx(mspi);
> +
> +		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> +	} else {
> +		complete(&mspi->done);
> +	}
> +}
> +
> +static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
> +{
> +	struct mpc8xxx_spi *mspi = context_data;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 events;
> +
> +	/* Get interrupt events(tx/rx) */
> +	events = mpc8xxx_spi_read_reg(&mspi->base->event);
> +	if (events)
> +		ret = IRQ_HANDLED;
> +
> +	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
> +
> +	if (mspi->flags & SPI_CPM_MODE)
> +		mpc8xxx_spi_cpm_irq(mspi, events);
> +	else
> +		mpc8xxx_spi_cpu_irq(mspi, events);
> +
> +	return ret;
> +}
> +
> +static int mpc8xxx_spi_transfer(struct spi_device *spi,
> +				struct spi_message *m)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	unsigned long flags;
> +
> +	m->actual_length = 0;
> +	m->status = -EINPROGRESS;
> +
> +	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
> +	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
> +	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
> +	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
> +
> +	return 0;
> +}
> +
> +
> +static void mpc8xxx_spi_cleanup(struct spi_device *spi)
> +{
> +	kfree(spi->controller_state);
> +}
> +
> +static void *mpc8xxx_spi_alloc_dummy_rx(void)
> +{
> +	mutex_lock(&mpc8xxx_dummy_rx_lock);
> +
> +	if (!mpc8xxx_dummy_rx)
> +		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
> +	if (mpc8xxx_dummy_rx)
> +		mpc8xxx_dummy_rx_refcnt++;
> +
> +	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> +
> +	return mpc8xxx_dummy_rx;
> +}
> +
> +static void mpc8xxx_spi_free_dummy_rx(void)
> +{
> +	mutex_lock(&mpc8xxx_dummy_rx_lock);
> +
> +	switch (mpc8xxx_dummy_rx_refcnt) {
> +	case 0:
> +		WARN_ON(1);
> +		break;
> +	case 1:
> +		kfree(mpc8xxx_dummy_rx);
> +		mpc8xxx_dummy_rx = NULL;
> +		/* fall through */
> +	default:
> +		mpc8xxx_dummy_rx_refcnt--;
> +		break;
> +	}
> +
> +	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> +}
> +
> +static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
> +{
> +	struct device *dev = mspi->dev;
> +	struct device_node *np = dev->of_node;
> +	const u32 *iprop;
> +	int size;
> +	unsigned long spi_base_ofs;
> +	unsigned long pram_ofs = -ENOMEM;
> +
> +	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
> +	iprop = of_get_property(np, "reg", &size);
> +
> +	/* QE with a fixed pram location? */
> +	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
> +		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
> +
> +	/* QE but with a dynamic pram location? */
> +	if (mspi->flags & SPI_QE) {
> +		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
> +		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
> +				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
> +		return pram_ofs;
> +	}
> +
> +	/* CPM1 and CPM2 pram must be at a fixed addr. */
> +	if (!iprop || size != sizeof(*iprop) * 4)
> +		return -ENOMEM;
> +
> +	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
> +	if (IS_ERR_VALUE(spi_base_ofs))
> +		return -ENOMEM;
> +
> +	if (mspi->flags & SPI_CPM2) {
> +		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
> +		if (!IS_ERR_VALUE(pram_ofs)) {
> +			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
> +
> +			out_be16(spi_base, pram_ofs);
> +		}
> +	} else {
> +		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
> +		u16 rpbase = in_be16(&pram->rpbase);
> +
> +		/* Microcode relocation patch applied? */
> +		if (rpbase)
> +			pram_ofs = rpbase;
> +		else
> +			return spi_base_ofs;
> +	}
> +
> +	cpm_muram_free(spi_base_ofs);
> +	return pram_ofs;
> +}
> +
> +static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
> +{
> +	struct device *dev = mspi->dev;
> +	struct device_node *np = dev->of_node;
> +	const u32 *iprop;
> +	int size;
> +	unsigned long pram_ofs;
> +	unsigned long bds_ofs;
> +
> +	if (!(mspi->flags & SPI_CPM_MODE))
> +		return 0;
> +
> +	if (!mpc8xxx_spi_alloc_dummy_rx())
> +		return -ENOMEM;
> +
> +	if (mspi->flags & SPI_QE) {
> +		iprop = of_get_property(np, "cell-index", &size);
> +		if (iprop && size == sizeof(*iprop))
> +			mspi->subblock = *iprop;
> +
> +		switch (mspi->subblock) {
> +		default:
> +			dev_warn(dev, "cell-index unspecified, assuming SPI1");
> +			/* fall through */
> +		case 0:
> +			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
> +			break;
> +		case 1:
> +			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
> +			break;
> +		}
> +	}
> +
> +	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
> +	if (IS_ERR_VALUE(pram_ofs)) {
> +		dev_err(dev, "can't allocate spi parameter ram\n");
> +		goto err_pram;
> +	}
> +
> +	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
> +				  sizeof(*mspi->rx_bd), 8);
> +	if (IS_ERR_VALUE(bds_ofs)) {
> +		dev_err(dev, "can't allocate bds\n");
> +		goto err_bds;
> +	}
> +
> +	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
> +					    DMA_TO_DEVICE);
> +	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
> +		dev_err(dev, "unable to map dummy tx buffer\n");
> +		goto err_dummy_tx;
> +	}
> +
> +	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
> +					    DMA_FROM_DEVICE);
> +	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
> +		dev_err(dev, "unable to map dummy rx buffer\n");
> +		goto err_dummy_rx;
> +	}
> +
> +	mspi->pram = cpm_muram_addr(pram_ofs);
> +
> +	mspi->tx_bd = cpm_muram_addr(bds_ofs);
> +	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
> +
> +	/* Initialize parameter ram. */
> +	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
> +	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
> +	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
> +	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
> +	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
> +	out_be32(&mspi->pram->rstate, 0);
> +	out_be32(&mspi->pram->rdp, 0);
> +	out_be16(&mspi->pram->rbptr, 0);
> +	out_be16(&mspi->pram->rbc, 0);
> +	out_be32(&mspi->pram->rxtmp, 0);
> +	out_be32(&mspi->pram->tstate, 0);
> +	out_be32(&mspi->pram->tdp, 0);
> +	out_be16(&mspi->pram->tbptr, 0);
> +	out_be16(&mspi->pram->tbc, 0);
> +	out_be32(&mspi->pram->txtmp, 0);
> +
> +	return 0;
> +
> +err_dummy_rx:
> +	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
> +err_dummy_tx:
> +	cpm_muram_free(bds_ofs);
> +err_bds:
> +	cpm_muram_free(pram_ofs);
> +err_pram:
> +	mpc8xxx_spi_free_dummy_rx();
> +	return -ENOMEM;
> +}
> +
> +static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
> +{
> +	struct device *dev = mspi->dev;
> +
> +	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
> +	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
> +	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
> +	cpm_muram_free(cpm_muram_offset(mspi->pram));
> +	mpc8xxx_spi_free_dummy_rx();
> +}
> +
> +static const char *mpc8xxx_spi_strmode(unsigned int flags)
> +{
> +	if (flags & SPI_QE_CPU_MODE) {
> +		return "QE CPU";
> +	} else if (flags & SPI_CPM_MODE) {
> +		if (flags & SPI_QE)
> +			return "QE";
> +		else if (flags & SPI_CPM2)
> +			return "CPM2";
> +		else
> +			return "CPM1";
> +	}
> +	return "CPU";
> +}
> +
> +static struct spi_master * __devinit
> +mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
> +{
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct spi_master *master;
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	u32 regval;
> +	int ret = 0;
> +
> +	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
> +	if (master == NULL) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	dev_set_drvdata(dev, master);
> +
> +	/* the spi->mode bits understood by this driver: */
> +	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
> +			| SPI_LSB_FIRST | SPI_LOOP;
> +
> +	master->setup = mpc8xxx_spi_setup;
> +	master->transfer = mpc8xxx_spi_transfer;
> +	master->cleanup = mpc8xxx_spi_cleanup;
> +	master->dev.of_node = dev->of_node;
> +
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +	mpc8xxx_spi->dev = dev;
> +	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
> +	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
> +	mpc8xxx_spi->flags = pdata->flags;
> +	mpc8xxx_spi->spibrg = pdata->sysclk;
> +
> +	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
> +	if (ret)
> +		goto err_cpm_init;
> +
> +	mpc8xxx_spi->rx_shift = 0;
> +	mpc8xxx_spi->tx_shift = 0;
> +	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> +		mpc8xxx_spi->rx_shift = 16;
> +		mpc8xxx_spi->tx_shift = 24;
> +	}
> +
> +	init_completion(&mpc8xxx_spi->done);
> +
> +	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
> +	if (mpc8xxx_spi->base == NULL) {
> +		ret = -ENOMEM;
> +		goto err_ioremap;
> +	}
> +
> +	mpc8xxx_spi->irq = irq;
> +
> +	/* Register for SPI Interrupt */
> +	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
> +			  0, "mpc8xxx_spi", mpc8xxx_spi);
> +
> +	if (ret != 0)
> +		goto unmap_io;
> +
> +	master->bus_num = pdata->bus_num;
> +	master->num_chipselect = pdata->max_chipselect;
> +
> +	/* SPI controller initializations */
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
> +
> +	/* Enable SPI interface */
> +	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
> +	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
> +		regval |= SPMODE_OP;
> +
> +	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
> +	spin_lock_init(&mpc8xxx_spi->lock);
> +	init_completion(&mpc8xxx_spi->done);
> +	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
> +	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
> +
> +	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
> +		dev_name(master->dev.parent));
> +	if (mpc8xxx_spi->workqueue == NULL) {
> +		ret = -EBUSY;
> +		goto free_irq;
> +	}
> +
> +	ret = spi_register_master(master);
> +	if (ret < 0)
> +		goto unreg_master;
> +
> +	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
> +		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
> +
> +	return master;
> +
> +unreg_master:
> +	destroy_workqueue(mpc8xxx_spi->workqueue);
> +free_irq:
> +	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> +unmap_io:
> +	iounmap(mpc8xxx_spi->base);
> +err_ioremap:
> +	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> +err_cpm_init:
> +	spi_master_put(master);
> +err:
> +	return ERR_PTR(ret);
> +}
> +
> +static int __devexit mpc8xxx_spi_remove(struct device *dev)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct spi_master *master;
> +
> +	master = dev_get_drvdata(dev);
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +
> +	flush_workqueue(mpc8xxx_spi->workqueue);
> +	destroy_workqueue(mpc8xxx_spi->workqueue);
> +	spi_unregister_master(master);
> +
> +	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> +	iounmap(mpc8xxx_spi->base);
> +	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> +
> +	return 0;
> +}
> +
> +struct mpc8xxx_spi_probe_info {
> +	struct fsl_spi_platform_data pdata;
> +	int *gpios;
> +	bool *alow_flags;
> +};
> +
> +static struct mpc8xxx_spi_probe_info *
> +to_of_pinfo(struct fsl_spi_platform_data *pdata)
> +{
> +	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
> +}
> +
> +static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
> +{
> +	struct device *dev = spi->dev.parent;
> +	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
> +	u16 cs = spi->chip_select;
> +	int gpio = pinfo->gpios[cs];
> +	bool alow = pinfo->alow_flags[cs];
> +
> +	gpio_set_value(gpio, on ^ alow);
> +}
> +
> +static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
> +	unsigned int ngpios;
> +	int i = 0;
> +	int ret;
> +
> +	ngpios = of_gpio_count(np);
> +	if (!ngpios) {
> +		/*
> +		 * SPI w/o chip-select line. One SPI device is still permitted
> +		 * though.
> +		 */
> +		pdata->max_chipselect = 1;
> +		return 0;
> +	}
> +
> +	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
> +	if (!pinfo->gpios)
> +		return -ENOMEM;
> +	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
> +
> +	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
> +				    GFP_KERNEL);
> +	if (!pinfo->alow_flags) {
> +		ret = -ENOMEM;
> +		goto err_alloc_flags;
> +	}
> +
> +	for (; i < ngpios; i++) {
> +		int gpio;
> +		enum of_gpio_flags flags;
> +
> +		gpio = of_get_gpio_flags(np, i, &flags);
> +		if (!gpio_is_valid(gpio)) {
> +			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
> +			ret = gpio;
> +			goto err_loop;
> +		}
> +
> +		ret = gpio_request(gpio, dev_name(dev));
> +		if (ret) {
> +			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
> +			goto err_loop;
> +		}
> +
> +		pinfo->gpios[i] = gpio;
> +		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
> +
> +		ret = gpio_direction_output(pinfo->gpios[i],
> +					    pinfo->alow_flags[i]);
> +		if (ret) {
> +			dev_err(dev, "can't set output direction for gpio "
> +				"#%d: %d\n", i, ret);
> +			goto err_loop;
> +		}
> +	}
> +
> +	pdata->max_chipselect = ngpios;
> +	pdata->cs_control = mpc8xxx_spi_cs_control;
> +
> +	return 0;
> +
> +err_loop:
> +	while (i >= 0) {
> +		if (gpio_is_valid(pinfo->gpios[i]))
> +			gpio_free(pinfo->gpios[i]);
> +		i--;
> +	}
> +
> +	kfree(pinfo->alow_flags);
> +	pinfo->alow_flags = NULL;
> +err_alloc_flags:
> +	kfree(pinfo->gpios);
> +	pinfo->gpios = NULL;
> +	return ret;
> +}
> +
> +static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
> +{
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
> +	int i;
> +
> +	if (!pinfo->gpios)
> +		return 0;
> +
> +	for (i = 0; i < pdata->max_chipselect; i++) {
> +		if (gpio_is_valid(pinfo->gpios[i]))
> +			gpio_free(pinfo->gpios[i]);
> +	}
> +
> +	kfree(pinfo->gpios);
> +	kfree(pinfo->alow_flags);
> +	return 0;
> +}
> +
> +static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
> +					  const struct of_device_id *ofid)
> +{
> +	struct device *dev = &ofdev->dev;
> +	struct device_node *np = ofdev->dev.of_node;
> +	struct mpc8xxx_spi_probe_info *pinfo;
> +	struct fsl_spi_platform_data *pdata;
> +	struct spi_master *master;
> +	struct resource mem;
> +	struct resource irq;
> +	const void *prop;
> +	int ret = -ENOMEM;
> +
> +	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
> +	if (!pinfo)
> +		return -ENOMEM;
> +
> +	pdata = &pinfo->pdata;
> +	dev->platform_data = pdata;
> +
> +	/* Allocate bus num dynamically. */
> +	pdata->bus_num = -1;
> +
> +	/* SPI controller is either clocked from QE or SoC clock. */
> +	pdata->sysclk = get_brgfreq();
> +	if (pdata->sysclk == -1) {
> +		pdata->sysclk = fsl_get_sys_freq();
> +		if (pdata->sysclk == -1) {
> +			ret = -ENODEV;
> +			goto err_clk;
> +		}
> +	}
> +
> +	prop = of_get_property(np, "mode", NULL);
> +	if (prop && !strcmp(prop, "cpu-qe"))
> +		pdata->flags = SPI_QE_CPU_MODE;
> +	else if (prop && !strcmp(prop, "qe"))
> +		pdata->flags = SPI_CPM_MODE | SPI_QE;
> +	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
> +		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
> +	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
> +		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> +
> +	ret = of_mpc8xxx_spi_get_chipselects(dev);
> +	if (ret)
> +		goto err;
> +
> +	ret = of_address_to_resource(np, 0, &mem);
> +	if (ret)
> +		goto err;
> +
> +	ret = of_irq_to_resource(np, 0, &irq);
> +	if (!ret) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
> +	if (IS_ERR(master)) {
> +		ret = PTR_ERR(master);
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	of_mpc8xxx_spi_free_chipselects(dev);
> +err_clk:
> +	kfree(pinfo);
> +	return ret;
> +}
> +
> +static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
> +{
> +	int ret;
> +
> +	ret = mpc8xxx_spi_remove(&ofdev->dev);
> +	if (ret)
> +		return ret;
> +	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
> +	return 0;
> +}
> +
> +static const struct of_device_id of_mpc8xxx_spi_match[] = {
> +	{ .compatible = "fsl,spi" },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
> +
> +static struct of_platform_driver of_mpc8xxx_spi_driver = {
> +	.driver = {
> +		.name = "mpc8xxx_spi",
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_mpc8xxx_spi_match,
> +	},
> +	.probe		= of_mpc8xxx_spi_probe,
> +	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
> +};
> +
> +#ifdef CONFIG_MPC832x_RDB
> +/*
> + * 				XXX XXX XXX
> + * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
> + * only. The driver should go away soon, since newer MPC8323E-RDB's device
> + * tree can work with OpenFirmware driver. But for now we support old trees
> + * as well.
> + */
> +static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
> +{
> +	struct resource *mem;
> +	int irq;
> +	struct spi_master *master;
> +
> +	if (!pdev->dev.platform_data)
> +		return -EINVAL;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!mem)
> +		return -EINVAL;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq <= 0)
> +		return -EINVAL;
> +
> +	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
> +	if (IS_ERR(master))
> +		return PTR_ERR(master);
> +	return 0;
> +}
> +
> +static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
> +{
> +	return mpc8xxx_spi_remove(&pdev->dev);
> +}
> +
> +MODULE_ALIAS("platform:mpc8xxx_spi");
> +static struct platform_driver mpc8xxx_spi_driver = {
> +	.probe = plat_mpc8xxx_spi_probe,
> +	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
> +	.driver = {
> +		.name = "mpc8xxx_spi",
> +		.owner = THIS_MODULE,
> +	},
> +};
> +
> +static bool legacy_driver_failed;
> +
> +static void __init legacy_driver_register(void)
> +{
> +	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
> +}
> +
> +static void __exit legacy_driver_unregister(void)
> +{
> +	if (legacy_driver_failed)
> +		return;
> +	platform_driver_unregister(&mpc8xxx_spi_driver);
> +}
> +#else
> +static void __init legacy_driver_register(void) {}
> +static void __exit legacy_driver_unregister(void) {}
> +#endif /* CONFIG_MPC832x_RDB */
> +
> +static int __init mpc8xxx_spi_init(void)
> +{
> +	legacy_driver_register();
> +	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
> +}
> +
> +static void __exit mpc8xxx_spi_exit(void)
> +{
> +	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
> +	legacy_driver_unregister();
> +}
> +
> +module_init(mpc8xxx_spi_init);
> +module_exit(mpc8xxx_spi_exit);
> +
> +MODULE_AUTHOR("Kumar Gala");
> +MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c
> deleted file mode 100644
> index 1dd86b8..0000000
> --- a/drivers/spi/spi_mpc8xxx.c
> +++ /dev/null
> @@ -1,1425 +0,0 @@
> -/*
> - * MPC8xxx SPI controller driver.
> - *
> - * Maintainer: Kumar Gala
> - *
> - * Copyright (C) 2006 Polycom, Inc.
> - *
> - * CPM SPI and QE buffer descriptors mode support:
> - * Copyright (c) 2009  MontaVista Software, Inc.
> - * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> - *
> - * This program is free software; you can redistribute  it and/or modify it
> - * under  the terms of  the GNU General  Public License as published by the
> - * Free Software Foundation;  either version 2 of the  License, or (at your
> - * option) any later version.
> - */
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/types.h>
> -#include <linux/kernel.h>
> -#include <linux/bug.h>
> -#include <linux/errno.h>
> -#include <linux/err.h>
> -#include <linux/io.h>
> -#include <linux/completion.h>
> -#include <linux/interrupt.h>
> -#include <linux/delay.h>
> -#include <linux/irq.h>
> -#include <linux/device.h>
> -#include <linux/spi/spi.h>
> -#include <linux/spi/spi_bitbang.h>
> -#include <linux/platform_device.h>
> -#include <linux/fsl_devices.h>
> -#include <linux/dma-mapping.h>
> -#include <linux/mm.h>
> -#include <linux/mutex.h>
> -#include <linux/of.h>
> -#include <linux/of_platform.h>
> -#include <linux/gpio.h>
> -#include <linux/of_gpio.h>
> -#include <linux/slab.h>
> -
> -#include <sysdev/fsl_soc.h>
> -#include <asm/cpm.h>
> -#include <asm/qe.h>
> -#include <asm/irq.h>
> -
> -/* CPM1 and CPM2 are mutually exclusive. */
> -#ifdef CONFIG_CPM1
> -#include <asm/cpm1.h>
> -#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_CH_SPI, 0)
> -#else
> -#include <asm/cpm2.h>
> -#define CPM_SPI_CMD mk_cr_cmd(CPM_CR_SPI_PAGE, CPM_CR_SPI_SBLOCK, 0, 0)
> -#endif
> -
> -/* SPI Controller registers */
> -struct mpc8xxx_spi_reg {
> -	u8 res1[0x20];
> -	__be32 mode;
> -	__be32 event;
> -	__be32 mask;
> -	__be32 command;
> -	__be32 transmit;
> -	__be32 receive;
> -};
> -
> -/* SPI Controller mode register definitions */
> -#define	SPMODE_LOOP		(1 << 30)
> -#define	SPMODE_CI_INACTIVEHIGH	(1 << 29)
> -#define	SPMODE_CP_BEGIN_EDGECLK	(1 << 28)
> -#define	SPMODE_DIV16		(1 << 27)
> -#define	SPMODE_REV		(1 << 26)
> -#define	SPMODE_MS		(1 << 25)
> -#define	SPMODE_ENABLE		(1 << 24)
> -#define	SPMODE_LEN(x)		((x) << 20)
> -#define	SPMODE_PM(x)		((x) << 16)
> -#define	SPMODE_OP		(1 << 14)
> -#define	SPMODE_CG(x)		((x) << 7)
> -
> -/*
> - * Default for SPI Mode:
> - * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
> - */
> -#define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
> -			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
> -
> -/* SPIE register values */
> -#define	SPIE_NE		0x00000200	/* Not empty */
> -#define	SPIE_NF		0x00000100	/* Not full */
> -
> -/* SPIM register values */
> -#define	SPIM_NE		0x00000200	/* Not empty */
> -#define	SPIM_NF		0x00000100	/* Not full */
> -
> -#define	SPIE_TXB	0x00000200	/* Last char is written to tx fifo */
> -#define	SPIE_RXB	0x00000100	/* Last char is written to rx buf */
> -
> -/* SPCOM register values */
> -#define	SPCOM_STR	(1 << 23)	/* Start transmit */
> -
> -#define	SPI_PRAM_SIZE	0x100
> -#define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
> -
> -/* SPI Controller driver's private data. */
> -struct mpc8xxx_spi {
> -	struct device *dev;
> -	struct mpc8xxx_spi_reg __iomem *base;
> -
> -	/* rx & tx bufs from the spi_transfer */
> -	const void *tx;
> -	void *rx;
> -
> -	int subblock;
> -	struct spi_pram __iomem *pram;
> -	struct cpm_buf_desc __iomem *tx_bd;
> -	struct cpm_buf_desc __iomem *rx_bd;
> -
> -	struct spi_transfer *xfer_in_progress;
> -
> -	/* dma addresses for CPM transfers */
> -	dma_addr_t tx_dma;
> -	dma_addr_t rx_dma;
> -	bool map_tx_dma;
> -	bool map_rx_dma;
> -
> -	dma_addr_t dma_dummy_tx;
> -	dma_addr_t dma_dummy_rx;
> -
> -	/* functions to deal with different sized buffers */
> -	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> -	u32(*get_tx) (struct mpc8xxx_spi *);
> -
> -	unsigned int count;
> -	unsigned int irq;
> -
> -	unsigned nsecs;		/* (clock cycle time)/2 */
> -
> -	u32 spibrg;		/* SPIBRG input clock */
> -	u32 rx_shift;		/* RX data reg shift when in qe mode */
> -	u32 tx_shift;		/* TX data reg shift when in qe mode */
> -
> -	unsigned int flags;
> -
> -	struct workqueue_struct *workqueue;
> -	struct work_struct work;
> -
> -	struct list_head queue;
> -	spinlock_t lock;
> -
> -	struct completion done;
> -};
> -
> -static void *mpc8xxx_dummy_rx;
> -static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
> -static int mpc8xxx_dummy_rx_refcnt;
> -
> -struct spi_mpc8xxx_cs {
> -	/* functions to deal with different sized buffers */
> -	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> -	u32 (*get_tx) (struct mpc8xxx_spi *);
> -	u32 rx_shift;		/* RX data reg shift when in qe mode */
> -	u32 tx_shift;		/* TX data reg shift when in qe mode */
> -	u32 hw_mode;		/* Holds HW mode register settings */
> -};
> -
> -static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
> -{
> -	out_be32(reg, val);
> -}
> -
> -static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
> -{
> -	return in_be32(reg);
> -}
> -
> -#define MPC83XX_SPI_RX_BUF(type) 					  \
> -static									  \
> -void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
> -{									  \
> -	type *rx = mpc8xxx_spi->rx;					  \
> -	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
> -	mpc8xxx_spi->rx = rx;						  \
> -}
> -
> -#define MPC83XX_SPI_TX_BUF(type)				\
> -static								\
> -u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
> -{								\
> -	u32 data;						\
> -	const type *tx = mpc8xxx_spi->tx;			\
> -	if (!tx)						\
> -		return 0;					\
> -	data = *tx++ << mpc8xxx_spi->tx_shift;			\
> -	mpc8xxx_spi->tx = tx;					\
> -	return data;						\
> -}
> -
> -MPC83XX_SPI_RX_BUF(u8)
> -MPC83XX_SPI_RX_BUF(u16)
> -MPC83XX_SPI_RX_BUF(u32)
> -MPC83XX_SPI_TX_BUF(u8)
> -MPC83XX_SPI_TX_BUF(u16)
> -MPC83XX_SPI_TX_BUF(u32)
> -
> -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> -{
> -	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> -	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> -	__be32 __iomem *mode = &mspi->base->mode;
> -	unsigned long flags;
> -
> -	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
> -		return;
> -
> -	/* Turn off IRQs locally to minimize time that SPI is disabled. */
> -	local_irq_save(flags);
> -
> -	/* Turn off SPI unit prior changing mode */
> -	mpc8xxx_spi_write_reg(mode, cs->hw_mode & ~SPMODE_ENABLE);
> -
> -	/* When in CPM mode, we need to reinit tx and rx. */
> -	if (mspi->flags & SPI_CPM_MODE) {
> -		if (mspi->flags & SPI_QE) {
> -			qe_issue_cmd(QE_INIT_TX_RX, mspi->subblock,
> -				     QE_CR_PROTOCOL_UNSPECIFIED, 0);
> -		} else {
> -			cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
> -			if (mspi->flags & SPI_CPM1) {
> -				out_be16(&mspi->pram->rbptr,
> -					 in_be16(&mspi->pram->rbase));
> -				out_be16(&mspi->pram->tbptr,
> -					 in_be16(&mspi->pram->tbase));
> -			}
> -		}
> -	}
> -	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> -	local_irq_restore(flags);
> -}
> -
> -static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
> -	bool pol = spi->mode & SPI_CS_HIGH;
> -	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> -
> -	if (value == BITBANG_CS_INACTIVE) {
> -		if (pdata->cs_control)
> -			pdata->cs_control(spi, !pol);
> -	}
> -
> -	if (value == BITBANG_CS_ACTIVE) {
> -		mpc8xxx_spi->rx_shift = cs->rx_shift;
> -		mpc8xxx_spi->tx_shift = cs->tx_shift;
> -		mpc8xxx_spi->get_rx = cs->get_rx;
> -		mpc8xxx_spi->get_tx = cs->get_tx;
> -
> -		mpc8xxx_spi_change_mode(spi);
> -
> -		if (pdata->cs_control)
> -			pdata->cs_control(spi, pol);
> -	}
> -}
> -
> -static int
> -mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
> -			   struct spi_device *spi,
> -			   struct mpc8xxx_spi *mpc8xxx_spi,
> -			   int bits_per_word)
> -{
> -	cs->rx_shift = 0;
> -	cs->tx_shift = 0;
> -	if (bits_per_word <= 8) {
> -		cs->get_rx = mpc8xxx_spi_rx_buf_u8;
> -		cs->get_tx = mpc8xxx_spi_tx_buf_u8;
> -		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> -			cs->rx_shift = 16;
> -			cs->tx_shift = 24;
> -		}
> -	} else if (bits_per_word <= 16) {
> -		cs->get_rx = mpc8xxx_spi_rx_buf_u16;
> -		cs->get_tx = mpc8xxx_spi_tx_buf_u16;
> -		if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> -			cs->rx_shift = 16;
> -			cs->tx_shift = 16;
> -		}
> -	} else if (bits_per_word <= 32) {
> -		cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> -		cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> -	} else
> -		return -EINVAL;
> -
> -	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE &&
> -	    spi->mode & SPI_LSB_FIRST) {
> -		cs->tx_shift = 0;
> -		if (bits_per_word <= 8)
> -			cs->rx_shift = 8;
> -		else
> -			cs->rx_shift = 0;
> -	}
> -	mpc8xxx_spi->rx_shift = cs->rx_shift;
> -	mpc8xxx_spi->tx_shift = cs->tx_shift;
> -	mpc8xxx_spi->get_rx = cs->get_rx;
> -	mpc8xxx_spi->get_tx = cs->get_tx;
> -
> -	return bits_per_word;
> -}
> -
> -static int
> -mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
> -			  struct spi_device *spi,
> -			  int bits_per_word)
> -{
> -	/* QE uses Little Endian for words > 8
> -	 * so transform all words > 8 into 8 bits
> -	 * Unfortnatly that doesn't work for LSB so
> -	 * reject these for now */
> -	/* Note: 32 bits word, LSB works iff
> -	 * tfcr/rfcr is set to CPMFCR_GBL */
> -	if (spi->mode & SPI_LSB_FIRST &&
> -	    bits_per_word > 8)
> -		return -EINVAL;
> -	if (bits_per_word > 8)
> -		return 8; /* pretend its 8 bits */
> -	return bits_per_word;
> -}
> -
> -static
> -int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi;
> -	int bits_per_word;
> -	u8 pm;
> -	u32 hz;
> -	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> -
> -	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -
> -	if (t) {
> -		bits_per_word = t->bits_per_word;
> -		hz = t->speed_hz;
> -	} else {
> -		bits_per_word = 0;
> -		hz = 0;
> -	}
> -
> -	/* spi_transfer level calls that work per-word */
> -	if (!bits_per_word)
> -		bits_per_word = spi->bits_per_word;
> -
> -	/* Make sure its a bit width we support [4..16, 32] */
> -	if ((bits_per_word < 4)
> -	    || ((bits_per_word > 16) && (bits_per_word != 32)))
> -		return -EINVAL;
> -
> -	if (!hz)
> -		hz = spi->max_speed_hz;
> -
> -	if (!(mpc8xxx_spi->flags & SPI_CPM_MODE))
> -		bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
> -							   mpc8xxx_spi,
> -							   bits_per_word);
> -	else if (mpc8xxx_spi->flags & SPI_QE)
> -		bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
> -							  bits_per_word);
> -
> -	if (bits_per_word < 0)
> -		return bits_per_word;
> -
> -	if (bits_per_word == 32)
> -		bits_per_word = 0;
> -	else
> -		bits_per_word = bits_per_word - 1;
> -
> -	/* mask out bits we are going to set */
> -	cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16
> -				  | SPMODE_PM(0xF));
> -
> -	cs->hw_mode |= SPMODE_LEN(bits_per_word);
> -
> -	if ((mpc8xxx_spi->spibrg / hz) > 64) {
> -		cs->hw_mode |= SPMODE_DIV16;
> -		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> -
> -		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
> -			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
> -			  hz, mpc8xxx_spi->spibrg / 1024);
> -		if (pm > 16)
> -			pm = 16;
> -	} else
> -		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> -	if (pm)
> -		pm--;
> -
> -	cs->hw_mode |= SPMODE_PM(pm);
> -
> -	mpc8xxx_spi_change_mode(spi);
> -	return 0;
> -}
> -
> -static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
> -{
> -	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
> -	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
> -	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
> -	unsigned int xfer_ofs;
> -
> -	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
> -
> -	if (mspi->rx_dma == mspi->dma_dummy_rx)
> -		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma);
> -	else
> -		out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
> -	out_be16(&rx_bd->cbd_datlen, 0);
> -	out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
> -
> -	if (mspi->tx_dma == mspi->dma_dummy_tx)
> -		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma);
> -	else
> -		out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
> -	out_be16(&tx_bd->cbd_datlen, xfer_len);
> -	out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
> -				 BD_SC_LAST);
> -
> -	/* start transfer */
> -	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
> -}
> -
> -static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
> -				struct spi_transfer *t, bool is_dma_mapped)
> -{
> -	struct device *dev = mspi->dev;
> -
> -	if (is_dma_mapped) {
> -		mspi->map_tx_dma = 0;
> -		mspi->map_rx_dma = 0;
> -	} else {
> -		mspi->map_tx_dma = 1;
> -		mspi->map_rx_dma = 1;
> -	}
> -
> -	if (!t->tx_buf) {
> -		mspi->tx_dma = mspi->dma_dummy_tx;
> -		mspi->map_tx_dma = 0;
> -	}
> -
> -	if (!t->rx_buf) {
> -		mspi->rx_dma = mspi->dma_dummy_rx;
> -		mspi->map_rx_dma = 0;
> -	}
> -
> -	if (mspi->map_tx_dma) {
> -		void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
> -
> -		mspi->tx_dma = dma_map_single(dev, nonconst_tx, t->len,
> -					      DMA_TO_DEVICE);
> -		if (dma_mapping_error(dev, mspi->tx_dma)) {
> -			dev_err(dev, "unable to map tx dma\n");
> -			return -ENOMEM;
> -		}
> -	} else if (t->tx_buf) {
> -		mspi->tx_dma = t->tx_dma;
> -	}
> -
> -	if (mspi->map_rx_dma) {
> -		mspi->rx_dma = dma_map_single(dev, mspi->rx, t->len,
> -					      DMA_FROM_DEVICE);
> -		if (dma_mapping_error(dev, mspi->rx_dma)) {
> -			dev_err(dev, "unable to map rx dma\n");
> -			goto err_rx_dma;
> -		}
> -	} else if (t->rx_buf) {
> -		mspi->rx_dma = t->rx_dma;
> -	}
> -
> -	/* enable rx ints */
> -	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
> -
> -	mspi->xfer_in_progress = t;
> -	mspi->count = t->len;
> -
> -	/* start CPM transfers */
> -	mpc8xxx_spi_cpm_bufs_start(mspi);
> -
> -	return 0;
> -
> -err_rx_dma:
> -	if (mspi->map_tx_dma)
> -		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
> -	return -ENOMEM;
> -}
> -
> -static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
> -{
> -	struct device *dev = mspi->dev;
> -	struct spi_transfer *t = mspi->xfer_in_progress;
> -
> -	if (mspi->map_tx_dma)
> -		dma_unmap_single(dev, mspi->tx_dma, t->len, DMA_TO_DEVICE);
> -	if (mspi->map_rx_dma)
> -		dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
> -	mspi->xfer_in_progress = NULL;
> -}
> -
> -static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
> -				struct spi_transfer *t, unsigned int len)
> -{
> -	u32 word;
> -
> -	mspi->count = len;
> -
> -	/* enable rx ints */
> -	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
> -
> -	/* transmit word */
> -	word = mspi->get_tx(mspi);
> -	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> -
> -	return 0;
> -}
> -
> -static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
> -			    bool is_dma_mapped)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -	unsigned int len = t->len;
> -	u8 bits_per_word;
> -	int ret;
> -
> -	bits_per_word = spi->bits_per_word;
> -	if (t->bits_per_word)
> -		bits_per_word = t->bits_per_word;
> -
> -	if (bits_per_word > 8) {
> -		/* invalid length? */
> -		if (len & 1)
> -			return -EINVAL;
> -		len /= 2;
> -	}
> -	if (bits_per_word > 16) {
> -		/* invalid length? */
> -		if (len & 1)
> -			return -EINVAL;
> -		len /= 2;
> -	}
> -
> -	mpc8xxx_spi->tx = t->tx_buf;
> -	mpc8xxx_spi->rx = t->rx_buf;
> -
> -	INIT_COMPLETION(mpc8xxx_spi->done);
> -
> -	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> -		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
> -	else
> -		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
> -	if (ret)
> -		return ret;
> -
> -	wait_for_completion(&mpc8xxx_spi->done);
> -
> -	/* disable rx ints */
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> -
> -	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> -		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
> -
> -	return mpc8xxx_spi->count;
> -}
> -
> -static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
> -{
> -	struct spi_device *spi = m->spi;
> -	struct spi_transfer *t;
> -	unsigned int cs_change;
> -	const int nsecs = 50;
> -	int status;
> -
> -	cs_change = 1;
> -	status = 0;
> -	list_for_each_entry(t, &m->transfers, transfer_list) {
> -		if (t->bits_per_word || t->speed_hz) {
> -			/* Don't allow changes if CS is active */
> -			status = -EINVAL;
> -
> -			if (cs_change)
> -				status = mpc8xxx_spi_setup_transfer(spi, t);
> -			if (status < 0)
> -				break;
> -		}
> -
> -		if (cs_change) {
> -			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
> -			ndelay(nsecs);
> -		}
> -		cs_change = t->cs_change;
> -		if (t->len)
> -			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
> -		if (status) {
> -			status = -EMSGSIZE;
> -			break;
> -		}
> -		m->actual_length += t->len;
> -
> -		if (t->delay_usecs)
> -			udelay(t->delay_usecs);
> -
> -		if (cs_change) {
> -			ndelay(nsecs);
> -			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> -			ndelay(nsecs);
> -		}
> -	}
> -
> -	m->status = status;
> -	m->complete(m->context);
> -
> -	if (status || !cs_change) {
> -		ndelay(nsecs);
> -		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> -	}
> -
> -	mpc8xxx_spi_setup_transfer(spi, NULL);
> -}
> -
> -static void mpc8xxx_spi_work(struct work_struct *work)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
> -						       work);
> -
> -	spin_lock_irq(&mpc8xxx_spi->lock);
> -	while (!list_empty(&mpc8xxx_spi->queue)) {
> -		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
> -						   struct spi_message, queue);
> -
> -		list_del_init(&m->queue);
> -		spin_unlock_irq(&mpc8xxx_spi->lock);
> -
> -		mpc8xxx_spi_do_one_msg(m);
> -
> -		spin_lock_irq(&mpc8xxx_spi->lock);
> -	}
> -	spin_unlock_irq(&mpc8xxx_spi->lock);
> -}
> -
> -static int mpc8xxx_spi_setup(struct spi_device *spi)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi;
> -	int retval;
> -	u32 hw_mode;
> -	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> -
> -	if (!spi->max_speed_hz)
> -		return -EINVAL;
> -
> -	if (!cs) {
> -		cs = kzalloc(sizeof *cs, GFP_KERNEL);
> -		if (!cs)
> -			return -ENOMEM;
> -		spi->controller_state = cs;
> -	}
> -	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -
> -	hw_mode = cs->hw_mode; /* Save original settings */
> -	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
> -	/* mask out bits we are going to set */
> -	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
> -			 | SPMODE_REV | SPMODE_LOOP);
> -
> -	if (spi->mode & SPI_CPHA)
> -		cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK;
> -	if (spi->mode & SPI_CPOL)
> -		cs->hw_mode |= SPMODE_CI_INACTIVEHIGH;
> -	if (!(spi->mode & SPI_LSB_FIRST))
> -		cs->hw_mode |= SPMODE_REV;
> -	if (spi->mode & SPI_LOOP)
> -		cs->hw_mode |= SPMODE_LOOP;
> -
> -	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
> -	if (retval < 0) {
> -		cs->hw_mode = hw_mode; /* Restore settings */
> -		return retval;
> -	}
> -	return 0;
> -}
> -
> -static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
> -{
> -	u16 len;
> -
> -	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
> -		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
> -
> -	len = in_be16(&mspi->rx_bd->cbd_datlen);
> -	if (len > mspi->count) {
> -		WARN_ON(1);
> -		len = mspi->count;
> -	}
> -
> -	/* Clear the events */
> -	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> -
> -	mspi->count -= len;
> -	if (mspi->count)
> -		mpc8xxx_spi_cpm_bufs_start(mspi);
> -	else
> -		complete(&mspi->done);
> -}
> -
> -static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
> -{
> -	/* We need handle RX first */
> -	if (events & SPIE_NE) {
> -		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
> -
> -		if (mspi->rx)
> -			mspi->get_rx(rx_data, mspi);
> -	}
> -
> -	if ((events & SPIE_NF) == 0)
> -		/* spin until TX is done */
> -		while (((events =
> -			mpc8xxx_spi_read_reg(&mspi->base->event)) &
> -						SPIE_NF) == 0)
> -			cpu_relax();
> -
> -	/* Clear the events */
> -	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> -
> -	mspi->count -= 1;
> -	if (mspi->count) {
> -		u32 word = mspi->get_tx(mspi);
> -
> -		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> -	} else {
> -		complete(&mspi->done);
> -	}
> -}
> -
> -static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
> -{
> -	struct mpc8xxx_spi *mspi = context_data;
> -	irqreturn_t ret = IRQ_NONE;
> -	u32 events;
> -
> -	/* Get interrupt events(tx/rx) */
> -	events = mpc8xxx_spi_read_reg(&mspi->base->event);
> -	if (events)
> -		ret = IRQ_HANDLED;
> -
> -	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
> -
> -	if (mspi->flags & SPI_CPM_MODE)
> -		mpc8xxx_spi_cpm_irq(mspi, events);
> -	else
> -		mpc8xxx_spi_cpu_irq(mspi, events);
> -
> -	return ret;
> -}
> -
> -static int mpc8xxx_spi_transfer(struct spi_device *spi,
> -				struct spi_message *m)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -	unsigned long flags;
> -
> -	m->actual_length = 0;
> -	m->status = -EINPROGRESS;
> -
> -	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
> -	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
> -	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
> -	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
> -
> -	return 0;
> -}
> -
> -
> -static void mpc8xxx_spi_cleanup(struct spi_device *spi)
> -{
> -	kfree(spi->controller_state);
> -}
> -
> -static void *mpc8xxx_spi_alloc_dummy_rx(void)
> -{
> -	mutex_lock(&mpc8xxx_dummy_rx_lock);
> -
> -	if (!mpc8xxx_dummy_rx)
> -		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
> -	if (mpc8xxx_dummy_rx)
> -		mpc8xxx_dummy_rx_refcnt++;
> -
> -	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> -
> -	return mpc8xxx_dummy_rx;
> -}
> -
> -static void mpc8xxx_spi_free_dummy_rx(void)
> -{
> -	mutex_lock(&mpc8xxx_dummy_rx_lock);
> -
> -	switch (mpc8xxx_dummy_rx_refcnt) {
> -	case 0:
> -		WARN_ON(1);
> -		break;
> -	case 1:
> -		kfree(mpc8xxx_dummy_rx);
> -		mpc8xxx_dummy_rx = NULL;
> -		/* fall through */
> -	default:
> -		mpc8xxx_dummy_rx_refcnt--;
> -		break;
> -	}
> -
> -	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> -}
> -
> -static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
> -{
> -	struct device *dev = mspi->dev;
> -	struct device_node *np = dev->of_node;
> -	const u32 *iprop;
> -	int size;
> -	unsigned long spi_base_ofs;
> -	unsigned long pram_ofs = -ENOMEM;
> -
> -	/* Can't use of_address_to_resource(), QE muram isn't at 0. */
> -	iprop = of_get_property(np, "reg", &size);
> -
> -	/* QE with a fixed pram location? */
> -	if (mspi->flags & SPI_QE && iprop && size == sizeof(*iprop) * 4)
> -		return cpm_muram_alloc_fixed(iprop[2], SPI_PRAM_SIZE);
> -
> -	/* QE but with a dynamic pram location? */
> -	if (mspi->flags & SPI_QE) {
> -		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
> -		qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, mspi->subblock,
> -				QE_CR_PROTOCOL_UNSPECIFIED, pram_ofs);
> -		return pram_ofs;
> -	}
> -
> -	/* CPM1 and CPM2 pram must be at a fixed addr. */
> -	if (!iprop || size != sizeof(*iprop) * 4)
> -		return -ENOMEM;
> -
> -	spi_base_ofs = cpm_muram_alloc_fixed(iprop[2], 2);
> -	if (IS_ERR_VALUE(spi_base_ofs))
> -		return -ENOMEM;
> -
> -	if (mspi->flags & SPI_CPM2) {
> -		pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
> -		if (!IS_ERR_VALUE(pram_ofs)) {
> -			u16 __iomem *spi_base = cpm_muram_addr(spi_base_ofs);
> -
> -			out_be16(spi_base, pram_ofs);
> -		}
> -	} else {
> -		struct spi_pram __iomem *pram = cpm_muram_addr(spi_base_ofs);
> -		u16 rpbase = in_be16(&pram->rpbase);
> -
> -		/* Microcode relocation patch applied? */
> -		if (rpbase)
> -			pram_ofs = rpbase;
> -		else
> -			return spi_base_ofs;
> -	}
> -
> -	cpm_muram_free(spi_base_ofs);
> -	return pram_ofs;
> -}
> -
> -static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
> -{
> -	struct device *dev = mspi->dev;
> -	struct device_node *np = dev->of_node;
> -	const u32 *iprop;
> -	int size;
> -	unsigned long pram_ofs;
> -	unsigned long bds_ofs;
> -
> -	if (!(mspi->flags & SPI_CPM_MODE))
> -		return 0;
> -
> -	if (!mpc8xxx_spi_alloc_dummy_rx())
> -		return -ENOMEM;
> -
> -	if (mspi->flags & SPI_QE) {
> -		iprop = of_get_property(np, "cell-index", &size);
> -		if (iprop && size == sizeof(*iprop))
> -			mspi->subblock = *iprop;
> -
> -		switch (mspi->subblock) {
> -		default:
> -			dev_warn(dev, "cell-index unspecified, assuming SPI1");
> -			/* fall through */
> -		case 0:
> -			mspi->subblock = QE_CR_SUBBLOCK_SPI1;
> -			break;
> -		case 1:
> -			mspi->subblock = QE_CR_SUBBLOCK_SPI2;
> -			break;
> -		}
> -	}
> -
> -	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
> -	if (IS_ERR_VALUE(pram_ofs)) {
> -		dev_err(dev, "can't allocate spi parameter ram\n");
> -		goto err_pram;
> -	}
> -
> -	bds_ofs = cpm_muram_alloc(sizeof(*mspi->tx_bd) +
> -				  sizeof(*mspi->rx_bd), 8);
> -	if (IS_ERR_VALUE(bds_ofs)) {
> -		dev_err(dev, "can't allocate bds\n");
> -		goto err_bds;
> -	}
> -
> -	mspi->dma_dummy_tx = dma_map_single(dev, empty_zero_page, PAGE_SIZE,
> -					    DMA_TO_DEVICE);
> -	if (dma_mapping_error(dev, mspi->dma_dummy_tx)) {
> -		dev_err(dev, "unable to map dummy tx buffer\n");
> -		goto err_dummy_tx;
> -	}
> -
> -	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
> -					    DMA_FROM_DEVICE);
> -	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
> -		dev_err(dev, "unable to map dummy rx buffer\n");
> -		goto err_dummy_rx;
> -	}
> -
> -	mspi->pram = cpm_muram_addr(pram_ofs);
> -
> -	mspi->tx_bd = cpm_muram_addr(bds_ofs);
> -	mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
> -
> -	/* Initialize parameter ram. */
> -	out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd));
> -	out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd));
> -	out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL);
> -	out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL);
> -	out_be16(&mspi->pram->mrblr, SPI_MRBLR);
> -	out_be32(&mspi->pram->rstate, 0);
> -	out_be32(&mspi->pram->rdp, 0);
> -	out_be16(&mspi->pram->rbptr, 0);
> -	out_be16(&mspi->pram->rbc, 0);
> -	out_be32(&mspi->pram->rxtmp, 0);
> -	out_be32(&mspi->pram->tstate, 0);
> -	out_be32(&mspi->pram->tdp, 0);
> -	out_be16(&mspi->pram->tbptr, 0);
> -	out_be16(&mspi->pram->tbc, 0);
> -	out_be32(&mspi->pram->txtmp, 0);
> -
> -	return 0;
> -
> -err_dummy_rx:
> -	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
> -err_dummy_tx:
> -	cpm_muram_free(bds_ofs);
> -err_bds:
> -	cpm_muram_free(pram_ofs);
> -err_pram:
> -	mpc8xxx_spi_free_dummy_rx();
> -	return -ENOMEM;
> -}
> -
> -static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
> -{
> -	struct device *dev = mspi->dev;
> -
> -	dma_unmap_single(dev, mspi->dma_dummy_rx, SPI_MRBLR, DMA_FROM_DEVICE);
> -	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
> -	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
> -	cpm_muram_free(cpm_muram_offset(mspi->pram));
> -	mpc8xxx_spi_free_dummy_rx();
> -}
> -
> -static const char *mpc8xxx_spi_strmode(unsigned int flags)
> -{
> -	if (flags & SPI_QE_CPU_MODE) {
> -		return "QE CPU";
> -	} else if (flags & SPI_CPM_MODE) {
> -		if (flags & SPI_QE)
> -			return "QE";
> -		else if (flags & SPI_CPM2)
> -			return "CPM2";
> -		else
> -			return "CPM1";
> -	}
> -	return "CPU";
> -}
> -
> -static struct spi_master * __devinit
> -mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
> -{
> -	struct fsl_spi_platform_data *pdata = dev->platform_data;
> -	struct spi_master *master;
> -	struct mpc8xxx_spi *mpc8xxx_spi;
> -	u32 regval;
> -	int ret = 0;
> -
> -	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
> -	if (master == NULL) {
> -		ret = -ENOMEM;
> -		goto err;
> -	}
> -
> -	dev_set_drvdata(dev, master);
> -
> -	/* the spi->mode bits understood by this driver: */
> -	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
> -			| SPI_LSB_FIRST | SPI_LOOP;
> -
> -	master->setup = mpc8xxx_spi_setup;
> -	master->transfer = mpc8xxx_spi_transfer;
> -	master->cleanup = mpc8xxx_spi_cleanup;
> -	master->dev.of_node = dev->of_node;
> -
> -	mpc8xxx_spi = spi_master_get_devdata(master);
> -	mpc8xxx_spi->dev = dev;
> -	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
> -	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
> -	mpc8xxx_spi->flags = pdata->flags;
> -	mpc8xxx_spi->spibrg = pdata->sysclk;
> -
> -	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
> -	if (ret)
> -		goto err_cpm_init;
> -
> -	mpc8xxx_spi->rx_shift = 0;
> -	mpc8xxx_spi->tx_shift = 0;
> -	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> -		mpc8xxx_spi->rx_shift = 16;
> -		mpc8xxx_spi->tx_shift = 24;
> -	}
> -
> -	init_completion(&mpc8xxx_spi->done);
> -
> -	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
> -	if (mpc8xxx_spi->base == NULL) {
> -		ret = -ENOMEM;
> -		goto err_ioremap;
> -	}
> -
> -	mpc8xxx_spi->irq = irq;
> -
> -	/* Register for SPI Interrupt */
> -	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
> -			  0, "mpc8xxx_spi", mpc8xxx_spi);
> -
> -	if (ret != 0)
> -		goto unmap_io;
> -
> -	master->bus_num = pdata->bus_num;
> -	master->num_chipselect = pdata->max_chipselect;
> -
> -	/* SPI controller initializations */
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
> -
> -	/* Enable SPI interface */
> -	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
> -	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
> -		regval |= SPMODE_OP;
> -
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
> -	spin_lock_init(&mpc8xxx_spi->lock);
> -	init_completion(&mpc8xxx_spi->done);
> -	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
> -	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
> -
> -	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
> -		dev_name(master->dev.parent));
> -	if (mpc8xxx_spi->workqueue == NULL) {
> -		ret = -EBUSY;
> -		goto free_irq;
> -	}
> -
> -	ret = spi_register_master(master);
> -	if (ret < 0)
> -		goto unreg_master;
> -
> -	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
> -		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
> -
> -	return master;
> -
> -unreg_master:
> -	destroy_workqueue(mpc8xxx_spi->workqueue);
> -free_irq:
> -	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> -unmap_io:
> -	iounmap(mpc8xxx_spi->base);
> -err_ioremap:
> -	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> -err_cpm_init:
> -	spi_master_put(master);
> -err:
> -	return ERR_PTR(ret);
> -}
> -
> -static int __devexit mpc8xxx_spi_remove(struct device *dev)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi;
> -	struct spi_master *master;
> -
> -	master = dev_get_drvdata(dev);
> -	mpc8xxx_spi = spi_master_get_devdata(master);
> -
> -	flush_workqueue(mpc8xxx_spi->workqueue);
> -	destroy_workqueue(mpc8xxx_spi->workqueue);
> -	spi_unregister_master(master);
> -
> -	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> -	iounmap(mpc8xxx_spi->base);
> -	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> -
> -	return 0;
> -}
> -
> -struct mpc8xxx_spi_probe_info {
> -	struct fsl_spi_platform_data pdata;
> -	int *gpios;
> -	bool *alow_flags;
> -};
> -
> -static struct mpc8xxx_spi_probe_info *
> -to_of_pinfo(struct fsl_spi_platform_data *pdata)
> -{
> -	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
> -}
> -
> -static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
> -{
> -	struct device *dev = spi->dev.parent;
> -	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
> -	u16 cs = spi->chip_select;
> -	int gpio = pinfo->gpios[cs];
> -	bool alow = pinfo->alow_flags[cs];
> -
> -	gpio_set_value(gpio, on ^ alow);
> -}
> -
> -static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
> -{
> -	struct device_node *np = dev->of_node;
> -	struct fsl_spi_platform_data *pdata = dev->platform_data;
> -	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
> -	unsigned int ngpios;
> -	int i = 0;
> -	int ret;
> -
> -	ngpios = of_gpio_count(np);
> -	if (!ngpios) {
> -		/*
> -		 * SPI w/o chip-select line. One SPI device is still permitted
> -		 * though.
> -		 */
> -		pdata->max_chipselect = 1;
> -		return 0;
> -	}
> -
> -	pinfo->gpios = kmalloc(ngpios * sizeof(*pinfo->gpios), GFP_KERNEL);
> -	if (!pinfo->gpios)
> -		return -ENOMEM;
> -	memset(pinfo->gpios, -1, ngpios * sizeof(*pinfo->gpios));
> -
> -	pinfo->alow_flags = kzalloc(ngpios * sizeof(*pinfo->alow_flags),
> -				    GFP_KERNEL);
> -	if (!pinfo->alow_flags) {
> -		ret = -ENOMEM;
> -		goto err_alloc_flags;
> -	}
> -
> -	for (; i < ngpios; i++) {
> -		int gpio;
> -		enum of_gpio_flags flags;
> -
> -		gpio = of_get_gpio_flags(np, i, &flags);
> -		if (!gpio_is_valid(gpio)) {
> -			dev_err(dev, "invalid gpio #%d: %d\n", i, gpio);
> -			ret = gpio;
> -			goto err_loop;
> -		}
> -
> -		ret = gpio_request(gpio, dev_name(dev));
> -		if (ret) {
> -			dev_err(dev, "can't request gpio #%d: %d\n", i, ret);
> -			goto err_loop;
> -		}
> -
> -		pinfo->gpios[i] = gpio;
> -		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
> -
> -		ret = gpio_direction_output(pinfo->gpios[i],
> -					    pinfo->alow_flags[i]);
> -		if (ret) {
> -			dev_err(dev, "can't set output direction for gpio "
> -				"#%d: %d\n", i, ret);
> -			goto err_loop;
> -		}
> -	}
> -
> -	pdata->max_chipselect = ngpios;
> -	pdata->cs_control = mpc8xxx_spi_cs_control;
> -
> -	return 0;
> -
> -err_loop:
> -	while (i >= 0) {
> -		if (gpio_is_valid(pinfo->gpios[i]))
> -			gpio_free(pinfo->gpios[i]);
> -		i--;
> -	}
> -
> -	kfree(pinfo->alow_flags);
> -	pinfo->alow_flags = NULL;
> -err_alloc_flags:
> -	kfree(pinfo->gpios);
> -	pinfo->gpios = NULL;
> -	return ret;
> -}
> -
> -static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
> -{
> -	struct fsl_spi_platform_data *pdata = dev->platform_data;
> -	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
> -	int i;
> -
> -	if (!pinfo->gpios)
> -		return 0;
> -
> -	for (i = 0; i < pdata->max_chipselect; i++) {
> -		if (gpio_is_valid(pinfo->gpios[i]))
> -			gpio_free(pinfo->gpios[i]);
> -	}
> -
> -	kfree(pinfo->gpios);
> -	kfree(pinfo->alow_flags);
> -	return 0;
> -}
> -
> -static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
> -					  const struct of_device_id *ofid)
> -{
> -	struct device *dev = &ofdev->dev;
> -	struct device_node *np = ofdev->dev.of_node;
> -	struct mpc8xxx_spi_probe_info *pinfo;
> -	struct fsl_spi_platform_data *pdata;
> -	struct spi_master *master;
> -	struct resource mem;
> -	struct resource irq;
> -	const void *prop;
> -	int ret = -ENOMEM;
> -
> -	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
> -	if (!pinfo)
> -		return -ENOMEM;
> -
> -	pdata = &pinfo->pdata;
> -	dev->platform_data = pdata;
> -
> -	/* Allocate bus num dynamically. */
> -	pdata->bus_num = -1;
> -
> -	/* SPI controller is either clocked from QE or SoC clock. */
> -	pdata->sysclk = get_brgfreq();
> -	if (pdata->sysclk == -1) {
> -		pdata->sysclk = fsl_get_sys_freq();
> -		if (pdata->sysclk == -1) {
> -			ret = -ENODEV;
> -			goto err_clk;
> -		}
> -	}
> -
> -	prop = of_get_property(np, "mode", NULL);
> -	if (prop && !strcmp(prop, "cpu-qe"))
> -		pdata->flags = SPI_QE_CPU_MODE;
> -	else if (prop && !strcmp(prop, "qe"))
> -		pdata->flags = SPI_CPM_MODE | SPI_QE;
> -	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
> -		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
> -	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
> -		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> -
> -	ret = of_mpc8xxx_spi_get_chipselects(dev);
> -	if (ret)
> -		goto err;
> -
> -	ret = of_address_to_resource(np, 0, &mem);
> -	if (ret)
> -		goto err;
> -
> -	ret = of_irq_to_resource(np, 0, &irq);
> -	if (!ret) {
> -		ret = -EINVAL;
> -		goto err;
> -	}
> -
> -	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
> -	if (IS_ERR(master)) {
> -		ret = PTR_ERR(master);
> -		goto err;
> -	}
> -
> -	return 0;
> -
> -err:
> -	of_mpc8xxx_spi_free_chipselects(dev);
> -err_clk:
> -	kfree(pinfo);
> -	return ret;
> -}
> -
> -static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
> -{
> -	int ret;
> -
> -	ret = mpc8xxx_spi_remove(&ofdev->dev);
> -	if (ret)
> -		return ret;
> -	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
> -	return 0;
> -}
> -
> -static const struct of_device_id of_mpc8xxx_spi_match[] = {
> -	{ .compatible = "fsl,spi" },
> -	{},
> -};
> -MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
> -
> -static struct of_platform_driver of_mpc8xxx_spi_driver = {
> -	.driver = {
> -		.name = "mpc8xxx_spi",
> -		.owner = THIS_MODULE,
> -		.of_match_table = of_mpc8xxx_spi_match,
> -	},
> -	.probe		= of_mpc8xxx_spi_probe,
> -	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
> -};
> -
> -#ifdef CONFIG_MPC832x_RDB
> -/*
> - * 				XXX XXX XXX
> - * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
> - * only. The driver should go away soon, since newer MPC8323E-RDB's device
> - * tree can work with OpenFirmware driver. But for now we support old trees
> - * as well.
> - */
> -static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
> -{
> -	struct resource *mem;
> -	int irq;
> -	struct spi_master *master;
> -
> -	if (!pdev->dev.platform_data)
> -		return -EINVAL;
> -
> -	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	if (!mem)
> -		return -EINVAL;
> -
> -	irq = platform_get_irq(pdev, 0);
> -	if (irq <= 0)
> -		return -EINVAL;
> -
> -	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
> -	if (IS_ERR(master))
> -		return PTR_ERR(master);
> -	return 0;
> -}
> -
> -static int __devexit plat_mpc8xxx_spi_remove(struct platform_device *pdev)
> -{
> -	return mpc8xxx_spi_remove(&pdev->dev);
> -}
> -
> -MODULE_ALIAS("platform:mpc8xxx_spi");
> -static struct platform_driver mpc8xxx_spi_driver = {
> -	.probe = plat_mpc8xxx_spi_probe,
> -	.remove = __devexit_p(plat_mpc8xxx_spi_remove),
> -	.driver = {
> -		.name = "mpc8xxx_spi",
> -		.owner = THIS_MODULE,
> -	},
> -};
> -
> -static bool legacy_driver_failed;
> -
> -static void __init legacy_driver_register(void)
> -{
> -	legacy_driver_failed = platform_driver_register(&mpc8xxx_spi_driver);
> -}
> -
> -static void __exit legacy_driver_unregister(void)
> -{
> -	if (legacy_driver_failed)
> -		return;
> -	platform_driver_unregister(&mpc8xxx_spi_driver);
> -}
> -#else
> -static void __init legacy_driver_register(void) {}
> -static void __exit legacy_driver_unregister(void) {}
> -#endif /* CONFIG_MPC832x_RDB */
> -
> -static int __init mpc8xxx_spi_init(void)
> -{
> -	legacy_driver_register();
> -	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
> -}
> -
> -static void __exit mpc8xxx_spi_exit(void)
> -{
> -	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
> -	legacy_driver_unregister();
> -}
> -
> -module_init(mpc8xxx_spi_init);
> -module_exit(mpc8xxx_spi_exit);
> -
> -MODULE_AUTHOR("Kumar Gala");
> -MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
> -MODULE_LICENSE("GPL");
> -- 
> 1.6.4
> 
> 


From grant.likely at secretlab.ca  Tue Oct 12 23:41:10 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Tue, 12 Oct 2010 21:41:10 -0600
Subject: [PATCH v4 2/5] spi/mpc8xxx: refactor the common code for
	SPI/eSPI controller
In-Reply-To: <1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101013034110.GB7254@angua.secretlab.ca>

On Tue, Oct 12, 2010 at 06:18:31PM +0800, Mingkai Hu wrote:
> Refactor the common code in file spi_fsl_spi.c to spi_fsl_lib.c used
> by SPI/eSPI controller driver as a library, and leave the QE/CPM SPI
> controller code in the SPI controller driver spi_fsl_spi.c.
> 
> Because the register map of the SPI controller and eSPI controller
> is so different, also leave the code operated the register to the
> driver code, not the common code.
> 
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>

Applied, thanks.

g.

> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
> 
>  drivers/spi/Kconfig       |    5 +
>  drivers/spi/Makefile      |    1 +
>  drivers/spi/spi_fsl_lib.c |  237 +++++++++++++++++++
>  drivers/spi/spi_fsl_lib.h |  119 ++++++++++
>  drivers/spi/spi_fsl_spi.c |  552 +++++++++++++--------------------------------
>  5 files changed, 522 insertions(+), 392 deletions(-)
>  create mode 100644 drivers/spi/spi_fsl_lib.c
>  create mode 100644 drivers/spi/spi_fsl_lib.h
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 6af34c6..79ad06f 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -182,9 +182,14 @@ config SPI_MPC512x_PSC
>  	  This enables using the Freescale MPC5121 Programmable Serial
>  	  Controller in SPI master mode.
>  
> +config SPI_FSL_LIB
> +	tristate
> +	depends on FSL_SOC
> +
>  config SPI_FSL_SPI
>  	tristate "Freescale SPI controller"
>  	depends on FSL_SOC
> +	select SPI_FSL_LIB
>  	help
>  	  This enables using the Freescale SPI controllers in master mode.
>  	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 770817c..7974c21 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_SPI_PL022)			+= amba-pl022.o
>  obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
> +obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
>  obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
>  obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
>  obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
> diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
> new file mode 100644
> index 0000000..5cd741f
> --- /dev/null
> +++ b/drivers/spi/spi_fsl_lib.c
> @@ -0,0 +1,237 @@
> +/*
> + * Freescale SPI/eSPI controller driver library.
> + *
> + * Maintainer: Kumar Gala
> + *
> + * Copyright (C) 2006 Polycom, Inc.
> + *
> + * CPM SPI and QE buffer descriptors mode support:
> + * Copyright (c) 2009  MontaVista Software, Inc.
> + * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> + *
> + * Copyright 2010 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 <linux/kernel.h>
> +#include <linux/interrupt.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/mm.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_spi.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#include "spi_fsl_lib.h"
> +
> +#define MPC8XXX_SPI_RX_BUF(type) 					  \
> +void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
> +{									  \
> +	type *rx = mpc8xxx_spi->rx;					  \
> +	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
> +	mpc8xxx_spi->rx = rx;						  \
> +}
> +
> +#define MPC8XXX_SPI_TX_BUF(type)				\
> +u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
> +{								\
> +	u32 data;						\
> +	const type *tx = mpc8xxx_spi->tx;			\
> +	if (!tx)						\
> +		return 0;					\
> +	data = *tx++ << mpc8xxx_spi->tx_shift;			\
> +	mpc8xxx_spi->tx = tx;					\
> +	return data;						\
> +}
> +
> +MPC8XXX_SPI_RX_BUF(u8)
> +MPC8XXX_SPI_RX_BUF(u16)
> +MPC8XXX_SPI_RX_BUF(u32)
> +MPC8XXX_SPI_TX_BUF(u8)
> +MPC8XXX_SPI_TX_BUF(u16)
> +MPC8XXX_SPI_TX_BUF(u32)
> +
> +struct mpc8xxx_spi_probe_info *to_of_pinfo(struct fsl_spi_platform_data *pdata)
> +{
> +	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
> +}
> +
> +void mpc8xxx_spi_work(struct work_struct *work)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
> +						       work);
> +
> +	spin_lock_irq(&mpc8xxx_spi->lock);
> +	while (!list_empty(&mpc8xxx_spi->queue)) {
> +		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
> +						   struct spi_message, queue);
> +
> +		list_del_init(&m->queue);
> +		spin_unlock_irq(&mpc8xxx_spi->lock);
> +
> +		if (mpc8xxx_spi->spi_do_one_msg)
> +			mpc8xxx_spi->spi_do_one_msg(m);
> +
> +		spin_lock_irq(&mpc8xxx_spi->lock);
> +	}
> +	spin_unlock_irq(&mpc8xxx_spi->lock);
> +}
> +
> +int mpc8xxx_spi_transfer(struct spi_device *spi,
> +				struct spi_message *m)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	unsigned long flags;
> +
> +	m->actual_length = 0;
> +	m->status = -EINPROGRESS;
> +
> +	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
> +	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
> +	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
> +	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
> +
> +	return 0;
> +}
> +
> +void mpc8xxx_spi_cleanup(struct spi_device *spi)
> +{
> +	kfree(spi->controller_state);
> +}
> +
> +const char *mpc8xxx_spi_strmode(unsigned int flags)
> +{
> +	if (flags & SPI_QE_CPU_MODE) {
> +		return "QE CPU";
> +	} else if (flags & SPI_CPM_MODE) {
> +		if (flags & SPI_QE)
> +			return "QE";
> +		else if (flags & SPI_CPM2)
> +			return "CPM2";
> +		else
> +			return "CPM1";
> +	}
> +	return "CPU";
> +}
> +
> +int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
> +			unsigned int irq)
> +{
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct spi_master *master;
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	int ret = 0;
> +
> +	master = dev_get_drvdata(dev);
> +
> +	/* the spi->mode bits understood by this driver: */
> +	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
> +			| SPI_LSB_FIRST | SPI_LOOP;
> +
> +	master->transfer = mpc8xxx_spi_transfer;
> +	master->cleanup = mpc8xxx_spi_cleanup;
> +	master->dev.of_node = dev->of_node;
> +
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +	mpc8xxx_spi->dev = dev;
> +	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
> +	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
> +	mpc8xxx_spi->flags = pdata->flags;
> +	mpc8xxx_spi->spibrg = pdata->sysclk;
> +	mpc8xxx_spi->irq = irq;
> +
> +	mpc8xxx_spi->rx_shift = 0;
> +	mpc8xxx_spi->tx_shift = 0;
> +
> +	init_completion(&mpc8xxx_spi->done);
> +
> +	master->bus_num = pdata->bus_num;
> +	master->num_chipselect = pdata->max_chipselect;
> +
> +	spin_lock_init(&mpc8xxx_spi->lock);
> +	init_completion(&mpc8xxx_spi->done);
> +	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
> +	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
> +
> +	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
> +		dev_name(master->dev.parent));
> +	if (mpc8xxx_spi->workqueue == NULL) {
> +		ret = -EBUSY;
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	return ret;
> +}
> +
> +int __devexit mpc8xxx_spi_remove(struct device *dev)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct spi_master *master;
> +
> +	master = dev_get_drvdata(dev);
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +
> +	flush_workqueue(mpc8xxx_spi->workqueue);
> +	destroy_workqueue(mpc8xxx_spi->workqueue);
> +	spi_unregister_master(master);
> +
> +	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> +
> +	if (mpc8xxx_spi->spi_remove)
> +		mpc8xxx_spi->spi_remove(mpc8xxx_spi);
> +
> +	return 0;
> +}
> +
> +int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
> +					const struct of_device_id *ofid)
> +{
> +	struct device *dev = &ofdev->dev;
> +	struct device_node *np = ofdev->dev.of_node;
> +	struct mpc8xxx_spi_probe_info *pinfo;
> +	struct fsl_spi_platform_data *pdata;
> +	const void *prop;
> +	int ret = -ENOMEM;
> +
> +	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
> +	if (!pinfo)
> +		return -ENOMEM;
> +
> +	pdata = &pinfo->pdata;
> +	dev->platform_data = pdata;
> +
> +	/* Allocate bus num dynamically. */
> +	pdata->bus_num = -1;
> +
> +	/* SPI controller is either clocked from QE or SoC clock. */
> +	pdata->sysclk = get_brgfreq();
> +	if (pdata->sysclk == -1) {
> +		pdata->sysclk = fsl_get_sys_freq();
> +		if (pdata->sysclk == -1) {
> +			ret = -ENODEV;
> +			goto err;
> +		}
> +	}
> +
> +	prop = of_get_property(np, "mode", NULL);
> +	if (prop && !strcmp(prop, "cpu-qe"))
> +		pdata->flags = SPI_QE_CPU_MODE;
> +	else if (prop && !strcmp(prop, "qe"))
> +		pdata->flags = SPI_CPM_MODE | SPI_QE;
> +	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
> +		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
> +	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
> +		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> +
> +	return 0;
> +
> +err:
> +	kfree(pinfo);
> +	return ret;
> +}
> diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
> new file mode 100644
> index 0000000..6ae8949
> --- /dev/null
> +++ b/drivers/spi/spi_fsl_lib.h
> @@ -0,0 +1,119 @@
> +/*
> + * Freescale SPI/eSPI controller driver library.
> + *
> + * Maintainer: Kumar Gala
> + *
> + * Copyright 2010 Freescale Semiconductor, Inc.
> + * Copyright (C) 2006 Polycom, Inc.
> + *
> + * CPM SPI and QE buffer descriptors mode support:
> + * Copyright (c) 2009  MontaVista Software, Inc.
> + * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + */
> +#ifndef __SPI_FSL_LIB_H__
> +#define __SPI_FSL_LIB_H__
> +
> +/* SPI/eSPI Controller driver's private data. */
> +struct mpc8xxx_spi {
> +	struct device *dev;
> +	void *reg_base;
> +
> +	/* rx & tx bufs from the spi_transfer */
> +	const void *tx;
> +	void *rx;
> +
> +	int subblock;
> +	struct spi_pram __iomem *pram;
> +	struct cpm_buf_desc __iomem *tx_bd;
> +	struct cpm_buf_desc __iomem *rx_bd;
> +
> +	struct spi_transfer *xfer_in_progress;
> +
> +	/* dma addresses for CPM transfers */
> +	dma_addr_t tx_dma;
> +	dma_addr_t rx_dma;
> +	bool map_tx_dma;
> +	bool map_rx_dma;
> +
> +	dma_addr_t dma_dummy_tx;
> +	dma_addr_t dma_dummy_rx;
> +
> +	/* functions to deal with different sized buffers */
> +	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> +	u32(*get_tx) (struct mpc8xxx_spi *);
> +
> +	/* hooks for different controller driver */
> +	void (*spi_do_one_msg) (struct spi_message *m);
> +	void (*spi_remove) (struct mpc8xxx_spi *mspi);
> +
> +	unsigned int count;
> +	unsigned int irq;
> +
> +	unsigned nsecs;		/* (clock cycle time)/2 */
> +
> +	u32 spibrg;		/* SPIBRG input clock */
> +	u32 rx_shift;		/* RX data reg shift when in qe mode */
> +	u32 tx_shift;		/* TX data reg shift when in qe mode */
> +
> +	unsigned int flags;
> +
> +	struct workqueue_struct *workqueue;
> +	struct work_struct work;
> +
> +	struct list_head queue;
> +	spinlock_t lock;
> +
> +	struct completion done;
> +};
> +
> +struct spi_mpc8xxx_cs {
> +	/* functions to deal with different sized buffers */
> +	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> +	u32 (*get_tx) (struct mpc8xxx_spi *);
> +	u32 rx_shift;		/* RX data reg shift when in qe mode */
> +	u32 tx_shift;		/* TX data reg shift when in qe mode */
> +	u32 hw_mode;		/* Holds HW mode register settings */
> +};
> +
> +static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
> +{
> +	out_be32(reg, val);
> +}
> +
> +static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
> +{
> +	return in_be32(reg);
> +}
> +
> +struct mpc8xxx_spi_probe_info {
> +	struct fsl_spi_platform_data pdata;
> +	int *gpios;
> +	bool *alow_flags;
> +};
> +
> +extern u32 mpc8xxx_spi_tx_buf_u8(struct mpc8xxx_spi *mpc8xxx_spi);
> +extern u32 mpc8xxx_spi_tx_buf_u16(struct mpc8xxx_spi *mpc8xxx_spi);
> +extern u32 mpc8xxx_spi_tx_buf_u32(struct mpc8xxx_spi *mpc8xxx_spi);
> +extern void mpc8xxx_spi_rx_buf_u8(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
> +extern void mpc8xxx_spi_rx_buf_u16(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
> +extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi);
> +
> +extern struct mpc8xxx_spi_probe_info *to_of_pinfo(
> +		struct fsl_spi_platform_data *pdata);
> +extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi,
> +		struct spi_transfer *t, unsigned int len);
> +extern int mpc8xxx_spi_transfer(struct spi_device *spi, struct spi_message *m);
> +extern void mpc8xxx_spi_cleanup(struct spi_device *spi);
> +extern const char *mpc8xxx_spi_strmode(unsigned int flags);
> +extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
> +		unsigned int irq);
> +extern int mpc8xxx_spi_remove(struct device *dev);
> +extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
> +				const struct of_device_id *ofid);
> +
> +#endif /* __SPI_FSL_LIB_H__ */
> diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
> index 1dd86b8..7ca52d3 100644
> --- a/drivers/spi/spi_fsl_spi.c
> +++ b/drivers/spi/spi_fsl_spi.c
> @@ -1,9 +1,10 @@
>  /*
> - * MPC8xxx SPI controller driver.
> + * Freescale SPI controller driver.
>   *
>   * Maintainer: Kumar Gala
>   *
>   * Copyright (C) 2006 Polycom, Inc.
> + * Copyright 2010 Freescale Semiconductor, Inc.
>   *
>   * CPM SPI and QE buffer descriptors mode support:
>   * Copyright (c) 2009  MontaVista Software, Inc.
> @@ -15,18 +16,11 @@
>   * option) any later version.
>   */
>  #include <linux/module.h>
> -#include <linux/init.h>
>  #include <linux/types.h>
>  #include <linux/kernel.h>
> -#include <linux/bug.h>
> -#include <linux/errno.h>
> -#include <linux/err.h>
> -#include <linux/io.h>
> -#include <linux/completion.h>
>  #include <linux/interrupt.h>
>  #include <linux/delay.h>
>  #include <linux/irq.h>
> -#include <linux/device.h>
>  #include <linux/spi/spi.h>
>  #include <linux/spi/spi_bitbang.h>
>  #include <linux/platform_device.h>
> @@ -38,12 +32,12 @@
>  #include <linux/of_platform.h>
>  #include <linux/gpio.h>
>  #include <linux/of_gpio.h>
> -#include <linux/slab.h>
>  
>  #include <sysdev/fsl_soc.h>
>  #include <asm/cpm.h>
>  #include <asm/qe.h>
> -#include <asm/irq.h>
> +
> +#include "spi_fsl_lib.h"
>  
>  /* CPM1 and CPM2 are mutually exclusive. */
>  #ifdef CONFIG_CPM1
> @@ -55,7 +49,7 @@
>  #endif
>  
>  /* SPI Controller registers */
> -struct mpc8xxx_spi_reg {
> +struct fsl_spi_reg {
>  	u8 res1[0x20];
>  	__be32 mode;
>  	__be32 event;
> @@ -80,7 +74,7 @@ struct mpc8xxx_spi_reg {
>  
>  /*
>   * Default for SPI Mode:
> - * 	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
> + *	SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk
>   */
>  #define	SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \
>  			 SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf))
> @@ -102,112 +96,16 @@ struct mpc8xxx_spi_reg {
>  #define	SPI_PRAM_SIZE	0x100
>  #define	SPI_MRBLR	((unsigned int)PAGE_SIZE)
>  
> -/* SPI Controller driver's private data. */
> -struct mpc8xxx_spi {
> -	struct device *dev;
> -	struct mpc8xxx_spi_reg __iomem *base;
> -
> -	/* rx & tx bufs from the spi_transfer */
> -	const void *tx;
> -	void *rx;
> -
> -	int subblock;
> -	struct spi_pram __iomem *pram;
> -	struct cpm_buf_desc __iomem *tx_bd;
> -	struct cpm_buf_desc __iomem *rx_bd;
> -
> -	struct spi_transfer *xfer_in_progress;
> -
> -	/* dma addresses for CPM transfers */
> -	dma_addr_t tx_dma;
> -	dma_addr_t rx_dma;
> -	bool map_tx_dma;
> -	bool map_rx_dma;
> -
> -	dma_addr_t dma_dummy_tx;
> -	dma_addr_t dma_dummy_rx;
> -
> -	/* functions to deal with different sized buffers */
> -	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> -	u32(*get_tx) (struct mpc8xxx_spi *);
> -
> -	unsigned int count;
> -	unsigned int irq;
> -
> -	unsigned nsecs;		/* (clock cycle time)/2 */
> -
> -	u32 spibrg;		/* SPIBRG input clock */
> -	u32 rx_shift;		/* RX data reg shift when in qe mode */
> -	u32 tx_shift;		/* TX data reg shift when in qe mode */
> -
> -	unsigned int flags;
> -
> -	struct workqueue_struct *workqueue;
> -	struct work_struct work;
> -
> -	struct list_head queue;
> -	spinlock_t lock;
> -
> -	struct completion done;
> -};
> -
> -static void *mpc8xxx_dummy_rx;
> -static DEFINE_MUTEX(mpc8xxx_dummy_rx_lock);
> -static int mpc8xxx_dummy_rx_refcnt;
> -
> -struct spi_mpc8xxx_cs {
> -	/* functions to deal with different sized buffers */
> -	void (*get_rx) (u32 rx_data, struct mpc8xxx_spi *);
> -	u32 (*get_tx) (struct mpc8xxx_spi *);
> -	u32 rx_shift;		/* RX data reg shift when in qe mode */
> -	u32 tx_shift;		/* TX data reg shift when in qe mode */
> -	u32 hw_mode;		/* Holds HW mode register settings */
> -};
> -
> -static inline void mpc8xxx_spi_write_reg(__be32 __iomem *reg, u32 val)
> -{
> -	out_be32(reg, val);
> -}
> -
> -static inline u32 mpc8xxx_spi_read_reg(__be32 __iomem *reg)
> -{
> -	return in_be32(reg);
> -}
> -
> -#define MPC83XX_SPI_RX_BUF(type) 					  \
> -static									  \
> -void mpc8xxx_spi_rx_buf_##type(u32 data, struct mpc8xxx_spi *mpc8xxx_spi) \
> -{									  \
> -	type *rx = mpc8xxx_spi->rx;					  \
> -	*rx++ = (type)(data >> mpc8xxx_spi->rx_shift);			  \
> -	mpc8xxx_spi->rx = rx;						  \
> -}
> -
> -#define MPC83XX_SPI_TX_BUF(type)				\
> -static								\
> -u32 mpc8xxx_spi_tx_buf_##type(struct mpc8xxx_spi *mpc8xxx_spi)	\
> -{								\
> -	u32 data;						\
> -	const type *tx = mpc8xxx_spi->tx;			\
> -	if (!tx)						\
> -		return 0;					\
> -	data = *tx++ << mpc8xxx_spi->tx_shift;			\
> -	mpc8xxx_spi->tx = tx;					\
> -	return data;						\
> -}
> +static void *fsl_dummy_rx;
> +static DEFINE_MUTEX(fsl_dummy_rx_lock);
> +static int fsl_dummy_rx_refcnt;
>  
> -MPC83XX_SPI_RX_BUF(u8)
> -MPC83XX_SPI_RX_BUF(u16)
> -MPC83XX_SPI_RX_BUF(u32)
> -MPC83XX_SPI_TX_BUF(u8)
> -MPC83XX_SPI_TX_BUF(u16)
> -MPC83XX_SPI_TX_BUF(u32)
> -
> -static void mpc8xxx_spi_change_mode(struct spi_device *spi)
> +static void fsl_spi_change_mode(struct spi_device *spi)
>  {
>  	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
>  	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> -	__be32 __iomem *mode = &mspi->base->mode;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
> +	__be32 __iomem *mode = &reg_base->mode;
>  	unsigned long flags;
>  
>  	if (cs->hw_mode == mpc8xxx_spi_read_reg(mode))
> @@ -238,7 +136,7 @@ static void mpc8xxx_spi_change_mode(struct spi_device *spi)
>  	local_irq_restore(flags);
>  }
>  
> -static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
> +static void fsl_spi_chipselect(struct spi_device *spi, int value)
>  {
>  	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
>  	struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
> @@ -256,18 +154,17 @@ static void mpc8xxx_spi_chipselect(struct spi_device *spi, int value)
>  		mpc8xxx_spi->get_rx = cs->get_rx;
>  		mpc8xxx_spi->get_tx = cs->get_tx;
>  
> -		mpc8xxx_spi_change_mode(spi);
> +		fsl_spi_change_mode(spi);
>  
>  		if (pdata->cs_control)
>  			pdata->cs_control(spi, pol);
>  	}
>  }
>  
> -static int
> -mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
> -			   struct spi_device *spi,
> -			   struct mpc8xxx_spi *mpc8xxx_spi,
> -			   int bits_per_word)
> +static int mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
> +				struct spi_device *spi,
> +				struct mpc8xxx_spi *mpc8xxx_spi,
> +				int bits_per_word)
>  {
>  	cs->rx_shift = 0;
>  	cs->tx_shift = 0;
> @@ -307,10 +204,9 @@ mspi_apply_cpu_mode_quirks(struct spi_mpc8xxx_cs *cs,
>  	return bits_per_word;
>  }
>  
> -static int
> -mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
> -			  struct spi_device *spi,
> -			  int bits_per_word)
> +static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
> +				struct spi_device *spi,
> +				int bits_per_word)
>  {
>  	/* QE uses Little Endian for words > 8
>  	 * so transform all words > 8 into 8 bits
> @@ -326,13 +222,13 @@ mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
>  	return bits_per_word;
>  }
>  
> -static
> -int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
> +static int fsl_spi_setup_transfer(struct spi_device *spi,
> +					struct spi_transfer *t)
>  {
>  	struct mpc8xxx_spi *mpc8xxx_spi;
> -	int bits_per_word;
> +	int bits_per_word = 0;
>  	u8 pm;
> -	u32 hz;
> +	u32 hz = 0;
>  	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
>  
>  	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> @@ -340,9 +236,6 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
>  	if (t) {
>  		bits_per_word = t->bits_per_word;
>  		hz = t->speed_hz;
> -	} else {
> -		bits_per_word = 0;
> -		hz = 0;
>  	}
>  
>  	/* spi_transfer level calls that work per-word */
> @@ -388,23 +281,25 @@ int mpc8xxx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
>  			  hz, mpc8xxx_spi->spibrg / 1024);
>  		if (pm > 16)
>  			pm = 16;
> -	} else
> +	} else {
>  		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> +	}
>  	if (pm)
>  		pm--;
>  
>  	cs->hw_mode |= SPMODE_PM(pm);
>  
> -	mpc8xxx_spi_change_mode(spi);
> +	fsl_spi_change_mode(spi);
>  	return 0;
>  }
>  
> -static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
> +static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
>  {
>  	struct cpm_buf_desc __iomem *tx_bd = mspi->tx_bd;
>  	struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
>  	unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
>  	unsigned int xfer_ofs;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
>  
>  	xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
>  
> @@ -424,13 +319,14 @@ static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
>  				 BD_SC_LAST);
>  
>  	/* start transfer */
> -	mpc8xxx_spi_write_reg(&mspi->base->command, SPCOM_STR);
> +	mpc8xxx_spi_write_reg(&reg_base->command, SPCOM_STR);
>  }
>  
> -static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
> +static int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
>  				struct spi_transfer *t, bool is_dma_mapped)
>  {
>  	struct device *dev = mspi->dev;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
>  
>  	if (is_dma_mapped) {
>  		mspi->map_tx_dma = 0;
> @@ -475,13 +371,13 @@ static int mpc8xxx_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
>  	}
>  
>  	/* enable rx ints */
> -	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIE_RXB);
> +	mpc8xxx_spi_write_reg(&reg_base->mask, SPIE_RXB);
>  
>  	mspi->xfer_in_progress = t;
>  	mspi->count = t->len;
>  
>  	/* start CPM transfers */
> -	mpc8xxx_spi_cpm_bufs_start(mspi);
> +	fsl_spi_cpm_bufs_start(mspi);
>  
>  	return 0;
>  
> @@ -491,7 +387,7 @@ err_rx_dma:
>  	return -ENOMEM;
>  }
>  
> -static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
> +static void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
>  {
>  	struct device *dev = mspi->dev;
>  	struct spi_transfer *t = mspi->xfer_in_progress;
> @@ -503,31 +399,34 @@ static void mpc8xxx_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
>  	mspi->xfer_in_progress = NULL;
>  }
>  
> -static int mpc8xxx_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
> +static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi,
>  				struct spi_transfer *t, unsigned int len)
>  {
>  	u32 word;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
>  
>  	mspi->count = len;
>  
>  	/* enable rx ints */
> -	mpc8xxx_spi_write_reg(&mspi->base->mask, SPIM_NE);
> +	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
>  
>  	/* transmit word */
>  	word = mspi->get_tx(mspi);
> -	mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> +	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
>  
>  	return 0;
>  }
>  
> -static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
> +static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
>  			    bool is_dma_mapped)
>  {
>  	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	struct fsl_spi_reg *reg_base;
>  	unsigned int len = t->len;
>  	u8 bits_per_word;
>  	int ret;
>  
> +	reg_base = mpc8xxx_spi->reg_base;
>  	bits_per_word = spi->bits_per_word;
>  	if (t->bits_per_word)
>  		bits_per_word = t->bits_per_word;
> @@ -551,24 +450,24 @@ static int mpc8xxx_spi_bufs(struct spi_device *spi, struct spi_transfer *t,
>  	INIT_COMPLETION(mpc8xxx_spi->done);
>  
>  	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> -		ret = mpc8xxx_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
> +		ret = fsl_spi_cpm_bufs(mpc8xxx_spi, t, is_dma_mapped);
>  	else
> -		ret = mpc8xxx_spi_cpu_bufs(mpc8xxx_spi, t, len);
> +		ret = fsl_spi_cpu_bufs(mpc8xxx_spi, t, len);
>  	if (ret)
>  		return ret;
>  
>  	wait_for_completion(&mpc8xxx_spi->done);
>  
>  	/* disable rx ints */
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
>  
>  	if (mpc8xxx_spi->flags & SPI_CPM_MODE)
> -		mpc8xxx_spi_cpm_bufs_complete(mpc8xxx_spi);
> +		fsl_spi_cpm_bufs_complete(mpc8xxx_spi);
>  
>  	return mpc8xxx_spi->count;
>  }
>  
> -static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
> +static void fsl_spi_do_one_msg(struct spi_message *m)
>  {
>  	struct spi_device *spi = m->spi;
>  	struct spi_transfer *t;
> @@ -584,18 +483,18 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
>  			status = -EINVAL;
>  
>  			if (cs_change)
> -				status = mpc8xxx_spi_setup_transfer(spi, t);
> +				status = fsl_spi_setup_transfer(spi, t);
>  			if (status < 0)
>  				break;
>  		}
>  
>  		if (cs_change) {
> -			mpc8xxx_spi_chipselect(spi, BITBANG_CS_ACTIVE);
> +			fsl_spi_chipselect(spi, BITBANG_CS_ACTIVE);
>  			ndelay(nsecs);
>  		}
>  		cs_change = t->cs_change;
>  		if (t->len)
> -			status = mpc8xxx_spi_bufs(spi, t, m->is_dma_mapped);
> +			status = fsl_spi_bufs(spi, t, m->is_dma_mapped);
>  		if (status) {
>  			status = -EMSGSIZE;
>  			break;
> @@ -607,7 +506,7 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
>  
>  		if (cs_change) {
>  			ndelay(nsecs);
> -			mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> +			fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
>  			ndelay(nsecs);
>  		}
>  	}
> @@ -617,35 +516,16 @@ static void mpc8xxx_spi_do_one_msg(struct spi_message *m)
>  
>  	if (status || !cs_change) {
>  		ndelay(nsecs);
> -		mpc8xxx_spi_chipselect(spi, BITBANG_CS_INACTIVE);
> +		fsl_spi_chipselect(spi, BITBANG_CS_INACTIVE);
>  	}
>  
> -	mpc8xxx_spi_setup_transfer(spi, NULL);
> -}
> -
> -static void mpc8xxx_spi_work(struct work_struct *work)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi = container_of(work, struct mpc8xxx_spi,
> -						       work);
> -
> -	spin_lock_irq(&mpc8xxx_spi->lock);
> -	while (!list_empty(&mpc8xxx_spi->queue)) {
> -		struct spi_message *m = container_of(mpc8xxx_spi->queue.next,
> -						   struct spi_message, queue);
> -
> -		list_del_init(&m->queue);
> -		spin_unlock_irq(&mpc8xxx_spi->lock);
> -
> -		mpc8xxx_spi_do_one_msg(m);
> -
> -		spin_lock_irq(&mpc8xxx_spi->lock);
> -	}
> -	spin_unlock_irq(&mpc8xxx_spi->lock);
> +	fsl_spi_setup_transfer(spi, NULL);
>  }
>  
> -static int mpc8xxx_spi_setup(struct spi_device *spi)
> +static int fsl_spi_setup(struct spi_device *spi)
>  {
>  	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_spi_reg *reg_base;
>  	int retval;
>  	u32 hw_mode;
>  	struct spi_mpc8xxx_cs	*cs = spi->controller_state;
> @@ -661,8 +541,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
>  	}
>  	mpc8xxx_spi = spi_master_get_devdata(spi->master);
>  
> +	reg_base = mpc8xxx_spi->reg_base;
> +
>  	hw_mode = cs->hw_mode; /* Save original settings */
> -	cs->hw_mode = mpc8xxx_spi_read_reg(&mpc8xxx_spi->base->mode);
> +	cs->hw_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
>  	/* mask out bits we are going to set */
>  	cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH
>  			 | SPMODE_REV | SPMODE_LOOP);
> @@ -676,7 +558,7 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
>  	if (spi->mode & SPI_LOOP)
>  		cs->hw_mode |= SPMODE_LOOP;
>  
> -	retval = mpc8xxx_spi_setup_transfer(spi, NULL);
> +	retval = fsl_spi_setup_transfer(spi, NULL);
>  	if (retval < 0) {
>  		cs->hw_mode = hw_mode; /* Restore settings */
>  		return retval;
> @@ -684,9 +566,10 @@ static int mpc8xxx_spi_setup(struct spi_device *spi)
>  	return 0;
>  }
>  
> -static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
> +static void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
>  {
>  	u16 len;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
>  
>  	dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
>  		in_be16(&mspi->rx_bd->cbd_datlen), mspi->count);
> @@ -698,20 +581,22 @@ static void mpc8xxx_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
>  	}
>  
>  	/* Clear the events */
> -	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> +	mpc8xxx_spi_write_reg(&reg_base->event, events);
>  
>  	mspi->count -= len;
>  	if (mspi->count)
> -		mpc8xxx_spi_cpm_bufs_start(mspi);
> +		fsl_spi_cpm_bufs_start(mspi);
>  	else
>  		complete(&mspi->done);
>  }
>  
> -static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
> +static void fsl_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
>  {
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
> +
>  	/* We need handle RX first */
>  	if (events & SPIE_NE) {
> -		u32 rx_data = mpc8xxx_spi_read_reg(&mspi->base->receive);
> +		u32 rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
>  
>  		if (mspi->rx)
>  			mspi->get_rx(rx_data, mspi);
> @@ -720,102 +605,80 @@ static void mpc8xxx_spi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
>  	if ((events & SPIE_NF) == 0)
>  		/* spin until TX is done */
>  		while (((events =
> -			mpc8xxx_spi_read_reg(&mspi->base->event)) &
> +			mpc8xxx_spi_read_reg(&reg_base->event)) &
>  						SPIE_NF) == 0)
>  			cpu_relax();
>  
>  	/* Clear the events */
> -	mpc8xxx_spi_write_reg(&mspi->base->event, events);
> +	mpc8xxx_spi_write_reg(&reg_base->event, events);
>  
>  	mspi->count -= 1;
>  	if (mspi->count) {
>  		u32 word = mspi->get_tx(mspi);
>  
> -		mpc8xxx_spi_write_reg(&mspi->base->transmit, word);
> +		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
>  	} else {
>  		complete(&mspi->done);
>  	}
>  }
>  
> -static irqreturn_t mpc8xxx_spi_irq(s32 irq, void *context_data)
> +static irqreturn_t fsl_spi_irq(s32 irq, void *context_data)
>  {
>  	struct mpc8xxx_spi *mspi = context_data;
>  	irqreturn_t ret = IRQ_NONE;
>  	u32 events;
> +	struct fsl_spi_reg *reg_base = mspi->reg_base;
>  
>  	/* Get interrupt events(tx/rx) */
> -	events = mpc8xxx_spi_read_reg(&mspi->base->event);
> +	events = mpc8xxx_spi_read_reg(&reg_base->event);
>  	if (events)
>  		ret = IRQ_HANDLED;
>  
>  	dev_dbg(mspi->dev, "%s: events %x\n", __func__, events);
>  
>  	if (mspi->flags & SPI_CPM_MODE)
> -		mpc8xxx_spi_cpm_irq(mspi, events);
> +		fsl_spi_cpm_irq(mspi, events);
>  	else
> -		mpc8xxx_spi_cpu_irq(mspi, events);
> +		fsl_spi_cpu_irq(mspi, events);
>  
>  	return ret;
>  }
>  
> -static int mpc8xxx_spi_transfer(struct spi_device *spi,
> -				struct spi_message *m)
> +static void *fsl_spi_alloc_dummy_rx(void)
>  {
> -	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> -	unsigned long flags;
> +	mutex_lock(&fsl_dummy_rx_lock);
>  
> -	m->actual_length = 0;
> -	m->status = -EINPROGRESS;
> +	if (!fsl_dummy_rx)
> +		fsl_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
> +	if (fsl_dummy_rx)
> +		fsl_dummy_rx_refcnt++;
>  
> -	spin_lock_irqsave(&mpc8xxx_spi->lock, flags);
> -	list_add_tail(&m->queue, &mpc8xxx_spi->queue);
> -	queue_work(mpc8xxx_spi->workqueue, &mpc8xxx_spi->work);
> -	spin_unlock_irqrestore(&mpc8xxx_spi->lock, flags);
> +	mutex_unlock(&fsl_dummy_rx_lock);
>  
> -	return 0;
> +	return fsl_dummy_rx;
>  }
>  
> -
> -static void mpc8xxx_spi_cleanup(struct spi_device *spi)
> +static void fsl_spi_free_dummy_rx(void)
>  {
> -	kfree(spi->controller_state);
> -}
> +	mutex_lock(&fsl_dummy_rx_lock);
>  
> -static void *mpc8xxx_spi_alloc_dummy_rx(void)
> -{
> -	mutex_lock(&mpc8xxx_dummy_rx_lock);
> -
> -	if (!mpc8xxx_dummy_rx)
> -		mpc8xxx_dummy_rx = kmalloc(SPI_MRBLR, GFP_KERNEL);
> -	if (mpc8xxx_dummy_rx)
> -		mpc8xxx_dummy_rx_refcnt++;
> -
> -	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> -
> -	return mpc8xxx_dummy_rx;
> -}
> -
> -static void mpc8xxx_spi_free_dummy_rx(void)
> -{
> -	mutex_lock(&mpc8xxx_dummy_rx_lock);
> -
> -	switch (mpc8xxx_dummy_rx_refcnt) {
> +	switch (fsl_dummy_rx_refcnt) {
>  	case 0:
>  		WARN_ON(1);
>  		break;
>  	case 1:
> -		kfree(mpc8xxx_dummy_rx);
> -		mpc8xxx_dummy_rx = NULL;
> +		kfree(fsl_dummy_rx);
> +		fsl_dummy_rx = NULL;
>  		/* fall through */
>  	default:
> -		mpc8xxx_dummy_rx_refcnt--;
> +		fsl_dummy_rx_refcnt--;
>  		break;
>  	}
>  
> -	mutex_unlock(&mpc8xxx_dummy_rx_lock);
> +	mutex_unlock(&fsl_dummy_rx_lock);
>  }
>  
> -static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
> +static unsigned long fsl_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
>  {
>  	struct device *dev = mspi->dev;
>  	struct device_node *np = dev->of_node;
> @@ -869,7 +732,7 @@ static unsigned long mpc8xxx_spi_cpm_get_pram(struct mpc8xxx_spi *mspi)
>  	return pram_ofs;
>  }
>  
> -static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
> +static int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
>  {
>  	struct device *dev = mspi->dev;
>  	struct device_node *np = dev->of_node;
> @@ -881,7 +744,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
>  	if (!(mspi->flags & SPI_CPM_MODE))
>  		return 0;
>  
> -	if (!mpc8xxx_spi_alloc_dummy_rx())
> +	if (!fsl_spi_alloc_dummy_rx())
>  		return -ENOMEM;
>  
>  	if (mspi->flags & SPI_QE) {
> @@ -902,7 +765,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
>  		}
>  	}
>  
> -	pram_ofs = mpc8xxx_spi_cpm_get_pram(mspi);
> +	pram_ofs = fsl_spi_cpm_get_pram(mspi);
>  	if (IS_ERR_VALUE(pram_ofs)) {
>  		dev_err(dev, "can't allocate spi parameter ram\n");
>  		goto err_pram;
> @@ -922,7 +785,7 @@ static int mpc8xxx_spi_cpm_init(struct mpc8xxx_spi *mspi)
>  		goto err_dummy_tx;
>  	}
>  
> -	mspi->dma_dummy_rx = dma_map_single(dev, mpc8xxx_dummy_rx, SPI_MRBLR,
> +	mspi->dma_dummy_rx = dma_map_single(dev, fsl_dummy_rx, SPI_MRBLR,
>  					    DMA_FROM_DEVICE);
>  	if (dma_mapping_error(dev, mspi->dma_dummy_rx)) {
>  		dev_err(dev, "unable to map dummy rx buffer\n");
> @@ -960,11 +823,11 @@ err_dummy_tx:
>  err_bds:
>  	cpm_muram_free(pram_ofs);
>  err_pram:
> -	mpc8xxx_spi_free_dummy_rx();
> +	fsl_spi_free_dummy_rx();
>  	return -ENOMEM;
>  }
>  
> -static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
> +static void fsl_spi_cpm_free(struct mpc8xxx_spi *mspi)
>  {
>  	struct device *dev = mspi->dev;
>  
> @@ -972,30 +835,22 @@ static void mpc8xxx_spi_cpm_free(struct mpc8xxx_spi *mspi)
>  	dma_unmap_single(dev, mspi->dma_dummy_tx, PAGE_SIZE, DMA_TO_DEVICE);
>  	cpm_muram_free(cpm_muram_offset(mspi->tx_bd));
>  	cpm_muram_free(cpm_muram_offset(mspi->pram));
> -	mpc8xxx_spi_free_dummy_rx();
> +	fsl_spi_free_dummy_rx();
>  }
>  
> -static const char *mpc8xxx_spi_strmode(unsigned int flags)
> +static void fsl_spi_remove(struct mpc8xxx_spi *mspi)
>  {
> -	if (flags & SPI_QE_CPU_MODE) {
> -		return "QE CPU";
> -	} else if (flags & SPI_CPM_MODE) {
> -		if (flags & SPI_QE)
> -			return "QE";
> -		else if (flags & SPI_CPM2)
> -			return "CPM2";
> -		else
> -			return "CPM1";
> -	}
> -	return "CPU";
> +	iounmap(mspi->reg_base);
> +	fsl_spi_cpm_free(mspi);
>  }
>  
> -static struct spi_master * __devinit
> -mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
> +static struct spi_master * __devinit fsl_spi_probe(struct device *dev,
> +		struct resource *mem, unsigned int irq)
>  {
>  	struct fsl_spi_platform_data *pdata = dev->platform_data;
>  	struct spi_master *master;
>  	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_spi_reg *reg_base;
>  	u32 regval;
>  	int ret = 0;
>  
> @@ -1007,132 +862,77 @@ mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq)
>  
>  	dev_set_drvdata(dev, master);
>  
> -	/* the spi->mode bits understood by this driver: */
> -	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH
> -			| SPI_LSB_FIRST | SPI_LOOP;
> +	ret = mpc8xxx_spi_probe(dev, mem, irq);
> +	if (ret)
> +		goto err_probe;
>  
> -	master->setup = mpc8xxx_spi_setup;
> -	master->transfer = mpc8xxx_spi_transfer;
> -	master->cleanup = mpc8xxx_spi_cleanup;
> -	master->dev.of_node = dev->of_node;
> +	master->setup = fsl_spi_setup;
>  
>  	mpc8xxx_spi = spi_master_get_devdata(master);
> -	mpc8xxx_spi->dev = dev;
> -	mpc8xxx_spi->get_rx = mpc8xxx_spi_rx_buf_u8;
> -	mpc8xxx_spi->get_tx = mpc8xxx_spi_tx_buf_u8;
> -	mpc8xxx_spi->flags = pdata->flags;
> -	mpc8xxx_spi->spibrg = pdata->sysclk;
> +	mpc8xxx_spi->spi_do_one_msg = fsl_spi_do_one_msg;
> +	mpc8xxx_spi->spi_remove = fsl_spi_remove;
> +
>  
> -	ret = mpc8xxx_spi_cpm_init(mpc8xxx_spi);
> +	ret = fsl_spi_cpm_init(mpc8xxx_spi);
>  	if (ret)
>  		goto err_cpm_init;
>  
> -	mpc8xxx_spi->rx_shift = 0;
> -	mpc8xxx_spi->tx_shift = 0;
>  	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
>  		mpc8xxx_spi->rx_shift = 16;
>  		mpc8xxx_spi->tx_shift = 24;
>  	}
>  
> -	init_completion(&mpc8xxx_spi->done);
> -
> -	mpc8xxx_spi->base = ioremap(mem->start, resource_size(mem));
> -	if (mpc8xxx_spi->base == NULL) {
> +	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
> +	if (mpc8xxx_spi->reg_base == NULL) {
>  		ret = -ENOMEM;
>  		goto err_ioremap;
>  	}
>  
> -	mpc8xxx_spi->irq = irq;
> -
>  	/* Register for SPI Interrupt */
> -	ret = request_irq(mpc8xxx_spi->irq, mpc8xxx_spi_irq,
> -			  0, "mpc8xxx_spi", mpc8xxx_spi);
> +	ret = request_irq(mpc8xxx_spi->irq, fsl_spi_irq,
> +			  0, "fsl_spi", mpc8xxx_spi);
>  
>  	if (ret != 0)
> -		goto unmap_io;
> +		goto free_irq;
>  
> -	master->bus_num = pdata->bus_num;
> -	master->num_chipselect = pdata->max_chipselect;
> +	reg_base = mpc8xxx_spi->reg_base;
>  
>  	/* SPI controller initializations */
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mask, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->command, 0);
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->event, 0xffffffff);
> +	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->command, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
>  
>  	/* Enable SPI interface */
>  	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
>  	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
>  		regval |= SPMODE_OP;
>  
> -	mpc8xxx_spi_write_reg(&mpc8xxx_spi->base->mode, regval);
> -	spin_lock_init(&mpc8xxx_spi->lock);
> -	init_completion(&mpc8xxx_spi->done);
> -	INIT_WORK(&mpc8xxx_spi->work, mpc8xxx_spi_work);
> -	INIT_LIST_HEAD(&mpc8xxx_spi->queue);
> -
> -	mpc8xxx_spi->workqueue = create_singlethread_workqueue(
> -		dev_name(master->dev.parent));
> -	if (mpc8xxx_spi->workqueue == NULL) {
> -		ret = -EBUSY;
> -		goto free_irq;
> -	}
> +	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
>  
>  	ret = spi_register_master(master);
>  	if (ret < 0)
>  		goto unreg_master;
>  
> -	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", mpc8xxx_spi->base,
> +	dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base,
>  		 mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags));
>  
>  	return master;
>  
>  unreg_master:
> -	destroy_workqueue(mpc8xxx_spi->workqueue);
> -free_irq:
>  	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> -unmap_io:
> -	iounmap(mpc8xxx_spi->base);
> +free_irq:
> +	iounmap(mpc8xxx_spi->reg_base);
>  err_ioremap:
> -	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> +	fsl_spi_cpm_free(mpc8xxx_spi);
>  err_cpm_init:
> +err_probe:
>  	spi_master_put(master);
>  err:
>  	return ERR_PTR(ret);
>  }
>  
> -static int __devexit mpc8xxx_spi_remove(struct device *dev)
> -{
> -	struct mpc8xxx_spi *mpc8xxx_spi;
> -	struct spi_master *master;
> -
> -	master = dev_get_drvdata(dev);
> -	mpc8xxx_spi = spi_master_get_devdata(master);
> -
> -	flush_workqueue(mpc8xxx_spi->workqueue);
> -	destroy_workqueue(mpc8xxx_spi->workqueue);
> -	spi_unregister_master(master);
> -
> -	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> -	iounmap(mpc8xxx_spi->base);
> -	mpc8xxx_spi_cpm_free(mpc8xxx_spi);
> -
> -	return 0;
> -}
> -
> -struct mpc8xxx_spi_probe_info {
> -	struct fsl_spi_platform_data pdata;
> -	int *gpios;
> -	bool *alow_flags;
> -};
> -
> -static struct mpc8xxx_spi_probe_info *
> -to_of_pinfo(struct fsl_spi_platform_data *pdata)
> -{
> -	return container_of(pdata, struct mpc8xxx_spi_probe_info, pdata);
> -}
> -
> -static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
> +static void fsl_spi_cs_control(struct spi_device *spi, bool on)
>  {
>  	struct device *dev = spi->dev.parent;
>  	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data);
> @@ -1143,7 +943,7 @@ static void mpc8xxx_spi_cs_control(struct spi_device *spi, bool on)
>  	gpio_set_value(gpio, on ^ alow);
>  }
>  
> -static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
> +static int of_fsl_spi_get_chipselects(struct device *dev)
>  {
>  	struct device_node *np = dev->of_node;
>  	struct fsl_spi_platform_data *pdata = dev->platform_data;
> @@ -1204,7 +1004,7 @@ static int of_mpc8xxx_spi_get_chipselects(struct device *dev)
>  	}
>  
>  	pdata->max_chipselect = ngpios;
> -	pdata->cs_control = mpc8xxx_spi_cs_control;
> +	pdata->cs_control = fsl_spi_cs_control;
>  
>  	return 0;
>  
> @@ -1223,7 +1023,7 @@ err_alloc_flags:
>  	return ret;
>  }
>  
> -static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
> +static int of_fsl_spi_free_chipselects(struct device *dev)
>  {
>  	struct fsl_spi_platform_data *pdata = dev->platform_data;
>  	struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(pdata);
> @@ -1242,50 +1042,21 @@ static int of_mpc8xxx_spi_free_chipselects(struct device *dev)
>  	return 0;
>  }
>  
> -static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
> -					  const struct of_device_id *ofid)
> +static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
> +					const struct of_device_id *ofid)
>  {
>  	struct device *dev = &ofdev->dev;
>  	struct device_node *np = ofdev->dev.of_node;
> -	struct mpc8xxx_spi_probe_info *pinfo;
> -	struct fsl_spi_platform_data *pdata;
>  	struct spi_master *master;
>  	struct resource mem;
>  	struct resource irq;
> -	const void *prop;
>  	int ret = -ENOMEM;
>  
> -	pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL);
> -	if (!pinfo)
> -		return -ENOMEM;
> -
> -	pdata = &pinfo->pdata;
> -	dev->platform_data = pdata;
> -
> -	/* Allocate bus num dynamically. */
> -	pdata->bus_num = -1;
> -
> -	/* SPI controller is either clocked from QE or SoC clock. */
> -	pdata->sysclk = get_brgfreq();
> -	if (pdata->sysclk == -1) {
> -		pdata->sysclk = fsl_get_sys_freq();
> -		if (pdata->sysclk == -1) {
> -			ret = -ENODEV;
> -			goto err_clk;
> -		}
> -	}
> +	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
> +	if (ret)
> +		return ret;
>  
> -	prop = of_get_property(np, "mode", NULL);
> -	if (prop && !strcmp(prop, "cpu-qe"))
> -		pdata->flags = SPI_QE_CPU_MODE;
> -	else if (prop && !strcmp(prop, "qe"))
> -		pdata->flags = SPI_CPM_MODE | SPI_QE;
> -	else if (of_device_is_compatible(np, "fsl,cpm2-spi"))
> -		pdata->flags = SPI_CPM_MODE | SPI_CPM2;
> -	else if (of_device_is_compatible(np, "fsl,cpm1-spi"))
> -		pdata->flags = SPI_CPM_MODE | SPI_CPM1;
> -
> -	ret = of_mpc8xxx_spi_get_chipselects(dev);
> +	ret = of_fsl_spi_get_chipselects(dev);
>  	if (ret)
>  		goto err;
>  
> @@ -1299,7 +1070,7 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
>  		goto err;
>  	}
>  
> -	master = mpc8xxx_spi_probe(dev, &mem, irq.start);
> +	master = fsl_spi_probe(dev, &mem, irq.start);
>  	if (IS_ERR(master)) {
>  		ret = PTR_ERR(master);
>  		goto err;
> @@ -1308,42 +1079,40 @@ static int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
>  	return 0;
>  
>  err:
> -	of_mpc8xxx_spi_free_chipselects(dev);
> -err_clk:
> -	kfree(pinfo);
> +	of_fsl_spi_free_chipselects(dev);
>  	return ret;
>  }
>  
> -static int __devexit of_mpc8xxx_spi_remove(struct platform_device *ofdev)
> +static int __devexit of_fsl_spi_remove(struct platform_device *ofdev)
>  {
>  	int ret;
>  
>  	ret = mpc8xxx_spi_remove(&ofdev->dev);
>  	if (ret)
>  		return ret;
> -	of_mpc8xxx_spi_free_chipselects(&ofdev->dev);
> +	of_fsl_spi_free_chipselects(&ofdev->dev);
>  	return 0;
>  }
>  
> -static const struct of_device_id of_mpc8xxx_spi_match[] = {
> +static const struct of_device_id of_fsl_spi_match[] = {
>  	{ .compatible = "fsl,spi" },
> -	{},
> +	{}
>  };
> -MODULE_DEVICE_TABLE(of, of_mpc8xxx_spi_match);
> +MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
>  
> -static struct of_platform_driver of_mpc8xxx_spi_driver = {
> +static struct of_platform_driver of_fsl_spi_driver = {
>  	.driver = {
> -		.name = "mpc8xxx_spi",
> +		.name = "fsl_spi",
>  		.owner = THIS_MODULE,
> -		.of_match_table = of_mpc8xxx_spi_match,
> +		.of_match_table = of_fsl_spi_match,
>  	},
> -	.probe		= of_mpc8xxx_spi_probe,
> -	.remove		= __devexit_p(of_mpc8xxx_spi_remove),
> +	.probe		= of_fsl_spi_probe,
> +	.remove		= __devexit_p(of_fsl_spi_remove),
>  };
>  
>  #ifdef CONFIG_MPC832x_RDB
>  /*
> - * 				XXX XXX XXX
> + * XXX XXX XXX
>   * This is "legacy" platform driver, was used by the MPC8323E-RDB boards
>   * only. The driver should go away soon, since newer MPC8323E-RDB's device
>   * tree can work with OpenFirmware driver. But for now we support old trees
> @@ -1366,7 +1135,7 @@ static int __devinit plat_mpc8xxx_spi_probe(struct platform_device *pdev)
>  	if (irq <= 0)
>  		return -EINVAL;
>  
> -	master = mpc8xxx_spi_probe(&pdev->dev, mem, irq);
> +	master = fsl_spi_probe(&pdev->dev, mem, irq);
>  	if (IS_ERR(master))
>  		return PTR_ERR(master);
>  	return 0;
> @@ -1405,21 +1174,20 @@ static void __init legacy_driver_register(void) {}
>  static void __exit legacy_driver_unregister(void) {}
>  #endif /* CONFIG_MPC832x_RDB */
>  
> -static int __init mpc8xxx_spi_init(void)
> +static int __init fsl_spi_init(void)
>  {
>  	legacy_driver_register();
> -	return of_register_platform_driver(&of_mpc8xxx_spi_driver);
> +	return of_register_platform_driver(&of_fsl_spi_driver);
>  }
> +module_init(fsl_spi_init);
>  
> -static void __exit mpc8xxx_spi_exit(void)
> +static void __exit fsl_spi_exit(void)
>  {
> -	of_unregister_platform_driver(&of_mpc8xxx_spi_driver);
> +	of_unregister_platform_driver(&of_fsl_spi_driver);
>  	legacy_driver_unregister();
>  }
> -
> -module_init(mpc8xxx_spi_init);
> -module_exit(mpc8xxx_spi_exit);
> +module_exit(fsl_spi_exit);
>  
>  MODULE_AUTHOR("Kumar Gala");
> -MODULE_DESCRIPTION("Simple MPC8xxx SPI Driver");
> +MODULE_DESCRIPTION("Simple Freescale SPI Driver");
>  MODULE_LICENSE("GPL");
> -- 
> 1.6.4
> 
> 


From grant.likely at secretlab.ca  Tue Oct 12 23:41:42 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Tue, 12 Oct 2010 21:41:42 -0600
Subject: [PATCH v4 3/5] eSPI: add eSPI controller support
In-Reply-To: <1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101013034142.GC7254@angua.secretlab.ca>

On Tue, Oct 12, 2010 at 06:18:32PM +0800, Mingkai Hu wrote:
> Add eSPI controller support based on the library code spi_fsl_lib.c.
> 
> The eSPI controller is newer controller 85xx/Pxxx devices supported.
> There're some differences comparing to the SPI controller:
> 
> 1. Has different register map and different bit definition
>    So leave the code operated the register to the driver code, not
>    the common code.
> 
> 2. Support 4 dedicated chip selects
>    The software can't controll the chip selects directly, The SPCOM[CS]
>    field is used to select which chip selects is used, and the
>    SPCOM[TRANLEN] field is set to tell the controller how long the CS
>    signal need to be asserted. So the driver doesn't need the chipselect
>    related function when transfering data, just set corresponding register
>    fields to controll the chipseclect.
> 
> 3. Different Transmit/Receive FIFO access register behavior
>    For SPI controller, the Tx/Rx FIFO access register can hold only
>    one character regardless of the character length, but for eSPI
>    controller, the register can hold 4 or 2 characters according to
>    the character lengths. Access the Tx/Rx FIFO access register of the
>    eSPI controller will shift out/in 4/2 characters one time. For SPI
>    subsystem, the command and data are put into different transfers, so
>    we need to combine all the transfers to one transfer in order to pass
>    the transfer to eSPI controller.
> 
> 4. The max transaction length limitation
>    The max transaction length one time is limitted by the SPCOM[TRANSLEN]
>    field which is 0xFFFF. When used mkfs.ext2 command to create ext2
>    filesystem on the flash, the read length will exceed the max value of
>    the SPCOM[TRANSLEN] field.
> 
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>

Applied, thanks.

g.

> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
>  - Added support to the transaction that the length is grater than 0xFFFF.
>  - Made some changes according to Anton's comments.
> 
>  drivers/spi/Kconfig        |    9 +
>  drivers/spi/Makefile       |    1 +
>  drivers/spi/spi_fsl_espi.c |  748 ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/spi/spi_fsl_lib.h  |    3 +
>  4 files changed, 761 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/spi/spi_fsl_espi.c
> 
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 79ad06f..f6888af 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -195,6 +195,15 @@ config SPI_FSL_SPI
>  	  MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
>  	  MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
>  
> +config SPI_FSL_ESPI
> +	tristate "Freescale eSPI controller"
> +	depends on FSL_SOC
> +	select SPI_FSL_LIB
> +	help
> +	  This enables using the Freescale eSPI controllers in master mode.
> +	  From MPC8536, 85xx platform uses the controller, and all P10xx,
> +	  P20xx, P30xx,P40xx, P50xx uses this controller.
> +
>  config SPI_OMAP_UWIRE
>  	tristate "OMAP1 MicroWire"
>  	depends on ARCH_OMAP1
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 7974c21..833d17e 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC)		+= mpc512x_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
>  obj-$(CONFIG_SPI_MPC52xx)		+= mpc52xx_spi.o
>  obj-$(CONFIG_SPI_FSL_LIB)		+= spi_fsl_lib.o
> +obj-$(CONFIG_SPI_FSL_ESPI)		+= spi_fsl_espi.o
>  obj-$(CONFIG_SPI_FSL_SPI)		+= spi_fsl_spi.o
>  obj-$(CONFIG_SPI_PPC4xx)		+= spi_ppc4xx.o
>  obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
> diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
> new file mode 100644
> index 0000000..e3b4f64
> --- /dev/null
> +++ b/drivers/spi/spi_fsl_espi.c
> @@ -0,0 +1,748 @@
> +/*
> + * Freescale eSPI controller driver.
> + *
> + * Copyright 2010 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 <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/spi/spi.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/mm.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_spi.h>
> +#include <linux/interrupt.h>
> +#include <linux/err.h>
> +#include <sysdev/fsl_soc.h>
> +
> +#include "spi_fsl_lib.h"
> +
> +/* eSPI Controller registers */
> +struct fsl_espi_reg {
> +	__be32 mode;		/* 0x000 - eSPI mode register */
> +	__be32 event;		/* 0x004 - eSPI event register */
> +	__be32 mask;		/* 0x008 - eSPI mask register */
> +	__be32 command;		/* 0x00c - eSPI command register */
> +	__be32 transmit;	/* 0x010 - eSPI transmit FIFO access register*/
> +	__be32 receive;		/* 0x014 - eSPI receive FIFO access register*/
> +	u8 res[8];		/* 0x018 - 0x01c reserved */
> +	__be32 csmode[4];	/* 0x020 - 0x02c eSPI cs mode register */
> +};
> +
> +struct fsl_espi_transfer {
> +	const void *tx_buf;
> +	void *rx_buf;
> +	unsigned len;
> +	unsigned n_tx;
> +	unsigned n_rx;
> +	unsigned actual_length;
> +	int status;
> +};
> +
> +/* eSPI Controller mode register definitions */
> +#define SPMODE_ENABLE		(1 << 31)
> +#define SPMODE_LOOP		(1 << 30)
> +#define SPMODE_TXTHR(x)		((x) << 8)
> +#define SPMODE_RXTHR(x)		((x) << 0)
> +
> +/* eSPI Controller CS mode register definitions */
> +#define CSMODE_CI_INACTIVEHIGH	(1 << 31)
> +#define CSMODE_CP_BEGIN_EDGECLK	(1 << 30)
> +#define CSMODE_REV		(1 << 29)
> +#define CSMODE_DIV16		(1 << 28)
> +#define CSMODE_PM(x)		((x) << 24)
> +#define CSMODE_POL_1		(1 << 20)
> +#define CSMODE_LEN(x)		((x) << 16)
> +#define CSMODE_BEF(x)		((x) << 12)
> +#define CSMODE_AFT(x)		((x) << 8)
> +#define CSMODE_CG(x)		((x) << 3)
> +
> +/* Default mode/csmode for eSPI controller */
> +#define SPMODE_INIT_VAL (SPMODE_TXTHR(4) | SPMODE_RXTHR(3))
> +#define CSMODE_INIT_VAL (CSMODE_POL_1 | CSMODE_BEF(0) \
> +		| CSMODE_AFT(0) | CSMODE_CG(1))
> +
> +/* SPIE register values */
> +#define	SPIE_NE		0x00000200	/* Not empty */
> +#define	SPIE_NF		0x00000100	/* Not full */
> +
> +/* SPIM register values */
> +#define	SPIM_NE		0x00000200	/* Not empty */
> +#define	SPIM_NF		0x00000100	/* Not full */
> +#define SPIE_RXCNT(reg)     ((reg >> 24) & 0x3F)
> +#define SPIE_TXCNT(reg)     ((reg >> 16) & 0x3F)
> +
> +/* SPCOM register values */
> +#define SPCOM_CS(x)		((x) << 30)
> +#define SPCOM_TRANLEN(x)	((x) << 0)
> +#define	SPCOM_TRANLEN_MAX	0xFFFF	/* Max transaction length */
> +
> +static void fsl_espi_change_mode(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> +	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> +	struct fsl_espi_reg *reg_base = mspi->reg_base;
> +	__be32 __iomem *mode = &reg_base->csmode[spi->chip_select];
> +	__be32 __iomem *espi_mode = &reg_base->mode;
> +	u32 tmp;
> +	unsigned long flags;
> +
> +	/* Turn off IRQs locally to minimize time that SPI is disabled. */
> +	local_irq_save(flags);
> +
> +	/* Turn off SPI unit prior changing mode */
> +	tmp = mpc8xxx_spi_read_reg(espi_mode);
> +	mpc8xxx_spi_write_reg(espi_mode, tmp & ~SPMODE_ENABLE);
> +	mpc8xxx_spi_write_reg(mode, cs->hw_mode);
> +	mpc8xxx_spi_write_reg(espi_mode, tmp);
> +
> +	local_irq_restore(flags);
> +}
> +
> +static u32 fsl_espi_tx_buf_lsb(struct mpc8xxx_spi *mpc8xxx_spi)
> +{
> +	u32 data;
> +	u16 data_h;
> +	u16 data_l;
> +	const u32 *tx = mpc8xxx_spi->tx;
> +
> +	if (!tx)
> +		return 0;
> +
> +	data = *tx++ << mpc8xxx_spi->tx_shift;
> +	data_l = data & 0xffff;
> +	data_h = (data >> 16) & 0xffff;
> +	swab16s(&data_l);
> +	swab16s(&data_h);
> +	data = data_h | data_l;
> +
> +	mpc8xxx_spi->tx = tx;
> +	return data;
> +}
> +
> +static int fsl_espi_setup_transfer(struct spi_device *spi,
> +					struct spi_transfer *t)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	int bits_per_word = 0;
> +	u8 pm;
> +	u32 hz = 0;
> +	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> +
> +	if (t) {
> +		bits_per_word = t->bits_per_word;
> +		hz = t->speed_hz;
> +	}
> +
> +	/* spi_transfer level calls that work per-word */
> +	if (!bits_per_word)
> +		bits_per_word = spi->bits_per_word;
> +
> +	/* Make sure its a bit width we support [4..16] */
> +	if ((bits_per_word < 4) || (bits_per_word > 16))
> +		return -EINVAL;
> +
> +	if (!hz)
> +		hz = spi->max_speed_hz;
> +
> +	cs->rx_shift = 0;
> +	cs->tx_shift = 0;
> +	cs->get_rx = mpc8xxx_spi_rx_buf_u32;
> +	cs->get_tx = mpc8xxx_spi_tx_buf_u32;
> +	if (bits_per_word <= 8) {
> +		cs->rx_shift = 8 - bits_per_word;
> +	} else if (bits_per_word <= 16) {
> +		cs->rx_shift = 16 - bits_per_word;
> +		if (spi->mode & SPI_LSB_FIRST)
> +			cs->get_tx = fsl_espi_tx_buf_lsb;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	mpc8xxx_spi->rx_shift = cs->rx_shift;
> +	mpc8xxx_spi->tx_shift = cs->tx_shift;
> +	mpc8xxx_spi->get_rx = cs->get_rx;
> +	mpc8xxx_spi->get_tx = cs->get_tx;
> +
> +	bits_per_word = bits_per_word - 1;
> +
> +	/* mask out bits we are going to set */
> +	cs->hw_mode &= ~(CSMODE_LEN(0xF) | CSMODE_DIV16 | CSMODE_PM(0xF));
> +
> +	cs->hw_mode |= CSMODE_LEN(bits_per_word);
> +
> +	if ((mpc8xxx_spi->spibrg / hz) > 64) {
> +		cs->hw_mode |= CSMODE_DIV16;
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 64) + 1;
> +
> +		WARN_ONCE(pm > 16, "%s: Requested speed is too low: %d Hz. "
> +			  "Will use %d Hz instead.\n", dev_name(&spi->dev),
> +			  hz, mpc8xxx_spi->spibrg / 1024);
> +		if (pm > 16)
> +			pm = 16;
> +	} else {
> +		pm = (mpc8xxx_spi->spibrg - 1) / (hz * 4) + 1;
> +	}
> +	if (pm)
> +		pm--;
> +
> +	cs->hw_mode |= CSMODE_PM(pm);
> +
> +	fsl_espi_change_mode(spi);
> +	return 0;
> +}
> +
> +static int fsl_espi_cpu_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t,
> +		unsigned int len)
> +{
> +	u32 word;
> +	struct fsl_espi_reg *reg_base = mspi->reg_base;
> +
> +	mspi->count = len;
> +
> +	/* enable rx ints */
> +	mpc8xxx_spi_write_reg(&reg_base->mask, SPIM_NE);
> +
> +	/* transmit word */
> +	word = mspi->get_tx(mspi);
> +	mpc8xxx_spi_write_reg(&reg_base->transmit, word);
> +
> +	return 0;
> +}
> +
> +static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
> +	unsigned int len = t->len;
> +	u8 bits_per_word;
> +	int ret;
> +
> +	bits_per_word = spi->bits_per_word;
> +	if (t->bits_per_word)
> +		bits_per_word = t->bits_per_word;
> +
> +	mpc8xxx_spi->len = t->len;
> +	len = roundup(len, 4) / 4;
> +
> +	mpc8xxx_spi->tx = t->tx_buf;
> +	mpc8xxx_spi->rx = t->rx_buf;
> +
> +	INIT_COMPLETION(mpc8xxx_spi->done);
> +
> +	/* Set SPCOM[CS] and SPCOM[TRANLEN] field */
> +	if ((t->len - 1) > SPCOM_TRANLEN_MAX) {
> +		dev_err(mpc8xxx_spi->dev, "Transaction length (%d)"
> +				" beyond the SPCOM[TRANLEN] field\n", t->len);
> +		return -EINVAL;
> +	}
> +	mpc8xxx_spi_write_reg(&reg_base->command,
> +		(SPCOM_CS(spi->chip_select) | SPCOM_TRANLEN(t->len - 1)));
> +
> +	ret = fsl_espi_cpu_bufs(mpc8xxx_spi, t, len);
> +	if (ret)
> +		return ret;
> +
> +	wait_for_completion(&mpc8xxx_spi->done);
> +
> +	/* disable rx ints */
> +	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
> +
> +	return mpc8xxx_spi->count;
> +}
> +
> +static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
> +{
> +	if (cmd[1] && cmd[2] && cmd[3]) {
> +		cmd[1] = (u8)(addr >> 16);
> +		cmd[2] = (u8)(addr >> 8);
> +		cmd[3] = (u8)(addr >> 0);
> +	}
> +}
> +
> +static unsigned int fsl_espi_cmd2addr(u8 *cmd)
> +{
> +	if (cmd[1] && cmd[2] && cmd[3])
> +		return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
> +
> +	return 0;
> +}
> +
> +static void fsl_espi_do_trans(struct spi_message *m,
> +				struct fsl_espi_transfer *tr)
> +{
> +	struct spi_device *spi = m->spi;
> +	struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
> +	struct fsl_espi_transfer *espi_trans = tr;
> +	struct spi_message message;
> +	struct spi_transfer *t, *first, trans;
> +	int status = 0;
> +
> +	spi_message_init(&message);
> +	memset(&trans, 0, sizeof(trans));
> +
> +	first = list_first_entry(&m->transfers, struct spi_transfer,
> +			transfer_list);
> +	list_for_each_entry(t, &m->transfers, transfer_list) {
> +		if ((first->bits_per_word != t->bits_per_word) ||
> +			(first->speed_hz != t->speed_hz)) {
> +			espi_trans->status = -EINVAL;
> +			dev_err(mspi->dev, "bits_per_word/speed_hz should be"
> +					" same for the same SPI transfer\n");
> +			return;
> +		}
> +
> +		trans.speed_hz = t->speed_hz;
> +		trans.bits_per_word = t->bits_per_word;
> +		trans.delay_usecs = max(first->delay_usecs, t->delay_usecs);
> +	}
> +
> +	trans.len = espi_trans->len;
> +	trans.tx_buf = espi_trans->tx_buf;
> +	trans.rx_buf = espi_trans->rx_buf;
> +	spi_message_add_tail(&trans, &message);
> +
> +	list_for_each_entry(t, &message.transfers, transfer_list) {
> +		if (t->bits_per_word || t->speed_hz) {
> +			status = -EINVAL;
> +
> +			status = fsl_espi_setup_transfer(spi, t);
> +			if (status < 0)
> +				break;
> +		}
> +
> +		if (t->len)
> +			status = fsl_espi_bufs(spi, t);
> +
> +		if (status) {
> +			status = -EMSGSIZE;
> +			break;
> +		}
> +
> +		if (t->delay_usecs)
> +			udelay(t->delay_usecs);
> +	}
> +
> +	espi_trans->status = status;
> +	fsl_espi_setup_transfer(spi, NULL);
> +}
> +
> +static void fsl_espi_cmd_trans(struct spi_message *m,
> +				struct fsl_espi_transfer *trans, u8 *rx_buff)
> +{
> +	struct spi_transfer *t;
> +	u8 *local_buf;
> +	int i = 0;
> +	struct fsl_espi_transfer *espi_trans = trans;
> +
> +	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
> +	if (!local_buf) {
> +		espi_trans->status = -ENOMEM;
> +		return;
> +	}
> +
> +	list_for_each_entry(t, &m->transfers, transfer_list) {
> +		if (t->tx_buf) {
> +			memcpy(local_buf + i, t->tx_buf, t->len);
> +			i += t->len;
> +		}
> +	}
> +
> +	espi_trans->tx_buf = local_buf;
> +	espi_trans->rx_buf = local_buf + espi_trans->n_tx;
> +	fsl_espi_do_trans(m, espi_trans);
> +
> +	espi_trans->actual_length = espi_trans->len;
> +	kfree(local_buf);
> +}
> +
> +static void fsl_espi_rw_trans(struct spi_message *m,
> +				struct fsl_espi_transfer *trans, u8 *rx_buff)
> +{
> +	struct fsl_espi_transfer *espi_trans = trans;
> +	unsigned int n_tx = espi_trans->n_tx;
> +	unsigned int n_rx = espi_trans->n_rx;
> +	struct spi_transfer *t;
> +	u8 *local_buf;
> +	u8 *rx_buf = rx_buff;
> +	unsigned int trans_len;
> +	unsigned int addr;
> +	int i, pos, loop;
> +
> +	local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
> +	if (!local_buf) {
> +		espi_trans->status = -ENOMEM;
> +		return;
> +	}
> +
> +	for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
> +		trans_len = n_rx - pos;
> +		if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
> +			trans_len = SPCOM_TRANLEN_MAX - n_tx;
> +
> +		i = 0;
> +		list_for_each_entry(t, &m->transfers, transfer_list) {
> +			if (t->tx_buf) {
> +				memcpy(local_buf + i, t->tx_buf, t->len);
> +				i += t->len;
> +			}
> +		}
> +
> +		addr = fsl_espi_cmd2addr(local_buf);
> +		addr += pos;
> +		fsl_espi_addr2cmd(addr, local_buf);
> +
> +		espi_trans->n_tx = n_tx;
> +		espi_trans->n_rx = trans_len;
> +		espi_trans->len = trans_len + n_tx;
> +		espi_trans->tx_buf = local_buf;
> +		espi_trans->rx_buf = local_buf + n_tx;
> +		fsl_espi_do_trans(m, espi_trans);
> +
> +		memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
> +
> +		if (loop > 0)
> +			espi_trans->actual_length += espi_trans->len - n_tx;
> +		else
> +			espi_trans->actual_length += espi_trans->len;
> +	}
> +
> +	kfree(local_buf);
> +}
> +
> +static void fsl_espi_do_one_msg(struct spi_message *m)
> +{
> +	struct spi_transfer *t;
> +	u8 *rx_buf = NULL;
> +	unsigned int n_tx = 0;
> +	unsigned int n_rx = 0;
> +	struct fsl_espi_transfer espi_trans;
> +
> +	list_for_each_entry(t, &m->transfers, transfer_list) {
> +		if (t->tx_buf)
> +			n_tx += t->len;
> +		if (t->rx_buf) {
> +			n_rx += t->len;
> +			rx_buf = t->rx_buf;
> +		}
> +	}
> +
> +	espi_trans.n_tx = n_tx;
> +	espi_trans.n_rx = n_rx;
> +	espi_trans.len = n_tx + n_rx;
> +	espi_trans.actual_length = 0;
> +	espi_trans.status = 0;
> +
> +	if (!rx_buf)
> +		fsl_espi_cmd_trans(m, &espi_trans, NULL);
> +	else
> +		fsl_espi_rw_trans(m, &espi_trans, rx_buf);
> +
> +	m->actual_length = espi_trans.actual_length;
> +	m->status = espi_trans.status;
> +	m->complete(m->context);
> +}
> +
> +static int fsl_espi_setup(struct spi_device *spi)
> +{
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_espi_reg *reg_base;
> +	int retval;
> +	u32 hw_mode;
> +	u32 loop_mode;
> +	struct spi_mpc8xxx_cs *cs = spi->controller_state;
> +
> +	if (!spi->max_speed_hz)
> +		return -EINVAL;
> +
> +	if (!cs) {
> +		cs = kzalloc(sizeof *cs, GFP_KERNEL);
> +		if (!cs)
> +			return -ENOMEM;
> +		spi->controller_state = cs;
> +	}
> +
> +	mpc8xxx_spi = spi_master_get_devdata(spi->master);
> +	reg_base = mpc8xxx_spi->reg_base;
> +
> +	hw_mode = cs->hw_mode; /* Save orginal settings */
> +	cs->hw_mode = mpc8xxx_spi_read_reg(
> +			&reg_base->csmode[spi->chip_select]);
> +	/* mask out bits we are going to set */
> +	cs->hw_mode &= ~(CSMODE_CP_BEGIN_EDGECLK | CSMODE_CI_INACTIVEHIGH
> +			 | CSMODE_REV);
> +
> +	if (spi->mode & SPI_CPHA)
> +		cs->hw_mode |= CSMODE_CP_BEGIN_EDGECLK;
> +	if (spi->mode & SPI_CPOL)
> +		cs->hw_mode |= CSMODE_CI_INACTIVEHIGH;
> +	if (!(spi->mode & SPI_LSB_FIRST))
> +		cs->hw_mode |= CSMODE_REV;
> +
> +	/* Handle the loop mode */
> +	loop_mode = mpc8xxx_spi_read_reg(&reg_base->mode);
> +	loop_mode &= ~SPMODE_LOOP;
> +	if (spi->mode & SPI_LOOP)
> +		loop_mode |= SPMODE_LOOP;
> +	mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
> +
> +	retval = fsl_espi_setup_transfer(spi, NULL);
> +	if (retval < 0) {
> +		cs->hw_mode = hw_mode; /* Restore settings */
> +		return retval;
> +	}
> +	return 0;
> +}
> +
> +void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
> +{
> +	struct fsl_espi_reg *reg_base = mspi->reg_base;
> +
> +	/* We need handle RX first */
> +	if (events & SPIE_NE) {
> +		u32 rx_data;
> +
> +		/* Spin until RX is done */
> +		while (SPIE_RXCNT(events) < min(4, mspi->len)) {
> +			cpu_relax();
> +			events = mpc8xxx_spi_read_reg(&reg_base->event);
> +		}
> +		mspi->len -= 4;
> +
> +		rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
> +
> +		if (mspi->rx)
> +			mspi->get_rx(rx_data, mspi);
> +	}
> +
> +	if (!(events & SPIE_NF)) {
> +		int ret;
> +
> +		/* spin until TX is done */
> +		ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
> +				&reg_base->event)) & SPIE_NF) == 0, 1000, 0);
> +		if (!ret) {
> +			dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
> +			return;
> +		}
> +	}
> +
> +	/* Clear the events */
> +	mpc8xxx_spi_write_reg(&reg_base->event, events);
> +
> +	mspi->count -= 1;
> +	if (mspi->count) {
> +		u32 word = mspi->get_tx(mspi);
> +
> +		mpc8xxx_spi_write_reg(&reg_base->transmit, word);
> +	} else {
> +		complete(&mspi->done);
> +	}
> +}
> +
> +static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
> +{
> +	struct mpc8xxx_spi *mspi = context_data;
> +	struct fsl_espi_reg *reg_base = mspi->reg_base;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 events;
> +
> +	/* Get interrupt events(tx/rx) */
> +	events = mpc8xxx_spi_read_reg(&reg_base->event);
> +	if (events)
> +		ret = IRQ_HANDLED;
> +
> +	dev_vdbg(mspi->dev, "%s: events %x\n", __func__, events);
> +
> +	fsl_espi_cpu_irq(mspi, events);
> +
> +	return ret;
> +}
> +
> +static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
> +{
> +	iounmap(mspi->reg_base);
> +}
> +
> +static struct spi_master * __devinit fsl_espi_probe(struct device *dev,
> +		struct resource *mem, unsigned int irq)
> +{
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	struct spi_master *master;
> +	struct mpc8xxx_spi *mpc8xxx_spi;
> +	struct fsl_espi_reg *reg_base;
> +	u32 regval;
> +	int i, ret = 0;
> +
> +	master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi));
> +	if (!master) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	dev_set_drvdata(dev, master);
> +
> +	ret = mpc8xxx_spi_probe(dev, mem, irq);
> +	if (ret)
> +		goto err_probe;
> +
> +	master->setup = fsl_espi_setup;
> +
> +	mpc8xxx_spi = spi_master_get_devdata(master);
> +	mpc8xxx_spi->spi_do_one_msg = fsl_espi_do_one_msg;
> +	mpc8xxx_spi->spi_remove = fsl_espi_remove;
> +
> +	mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
> +	if (!mpc8xxx_spi->reg_base) {
> +		ret = -ENOMEM;
> +		goto err_probe;
> +	}
> +
> +	reg_base = mpc8xxx_spi->reg_base;
> +
> +	/* Register for SPI Interrupt */
> +	ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
> +			  0, "fsl_espi", mpc8xxx_spi);
> +	if (ret)
> +		goto free_irq;
> +
> +	if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
> +		mpc8xxx_spi->rx_shift = 16;
> +		mpc8xxx_spi->tx_shift = 24;
> +	}
> +
> +	/* SPI controller initializations */
> +	mpc8xxx_spi_write_reg(&reg_base->mode, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->mask, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->command, 0);
> +	mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
> +
> +	/* Init eSPI CS mode register */
> +	for (i = 0; i < pdata->max_chipselect; i++)
> +		mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
> +
> +	/* Enable SPI interface */
> +	regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
> +
> +	mpc8xxx_spi_write_reg(&reg_base->mode, regval);
> +
> +	ret = spi_register_master(master);
> +	if (ret < 0)
> +		goto unreg_master;
> +
> +	dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
> +
> +	return master;
> +
> +unreg_master:
> +	free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
> +free_irq:
> +	iounmap(mpc8xxx_spi->reg_base);
> +err_probe:
> +	spi_master_put(master);
> +err:
> +	return ERR_PTR(ret);
> +}
> +
> +static int of_fsl_espi_get_chipselects(struct device *dev)
> +{
> +	struct device_node *np = dev->of_node;
> +	struct fsl_spi_platform_data *pdata = dev->platform_data;
> +	const u32 *prop;
> +	int len;
> +
> +	prop = of_get_property(np, "fsl,espi-num-chipselects", &len);
> +	if (!prop || len < sizeof(*prop)) {
> +		dev_err(dev, "No 'fsl,espi-num-chipselects' property\n");
> +		return -EINVAL;
> +	}
> +
> +	pdata->max_chipselect = *prop;
> +	pdata->cs_control = NULL;
> +
> +	return 0;
> +}
> +
> +static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
> +					const struct of_device_id *ofid)
> +{
> +	struct device *dev = &ofdev->dev;
> +	struct device_node *np = ofdev->dev.of_node;
> +	struct spi_master *master;
> +	struct resource mem;
> +	struct resource irq;
> +	int ret = -ENOMEM;
> +
> +	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
> +	if (ret)
> +		return ret;
> +
> +	ret = of_fsl_espi_get_chipselects(dev);
> +	if (ret)
> +		goto err;
> +
> +	ret = of_address_to_resource(np, 0, &mem);
> +	if (ret)
> +		goto err;
> +
> +	ret = of_irq_to_resource(np, 0, &irq);
> +	if (!ret) {
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +
> +	master = fsl_espi_probe(dev, &mem, irq.start);
> +	if (IS_ERR(master)) {
> +		ret = PTR_ERR(master);
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	return ret;
> +}
> +
> +static int __devexit of_fsl_espi_remove(struct platform_device *dev)
> +{
> +	return mpc8xxx_spi_remove(&dev->dev);
> +}
> +
> +static const struct of_device_id of_fsl_espi_match[] = {
> +	{ .compatible = "fsl,mpc8536-espi" },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
> +
> +static struct of_platform_driver fsl_espi_driver = {
> +	.driver = {
> +		.name = "fsl_espi",
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_fsl_espi_match,
> +	},
> +	.probe		= of_fsl_espi_probe,
> +	.remove		= __devexit_p(of_fsl_espi_remove),
> +};
> +
> +static int __init fsl_espi_init(void)
> +{
> +	return of_register_platform_driver(&fsl_espi_driver);
> +}
> +module_init(fsl_espi_init);
> +
> +static void __exit fsl_espi_exit(void)
> +{
> +	of_unregister_platform_driver(&fsl_espi_driver);
> +}
> +module_exit(fsl_espi_exit);
> +
> +MODULE_AUTHOR("Mingkai Hu");
> +MODULE_DESCRIPTION("Enhanced Freescale SPI Driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
> index 6ae8949..15aa6c2 100644
> --- a/drivers/spi/spi_fsl_lib.h
> +++ b/drivers/spi/spi_fsl_lib.h
> @@ -26,6 +26,9 @@ struct mpc8xxx_spi {
>  	/* rx & tx bufs from the spi_transfer */
>  	const void *tx;
>  	void *rx;
> +#ifdef CONFIG_SPI_FSL_ESPI
> +	int len;
> +#endif
>  
>  	int subblock;
>  	struct spi_pram __iomem *pram;
> -- 
> 1.6.4
> 
> 


From grant.likely at secretlab.ca  Tue Oct 12 23:41:55 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Tue, 12 Oct 2010 21:41:55 -0600
Subject: [PATCH v4 4/5] powerpc/of: add eSPI controller dts bindings
	and DTS modification
In-Reply-To: <1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101013034155.GD7254@angua.secretlab.ca>

On Tue, Oct 12, 2010 at 06:18:33PM +0800, Mingkai Hu wrote:
> Also modifiy the document of cell-index in SPI controller. Add the
> SPI flash(s25fl128p01) support on p4080ds and mpc8536ds board.
> 
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>

Applied, thanks.

g.

> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
> 
>  Documentation/powerpc/dts-bindings/fsl/spi.txt |   24 ++++++++++-
>  arch/powerpc/boot/dts/mpc8536ds.dts            |   52 ++++++++++++++++++++++++
>  arch/powerpc/boot/dts/p4080ds.dts              |   11 ++---
>  3 files changed, 79 insertions(+), 8 deletions(-)
> 
> diff --git a/Documentation/powerpc/dts-bindings/fsl/spi.txt b/Documentation/powerpc/dts-bindings/fsl/spi.txt
> index 80510c0..777abd7 100644
> --- a/Documentation/powerpc/dts-bindings/fsl/spi.txt
> +++ b/Documentation/powerpc/dts-bindings/fsl/spi.txt
> @@ -1,7 +1,9 @@
>  * SPI (Serial Peripheral Interface)
>  
>  Required properties:
> -- cell-index : SPI controller index.
> +- cell-index : QE SPI subblock index.
> +		0: QE subblock SPI1
> +		1: QE subblock SPI2
>  - compatible : should be "fsl,spi".
>  - mode : the SPI operation mode, it can be "cpu" or "cpu-qe".
>  - reg : Offset and length of the register set for the device
> @@ -29,3 +31,23 @@ Example:
>  		gpios = <&gpio 18 1	// device reg=<0>
>  			 &gpio 19 1>;	// device reg=<1>
>  	};
> +
> +
> +* eSPI (Enhanced Serial Peripheral Interface)
> +
> +Required properties:
> +- compatible : should be "fsl,mpc8536-espi".
> +- reg : Offset and length of the register set for the device.
> +- interrupts : should contain eSPI interrupt, the device has one interrupt.
> +- fsl,espi-num-chipselects : the number of the chipselect signals.
> +
> +Example:
> +	spi at 110000 {
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		compatible = "fsl,mpc8536-espi";
> +		reg = <0x110000 0x1000>;
> +		interrupts = <53 0x2>;
> +		interrupt-parent = <&mpic>;
> +		fsl,espi-num-chipselects = <4>;
> +	};
> diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts
> index 815cebb..a75c10e 100644
> --- a/arch/powerpc/boot/dts/mpc8536ds.dts
> +++ b/arch/powerpc/boot/dts/mpc8536ds.dts
> @@ -108,6 +108,58 @@
>  			};
>  		};
>  
> +		spi at 7000 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			compatible = "fsl,mpc8536-espi";
> +			reg = <0x7000 0x1000>;
> +			interrupts = <59 0x2>;
> +			interrupt-parent = <&mpic>;
> +			fsl,espi-num-chipselects = <4>;
> +
> +			flash at 0 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				compatible = "spansion,s25sl12801";
> +				reg = <0>;
> +				spi-max-frequency = <40000000>;
> +				partition at u-boot {
> +					label = "u-boot";
> +					reg = <0x00000000 0x00100000>;
> +					read-only;
> +				};
> +				partition at kernel {
> +					label = "kernel";
> +					reg = <0x00100000 0x00500000>;
> +					read-only;
> +				};
> +				partition at dtb {
> +					label = "dtb";
> +					reg = <0x00600000 0x00100000>;
> +					read-only;
> +				};
> +				partition at fs {
> +					label = "file system";
> +					reg = <0x00700000 0x00900000>;
> +				};
> +			};
> +			flash at 1 {
> +				compatible = "spansion,s25sl12801";
> +				reg = <1>;
> +				spi-max-frequency = <40000000>;
> +			};
> +			flash at 2 {
> +				compatible = "spansion,s25sl12801";
> +				reg = <2>;
> +				spi-max-frequency = <40000000>;
> +			};
> +			flash at 3 {
> +				compatible = "spansion,s25sl12801";
> +				reg = <3>;
> +				spi-max-frequency = <40000000>;
> +			};
> +		};
> +
>  		dma at 21300 {
>  			#address-cells = <1>;
>  			#size-cells = <1>;
> diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
> index 2f0de24..5b7fc29 100644
> --- a/arch/powerpc/boot/dts/p4080ds.dts
> +++ b/arch/powerpc/boot/dts/p4080ds.dts
> @@ -236,22 +236,19 @@
>  		};
>  
>  		spi at 110000 {
> -			cell-index = <0>;
>  			#address-cells = <1>;
>  			#size-cells = <0>;
> -			compatible = "fsl,espi";
> +			compatible = "fsl,p4080-espi", "fsl,mpc8536-espi";
>  			reg = <0x110000 0x1000>;
>  			interrupts = <53 0x2>;
>  			interrupt-parent = <&mpic>;
> -			espi,num-ss-bits = <4>;
> -			mode = "cpu";
> +			fsl,espi-num-chipselects = <4>;
>  
> -			fsl_m25p80 at 0 {
> +			flash at 0 {
>  				#address-cells = <1>;
>  				#size-cells = <1>;
> -				compatible = "fsl,espi-flash";
> +				compatible = "spansion,s25sl12801";
>  				reg = <0>;
> -				linux,modalias = "fsl_m25p80";
>  				spi-max-frequency = <40000000>; /* input clock */
>  				partition at u-boot {
>  					label = "u-boot";
> -- 
> 1.6.4
> 
> 


From grant.likely at secretlab.ca  Tue Oct 12 23:44:37 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Tue, 12 Oct 2010 21:44:37 -0600
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the
	partitions by OF node
In-Reply-To: <1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <20101013034437.GE7254@angua.secretlab.ca>

On Tue, Oct 12, 2010 at 06:18:34PM +0800, Mingkai Hu wrote:
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
> Acked-by: Grant Likely <grant.likely at secretlab.ca>

dwmw2: what are your thoughts on this one?

g.



> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
>  - Made changes according to Grant's comments.
> 
>  drivers/mtd/devices/m25p80.c |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 6f512b5..9d20738 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -924,6 +924,11 @@ static int __devinit m25p_probe(struct spi_device *spi)
>  			nr_parts = data->nr_parts;
>  		}
>  
> +		if (nr_parts <= 0 && spi->dev.of_node) {
> +			nr_parts = of_mtd_parse_partitions(&spi->dev,
> +					spi->dev.of_node, &parts);
> +		}
> +
>  		if (nr_parts > 0) {
>  			for (i = 0; i < nr_parts; i++) {
>  				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
> -- 
> 1.6.4
> 
> 


From jacmet at sunsite.dk  Wed Oct 13 06:35:56 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Wed, 13 Oct 2010 12:35:56 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
	(Karl Beldan's message of "Tue, 12 Oct 2010 15:16:40 +0200")
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
Message-ID: <87zkui2xdf.fsf@macbook.be.48ers.dk>

>>>>> "Karl" == Karl Beldan <karl.beldan at gmail.com> writes:

Hi,

 >> But how about teaching squashfs to understand mtdX and mtd:name syntax
 >> instead?

 Karl> I would not do that, squashfs and co just ask for a block device,
 Karl> putting mtdx syntax awareness in each of them just does not seem
 Karl> a good fit to me.

FYI, patches for direct mtd access in squashfs (E.G. for systems not
needing the block layer at all) were posted a while ago:

http://thread.gmane.org/gmane.linux.kernel/962226/focus=968074

-- 
Bye, Peter Korsgaard


From karl.beldan at gmail.com  Wed Oct 13 07:16:26 2010
From: karl.beldan at gmail.com (Karl Beldan)
Date: Wed, 13 Oct 2010 13:16:26 +0200
Subject: [RFC] do_mounts: Allow mtd names for non-flash block filesystems
In-Reply-To: <87zkui2xdf.fsf@macbook.be.48ers.dk>
References: <1286398974-12114-1-git-send-email-karl.beldan@gmail.com>
	<1286825063.1742.13.camel@brekeke>
	<AANLkTi=A6djk8hOgLOg045f5XiiwkOYS2QtzOUwiT+Bo@mail.gmail.com>
	<87zkui2xdf.fsf@macbook.be.48ers.dk>
Message-ID: <AANLkTim7eYVNtraU7uv5czh+JP3mKStgd4K_2aXHCfAo@mail.gmail.com>

On Wed, Oct 13, 2010 at 12:35 PM, Peter Korsgaard <jacmet at sunsite.dk> wrote:
>>>>>> "Karl" == Karl Beldan <karl.beldan at gmail.com> writes:
>
> Hi,
>
> ?>> But how about teaching squashfs to understand mtdX and mtd:name syntax
> ?>> instead?
>
> ?Karl> I would not do that, squashfs and co just ask for a block device,
> ?Karl> putting mtdx syntax awareness in each of them just does not seem
> ?Karl> a good fit to me.
>
> FYI, patches for direct mtd access in squashfs (E.G. for systems not
> needing the block layer at all) were posted a while ago:
>
> http://thread.gmane.org/gmane.linux.kernel/962226/focus=968074
>

Hi,

This is interesting work, I saw some time ago that a french company,
Free Electrons, was offering an internship on this very subject.
If squashfs would undergo such changes it could use something like
get_sb_mtd() as jffs2 does and do_mount would require no change to
understand mtd:name, yet the naming scheme would remain not-generic
and the mtd naming scheme would remain in mtd/mtdsuper.



-- 
Karl


From hjk at linutronix.de  Wed Oct 13 12:30:05 2010
From: hjk at linutronix.de (Hans J. Koch)
Date: Wed, 13 Oct 2010 18:30:05 +0200
Subject: ubifs: sync() causes writes even if nothing is changed
Message-ID: <20101013163005.GB1889@silverbox.local>

Running this command:

# while true ; do sync; sleep 1; done

causes two eraseblocks being erased every second, although there
are no writes to the ubifs filesystem. I hacked some printks into
my NAND driver that print page_address and column for each erase.
With that, I get this output every second:

...
[   63.701765] erase p=0x0000ae40 c=0xffffffff
[   63.706534] erase p=0xffffffff c=0xffffffff
[   63.725492] erase p=0x0000ae80 c=0xffffffff
[   63.730260] erase p=0xffffffff c=0xffffffff
...


From bogus@does.not.exist.com  Sat Oct  9 07:11:57 2010
From: bogus@does.not.exist.com ()
Date: Sat, 09 Oct 2010 11:11:57 -0000
Subject: No subject
Message-ID: <mailman.4.1286987289.18522.linux-mtd@lists.infradead.org>

garbage collector that is triggered on every sync() and writes
something even if nothing has changed.

Is that really needed?

Thanks,
Hans



From r61911 at freescale.com  Wed Oct 13 23:09:02 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Thu, 14 Oct 2010 11:09:02 +0800
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
	flash partitions
In-Reply-To: <20101004103813.14d04956@udp111988uds.am.freescale.net>
References: <20100920131907.GA2184@oksana.dev.rtsoft.ru><3850A844E6A3854C827AC5C0BEC7B60A256099@zch01exm23.fsl.freescale.net>
	<20101004103813.14d04956@udp111988uds.am.freescale.net>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B02B7@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Monday, October 04, 2010 23:38 PM
> To: Zang Roy-R61911
> Cc: Anton Vorontsov; linux-mtd at lists.infradead.org;
dwmw2 at infradead.org;
> dedekind1 at gmail.com; akpm at linux-foundation.org; Lan Chunhe-B25806;
Wood Scott-
> B07421; Gala Kumar-B11780; linuxppc-dev at ozlabs.org
> Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver
detect nand
> flash partitions
> 
> On Sat, 2 Oct 2010 05:36:27 -0700
> "Zang Roy-R61911" <r61911 at freescale.com> wrote:
> 
> >
> >
> > > -----Original Message-----
> > > From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> > > Sent: Monday, September 20, 2010 21:19 PM
> > > To: Zang Roy-R61911
> > > Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
> dedekind1 at gmail.com;
> > > akpm at linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421;
Gala
> Kumar-
> > > B11780; linuxppc-dev at ozlabs.org
> > > Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver
detect
> nand
> > > flash partitions
> > >
> > > On Fri, Sep 17, 2010 at 03:01:08PM +0800, Roy Zang wrote:
> > > [...]
> > > > +static struct mutex fsl_elbc_nand_mutex;
> > > > +
> > > > +static int __devinit fsl_elbc_nand_probe(struct platform_device
*dev)
> > > >  {
> > > > -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > > > +	struct fsl_lbc_regs __iomem *lbc;
> > > >  	struct fsl_elbc_mtd *priv;
> > > >  	struct resource res;
> > > > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> > >
> > > No need for = NULL.
> > Any harm? Or just personal habit or style? Can you explain about
why?
> 
> Besides not wanting superfluous code on general principle, it could
> hide a bug if in the future the real initialization is missing on some
> code path.  It would become a runtime NULL dereference rather than a
> compiler warning.

Not exactly.
Per my understand, if the pointer will definitely be assigned in code
path,
it is not necessary to init it when define. for example,

char c;
char b;
char *a;
if (condition)
	a = &c;
else
	a = &b;
...

for other case, if the path will not ensure the pointer assignment, it
will be inited
when define to avoid warning. for example,

char c;
char *a = NULL;
if (condition)
	a = &c;
...

Thanks.
Roy






From r61911 at freescale.com  Thu Oct 14 00:14:12 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Thu, 14 Oct 2010 12:14:12 +0800
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
	flash partitions
In-Reply-To: <20100920131907.GA2184@oksana.dev.rtsoft.ru>
References: <1284706869-12555-1-git-send-email-tie-fei.zang@freescale.com>
	<1284706869-12555-2-git-send-email-tie-fei.zang@freescale.com>
	<20100920131907.GA2184@oksana.dev.rtsoft.ru>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B02EF@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Monday, September 20, 2010 21:19 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org; dedekind1 at gmail.com;
> akpm at linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> B11780; linuxppc-dev at ozlabs.org
> Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
> flash partitions
> 
> On Fri, Sep 17, 2010 at 03:01:08PM +0800, Roy Zang wrote:
> [...]
> > +static struct mutex fsl_elbc_nand_mutex;
> > +
> > +static int __devinit fsl_elbc_nand_probe(struct platform_device *dev)
> >  {
> > -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > +	struct fsl_lbc_regs __iomem *lbc;
> >  	struct fsl_elbc_mtd *priv;
> >  	struct resource res;
> > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> 
> No need for = NULL.
> 
> [...]
> > -	ctrl->chips[bank] = priv;
> > +	mutex_init(&fsl_elbc_nand_mutex);
> 
> This may cause all sorts of misbehaviours, e.g.
> 
> A: mutex_init(foo)
> A: mutex_lock(foo)
> B: mutex_init(foo)   <- destroyed "A"-context mutex.
> A: mutex_unlock(foo) <- oops
> 
> Instead of dynamically initializing the mutex, just define it
> with DEFINE_MUTEX() above.
> 
> (Btw, #include <linux/mutex.h> is needed.)
> 
> > +
> > +	mutex_lock(&fsl_elbc_nand_mutex);
> [...]
> > -static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
> > +static int fsl_elbc_nand_remove(struct platform_device *dev)
> [...]
> > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
> [...]
> > +		if (elbc_fcm_ctrl->chips[i])
> > +			fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
> [...]
> > +	fsl_lbc_ctrl_dev->nand = NULL;
> > +	kfree(elbc_fcm_ctrl);
> 
> Will cause NULL dereference and/or use-after-free for other
> elbc nand instances. To avoid that, reference counting for
> elbc_fcm_ctrl is required.
Make sense.
will update.
Roy

From r61911 at freescale.com  Thu Oct 14 02:43:38 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Thu, 14 Oct 2010 14:43:38 +0800
Subject: [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt common
	to elbc devices
In-Reply-To: <20100920153718.GA4411@oksana.dev.rtsoft.ru>
References: <1284706869-12555-1-git-send-email-tie-fei.zang@freescale.com>
	<20100920153718.GA4411@oksana.dev.rtsoft.ru>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B0329@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru at gmail.com]
> Sent: Monday, September 20, 2010 23:37 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org; dedekind1 at gmail.com;
> akpm at linux-foundation.org; Lan Chunhe-B25806; Wood Scott-B07421; Gala Kumar-
> B11780; linuxppc-dev at ozlabs.org
> Subject: Re: [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt common
> to elbc devices
> 
> On Fri, Sep 17, 2010 at 03:01:07PM +0800, Roy Zang wrote:

[snip]

> >  int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
> >  {
> >  	int ret = 0;
> >  	unsigned long flags;
> [...]
> > +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev->dev.of_node) {
> > +		dev_err(&dev->dev, "Device OF-Node is NULL");
> > +		return -EFAULT;
> > +	}
> > +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
> 
> Btw, the code in the NAND driver checks for !fsl_lbc_ctrl_dev.
> 
> So it might make sense to assign the global variable after the
> struct is fully initialized.
What struct?
assign the global variable in nand driver? 
I'd prefer init it in the lbc code.
There may be other lbc device, who will use this  global variable.

> 
> > +	if (!fsl_lbc_ctrl_dev)
> > +		return -ENOMEM;
> > +
> > +	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
> > +
> > +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
> > +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
> > +
> > +	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
> > +	if (!fsl_lbc_ctrl_dev->regs) {
> > +		dev_err(&dev->dev, "failed to get memory region\n");
> > +		ret = -ENODEV;
> > +		goto err;
> > +	}
> > +
> > +	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
> > +	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
> > +		dev_err(&dev->dev, "failed to get irq resource\n");
> > +		ret = -ENODEV;
> > +		goto err;
> > +	}
> > +
> > +	fsl_lbc_ctrl_dev->dev = &dev->dev;
> > +
> > +	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
> > +	if (ret < 0)
> > +		goto err;
> > +
> > +	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
> > +				"fsl-lbc", fsl_lbc_ctrl_dev);
> > +	if (ret != 0) {
> > +		dev_err(&dev->dev, "failed to install irq (%d)\n",
> > +			fsl_lbc_ctrl_dev->irq);
> > +		ret = fsl_lbc_ctrl_dev->irq;
> > +		goto err;
> > +	}
> > +
> > +	return 0;
> > +
> > +err:
> > +	iounmap(fsl_lbc_ctrl_dev->regs);
> > +	kfree(fsl_lbc_ctrl_dev);
> > +	return ret;
> > +}
> > +
> > +static const struct of_device_id fsl_lbc_match[] = {
> 
> #include <linux/mod_devicetable.h> is needed for this.
> 
> 
> Plus, I think the patch is not runtime bisectable (i.e. you
> now do request_irq() here, but not removing it from the nand
> driver, so nand will fail to probe).
Nand driver does not need to request irq. It will use the irq requested by lbc.
remember, other lbc device may also need to use this registered irq. 
It should not be removed in nand driver.

Thanks.
Roy

From zhangyd6 at gmail.com  Wed Oct 13 13:19:29 2010
From: zhangyd6 at gmail.com (zhangyd)
Date: Wed, 13 Oct 2010 13:19:29 -0400
Subject: [PATCH] [MTD] [CHIPS] Add JEDEC probe support for the SST38VF6401
	flash chip
Message-ID: <1286990369-5165-1-git-send-email-zhangyd6@gmail.com>

Add SST38VF6401(8Mbit) chip to jedec_probe.

Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
---
 drivers/mtd/chips/jedec_probe.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index d72a5fb..b7a1016 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -163,6 +163,7 @@
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
 #define SST49LF080A	0x005B
+#define SST38VF6401	0x536B
 #define SST36VF3203	0x7354
 
 /* Toshiba */
@@ -1569,6 +1570,18 @@ static const struct amd_flash_info jedec_table[] = {
 		}
 	}, {
 		.mfr_id		= CFI_MFR_ST,
+		.dev_id		= SST38VF6401,
+		.name		= "SST 38VF6401",
+		.devtypes	= CFI_DEVICETYPE_X16,
+		.uaddr		= MTD_UADDR_0X0AAA_0x555,
+		.dev_size	= SIZE_8MiB,
+		.cmd_set	= P_ID_AMD_STD,
+		.nr_regions	= 1,
+		.regions	= {
+			ERASEINFO(0x10000,128),
+		}
+	}, {
+		.mfr_id		= CFI_MFR_ST,
 		.dev_id		= M29F800AB,
 		.name		= "ST M29F800AB",
 		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-- 
1.7.2.3



From scottwood at freescale.com  Thu Oct 14 12:01:18 2010
From: scottwood at freescale.com (Scott Wood)
Date: Thu, 14 Oct 2010 11:01:18 -0500
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect
	nand flash partitions
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A2B02B7@zch01exm23.fsl.freescale.net>
References: <20101004103813.14d04956@udp111988uds.am.freescale.net>
	<3850A844E6A3854C827AC5C0BEC7B60A2B02B7@zch01exm23.fsl.freescale.net>
Message-ID: <20101014110118.11fabed5@udp111988uds.am.freescale.net>

On Wed, 13 Oct 2010 20:09:02 -0700
"Zang Roy-R61911" <r61911 at freescale.com> wrote:

> > > > > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> > > >
> > > > No need for = NULL.
> > > Any harm? Or just personal habit or style? Can you explain about
> why?
> > 
> > Besides not wanting superfluous code on general principle, it could
> > hide a bug if in the future the real initialization is missing on some
> > code path.  It would become a runtime NULL dereference rather than a
> > compiler warning.
> 
> Not exactly.
> Per my understand, if the pointer will definitely be assigned in code
> path,
> it is not necessary to init it when define. for example,
> 
> char c;
> char b;
> char *a;
> if (condition)
> 	a = &c;
> else
> 	a = &b;
> ...
> 
> for other case, if the path will not ensure the pointer assignment, it
> will be inited
> when define to avoid warning. for example,
> 
> char c;
> char *a = NULL;
> if (condition)
> 	a = &c;
> ...

Yes, but this patch looks like the former case, not the
latter.  Is GCC giving a warning without the initializer?

-Scott



From scottwood at freescale.com  Thu Oct 14 12:02:39 2010
From: scottwood at freescale.com (Scott Wood)
Date: Thu, 14 Oct 2010 11:02:39 -0500
Subject: [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt common
	to elbc devices
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A2B0329@zch01exm23.fsl.freescale.net>
References: <20100920153718.GA4411@oksana.dev.rtsoft.ru>
	<3850A844E6A3854C827AC5C0BEC7B60A2B0329@zch01exm23.fsl.freescale.net>
Message-ID: <20101014110239.466072be@udp111988uds.am.freescale.net>

On Wed, 13 Oct 2010 23:43:38 -0700
"Zang Roy-R61911" <r61911 at freescale.com> wrote:

> > Plus, I think the patch is not runtime bisectable (i.e. you
> > now do request_irq() here, but not removing it from the nand
> > driver, so nand will fail to probe).
> Nand driver does not need to request irq. It will use the irq requested by lbc.
> remember, other lbc device may also need to use this registered irq. 
> It should not be removed in nand driver.

The point is that you need to make both changes in the same patch.

-Scott



From hartleys at visionengravers.com  Thu Oct 14 17:54:57 2010
From: hartleys at visionengravers.com (H Hartley Sweeten)
Date: Thu, 14 Oct 2010 16:54:57 -0500
Subject: Latest mkfs.jffs2 is broken.
Message-ID: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>

Hello all,

Buildroot recently bumped the mtd-utils package from version 1.3.1 to 1.4.0.

With the mkfs.jffs2 utility in 1.3.1 I am able to create rootfs.jffs images that
work fine on my i.mx35 arm system.  But, with the 1.4.0 version all the images
do not work.

With the 1.4.0 built images I get messages like this during the kernel boot:

jffs2_scan_eraseblock(): Node at 0x00000000 {0x1985, 0x2003, 0x0000000c) has invalid CRC 0x813c6fd8 (calculated 0xe41eb0b1)
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000004: 0x000c instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000008: 0x6fd8 instead
jffs2_scan_eraseblock(): Node at 0x0000000c {0x1985, 0xe001, 0x0000002b) has invalid CRC 0x1804b18f (calculated 0x7d266ee6)
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000010: 0x002b instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000014: 0xb18f instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000018: 0x0001 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000020: 0x0002 instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000024: 0x1a8d instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000028: 0x0403 instead
Further such events for this erase block will not be printed
Old JFFS2 bitmask found at 0x00000078
You cannot use older JFFS2 filesystems with newer kernels
Empty flash at 0x0000a46c ends at 0x0000a470

And, if I check the images with jffs2dump I get stuff like:

Wrong hdr_crc  at  0x0001f808, 0x783f44d2 instead of 0x1d1d9bbb
Wrong bitmask  at  0x0001f80c, 0x07f3
Empty space found from 0x0001fffc to 0x00020000

Any ideas what could be wrong with the 1.4.0 release?

Thanks,
Hartley

From r61911 at freescale.com  Thu Oct 14 22:15:20 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Fri, 15 Oct 2010 10:15:20 +0800
Subject: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver detect nand
	flash partitions
In-Reply-To: <20101014110118.11fabed5@udp111988uds.am.freescale.net>
References: <20101004103813.14d04956@udp111988uds.am.freescale.net><3850A844E6A3854C827AC5C0BEC7B60A2B02B7@zch01exm23.fsl.freescale.net>
	<20101014110118.11fabed5@udp111988uds.am.freescale.net>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B0445@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Friday, October 15, 2010 0:01 AM
> To: Zang Roy-R61911
> Cc: Wood Scott-B07421; Anton Vorontsov; linux-mtd at lists.infradead.org;
> dwmw2 at infradead.org; dedekind1 at gmail.com; akpm at linux-foundation.org;
Lan
> Chunhe-B25806; Gala Kumar-B11780; linuxppc-dev at ozlabs.org; Hu
Mingkai-B21284
> Subject: Re: [PATCH 2/3 v4] P4080/mtd: Only make elbc nand driver
detect nand
> flash partitions
> 
> On Wed, 13 Oct 2010 20:09:02 -0700
> "Zang Roy-R61911" <r61911 at freescale.com> wrote:
> 
> > > > > > +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = NULL;
> > > > >
> > > > > No need for = NULL.
> > > > Any harm? Or just personal habit or style? Can you explain about
> > why?
> > >
> > > Besides not wanting superfluous code on general principle, it
could
> > > hide a bug if in the future the real initialization is missing on
some
> > > code path.  It would become a runtime NULL dereference rather than
a
> > > compiler warning.
> >
> > Not exactly.
> > Per my understand, if the pointer will definitely be assigned in
code
> > path,
> > it is not necessary to init it when define. for example,
> >
> > char c;
> > char b;
> > char *a;
> > if (condition)
> > 	a = &c;
> > else
> > 	a = &b;
> > ...
> >
> > for other case, if the path will not ensure the pointer assignment,
it
> > will be inited
> > when define to avoid warning. for example,
> >
> > char c;
> > char *a = NULL;
> > if (condition)
> > 	a = &c;
> > ...
> 
> Yes, but this patch looks like the former case, not the
> latter. 
That is right.
> Is GCC giving a warning without the initializer?
no.
we are on the same point.
Thanks.
Roy



From r61911 at freescale.com  Fri Oct 15 01:03:14 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Fri, 15 Oct 2010 13:03:14 +0800
Subject: [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt common
	to elbc devices
In-Reply-To: <20101014110239.466072be@udp111988uds.am.freescale.net>
References: <20100920153718.GA4411@oksana.dev.rtsoft.ru><3850A844E6A3854C827AC5C0BEC7B60A2B0329@zch01exm23.fsl.freescale.net>
	<20101014110239.466072be@udp111988uds.am.freescale.net>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B049B@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Friday, October 15, 2010 0:03 AM
> To: Zang Roy-R61911
> Cc: Anton Vorontsov; linux-mtd at lists.infradead.org;
dwmw2 at infradead.org;
> dedekind1 at gmail.com; akpm at linux-foundation.org; Lan Chunhe-B25806;
Wood Scott-
> B07421; Gala Kumar-B11780; linuxppc-dev at ozlabs.org
> Subject: Re: [PATCH 1/3 v4] P4080/eLBC: Make Freescale elbc interrupt
common
> to elbc devices
> 
> On Wed, 13 Oct 2010 23:43:38 -0700
> "Zang Roy-R61911" <r61911 at freescale.com> wrote:
> 
> > > Plus, I think the patch is not runtime bisectable (i.e. you
> > > now do request_irq() here, but not removing it from the nand
> > > driver, so nand will fail to probe).
> > Nand driver does not need to request irq. It will use the irq
requested by
> lbc.
> > remember, other lbc device may also need to use this registered irq.
> > It should not be removed in nand driver.
> 
> The point is that you need to make both changes in the same patch.

But according to previous discussion, if lbc driver is registered
successful, it will not be removed. (.remove function is dropped in the
patch). that is not bisectable?
nand driver will not touch the irq. all irq status process is in the lbc
driver.
Thanks.
Roy



From dedekind1 at gmail.com  Fri Oct 15 02:13:01 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 15 Oct 2010 09:13:01 +0300
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <20101013163005.GB1889@silverbox.local>
References: <20101013163005.GB1889@silverbox.local>
Message-ID: <1287123181.18576.1.camel@localhost>

On Wed, 2010-10-13 at 18:30 +0200, Hans J. Koch wrote:
> Running this command:
> 
> # while true ; do sync; sleep 1; done
> 
> causes two eraseblocks being erased every second, although there
> are no writes to the ubifs filesystem. I hacked some printks into
> my NAND driver that print page_address and column for each erase.
> With that, I get this output every second:
> 
> ...
> [   63.701765] erase p=0x0000ae40 c=0xffffffff
> [   63.706534] erase p=0xffffffff c=0xffffffff
> [   63.725492] erase p=0x0000ae80 c=0xffffffff
> [   63.730260] erase p=0xffffffff c=0xffffffff
> ...
> 
> From a quick glance at the ubifs code, this might come out of the
> garbage collector that is triggered on every sync() and writes
> something even if nothing has changed.
> 
> Is that really needed?

Hi, no, it is not. I'll look at this as soon as I have some time. There
is already Matthieu's issue waiting in my queue, though. Thanks for
reporting.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Oct 15 02:14:05 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 15 Oct 2010 09:14:05 +0300
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
Message-ID: <1287123245.18576.2.camel@localhost>

On Thu, 2010-10-14 at 16:54 -0500, H Hartley Sweeten wrote:
> Hello all,
> 
> Buildroot recently bumped the mtd-utils package from version 1.3.1 to 1.4.0.
> 
> With the mkfs.jffs2 utility in 1.3.1 I am able to create rootfs.jffs images that
> work fine on my i.mx35 arm system.  But, with the 1.4.0 version all the images
> do not work.
> 
> With the 1.4.0 built images I get messages like this during the kernel boot:
> 
> jffs2_scan_eraseblock(): Node at 0x00000000 {0x1985, 0x2003, 0x0000000c) has invalid CRC 0x813c6fd8 (calculated 0xe41eb0b1)
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000004: 0x000c instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000008: 0x6fd8 instead
> jffs2_scan_eraseblock(): Node at 0x0000000c {0x1985, 0xe001, 0x0000002b) has invalid CRC 0x1804b18f (calculated 0x7d266ee6)
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000010: 0x002b instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000014: 0xb18f instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000018: 0x0001 instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000020: 0x0002 instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000024: 0x1a8d instead
> jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x00000028: 0x0403 instead
> Further such events for this erase block will not be printed
> Old JFFS2 bitmask found at 0x00000078
> You cannot use older JFFS2 filesystems with newer kernels
> Empty flash at 0x0000a46c ends at 0x0000a470
> 
> And, if I check the images with jffs2dump I get stuff like:
> 
> Wrong hdr_crc  at  0x0001f808, 0x783f44d2 instead of 0x1d1d9bbb
> Wrong bitmask  at  0x0001f80c, 0x07f3
> Empty space found from 0x0001fffc to 0x00020000
> 
> Any ideas what could be wrong with the 1.4.0 release?

Could you please bisect the mtd-utils.git tree and find the offending
commit.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Fri Oct 15 03:44:23 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 15 Oct 2010 00:44:23 -0700
Subject: [PATCH 1/3] mtd-utils: nanddump/nandwrite: Style fixups
Message-ID: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c  |   58 ++++++++++++++----------------
 nandwrite.c |  114 +++++++++++++++++++++++++++++------------------------------
 2 files changed, 83 insertions(+), 89 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index b7341a5..00762a5 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -37,7 +37,7 @@ static struct nand_oobinfo none_oobinfo = {
 	.useecc = MTD_NANDECC_OFF,
 };
 
-static void display_help (void)
+static void display_help(void)
 {
 	printf(
 "Usage: %s [OPTIONS] MTD-device\n"
@@ -60,7 +60,7 @@ static void display_help (void)
 	exit(EXIT_SUCCESS);
 }
 
-static void display_version (void)
+static void display_version(void)
 {
 	printf("%1$s " VERSION "\n"
 			"\n"
@@ -89,7 +89,7 @@ static bool		quiet = false;		// suppress diagnostic output
 static bool		canonical = false;	// print nice + ascii
 static bool		forcebinary = false;	// force printing binary to tty
 
-static void process_options (int argc, char * const argv[])
+static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
 
@@ -185,7 +185,7 @@ static void process_options (int argc, char * const argv[])
 	}
 
 	if ((argc - optind) != 1 || error)
-		display_help ();
+		display_help();
 
 	mtddev = argv[optind];
 }
@@ -293,14 +293,14 @@ int main(int argc, char * const argv[])
 	/* Open MTD device */
 	if ((fd = open(mtddev, O_RDONLY)) == -1) {
 		perror(mtddev);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	/* Fill in MTD device capability structure */
 	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
 		perror("MEMGETINFO");
 		close(fd);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	/* Make sure device page sizes are valid */
@@ -320,32 +320,31 @@ int main(int argc, char * const argv[])
 	oob.length = meminfo.oobsize;
 
 	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
+		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
 		if (ret == 0) {
 			oobinfochanged = 2;
 		} else {
 			switch (errno) {
 			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
+				if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
+					perror("MEMGETOOBSEL");
+					close(fd);
+					exit(EXIT_FAILURE);
 				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
+				if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
+					perror("MEMSETOOBSEL");
+					close(fd);
+					exit(EXIT_FAILURE);
 				}
 				oobinfochanged = 1;
 				break;
 			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
+				perror("MTDFILEMODE");
+				close(fd);
+				exit(EXIT_FAILURE);
 			}
 		}
 	} else {
-
 		/* check if we can read ecc stats */
 		if (!ioctl(fd, ECCGETSTATS, &stat1)) {
 			eccstats = true;
@@ -363,8 +362,8 @@ int main(int argc, char * const argv[])
 	 * output. */
 	if (!dumpfile) {
 		ofd = STDOUT_FILENO;
-	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
-		perror (dumpfile);
+	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) {
+		perror(dumpfile);
 		close(fd);
 		exit(EXIT_FAILURE);
 	}
@@ -391,12 +390,11 @@ int main(int argc, char * const argv[])
 				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
 		fprintf(stderr,
 				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
-				(unsigned int) start_addr, (unsigned int) end_addr);
+				(unsigned int)start_addr, (unsigned int)end_addr);
 	}
 	/* Dump the flash contents */
-	for (ofs = start_addr; ofs < end_addr ; ofs+=bs) {
-
-		// new eraseblock , check for bad block
+	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
+		/* Check for bad block */
 		if (noskipbad) {
 			badblock = 0;
 		} else if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
@@ -446,8 +444,6 @@ int main(int argc, char * const argv[])
 		} else
 			write(ofd, readbuf, bs);
 
-
-
 		if (omitoob)
 			continue;
 
@@ -475,8 +471,8 @@ int main(int argc, char * const argv[])
 
 	/* reset oobinfo */
 	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
+		if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
+			perror("MEMSETOOBSEL");
 			close(fd);
 			close(ofd);
 			return EXIT_FAILURE;
@@ -492,8 +488,8 @@ int main(int argc, char * const argv[])
 closeall:
 	/* The new mode change is per file descriptor ! */
 	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0)  {
-			perror ("MEMSETOOBSEL");
+		if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0)  {
+			perror("MEMSETOOBSEL");
 		}
 	}
 	close(fd);
diff --git a/nandwrite.c b/nandwrite.c
index 3520c62..e0f5f44 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -66,7 +66,7 @@ static struct nand_oobinfo autoplace_oobinfo = {
 	.useecc = MTD_NANDECC_AUTOPLACE
 };
 
-static void display_help (void)
+static void display_help(void)
 {
 	printf(
 "Usage: nandwrite [OPTION] MTD_DEVICE [INPUTFILE|-]\n"
@@ -89,10 +89,10 @@ static void display_help (void)
 "      --help              Display this help and exit\n"
 "      --version           Output version information and exit\n"
 	);
-	exit (EXIT_SUCCESS);
+	exit(EXIT_SUCCESS);
 }
 
-static void display_version (void)
+static void display_version(void)
 {
 	printf("%1$s " VERSION "\n"
 			"\n"
@@ -105,7 +105,7 @@ static void display_version (void)
 			"under the terms of the GNU General Public Licence.\n"
 			"See the file `COPYING' for more information.\n",
 			PROGRAM_NAME);
-	exit (EXIT_SUCCESS);
+	exit(EXIT_SUCCESS);
 }
 
 static const char	*standard_input = "-";
@@ -122,9 +122,9 @@ static bool		forcelegacy = false;
 static bool		noecc = false;
 static bool		noskipbad = false;
 static bool		pad = false;
-static int		blockalign = 1; /*default to using 16K block size */
+static int		blockalign = 1; /* default to using 16K block size */
 
-static void process_options (int argc, char * const argv[])
+static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
 
@@ -202,10 +202,10 @@ static void process_options (int argc, char * const argv[])
 				writeoob = true;
 				break;
 			case 's':
-				mtdoffset = strtol (optarg, NULL, 0);
+				mtdoffset = strtol(optarg, NULL, 0);
 				break;
 			case 'b':
-				blockalign = atoi (optarg);
+				blockalign = atoi(optarg);
 				break;
 			case '?':
 				error++;
@@ -216,7 +216,7 @@ static void process_options (int argc, char * const argv[])
 	if (mtdoffset < 0) {
 		fprintf(stderr, "Can't specify a negative device offset `%d'\n",
 				mtdoffset);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	argc -= optind;
@@ -228,7 +228,7 @@ static void process_options (int argc, char * const argv[])
 	 */
 
 	if (argc < 1 || argc > 2 || error)
-		display_help ();
+		display_help();
 
 	mtd_device = argv[0];
 
@@ -284,20 +284,20 @@ int main(int argc, char * const argv[])
 
 	if (pad && writeoob) {
 		fprintf(stderr, "Can't pad when oob data is present.\n");
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	/* Open the device */
 	if ((fd = open(mtd_device, O_RDWR)) == -1) {
 		perror(mtd_device);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	/* Fill in MTD device capability structure */
 	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
 		perror("MEMGETINFO");
 		close(fd);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	/* Set erasesize to specified number of blocks - to match jffs2
@@ -312,7 +312,7 @@ int main(int argc, char * const argv[])
 			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
 		fprintf(stderr, "Unknown flash (not normal NAND)\n");
 		close(fd);
-		exit (EXIT_FAILURE);
+		exit(EXIT_FAILURE);
 	}
 
 	if (mtdoffset & (meminfo.writesize - 1)) {
@@ -325,47 +325,47 @@ int main(int argc, char * const argv[])
 
 	if (autoplace) {
 		/* Read the current oob info */
-		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMGETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
+		if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
+			perror("MEMGETOOBSEL");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
 
 		// autoplace ECC ?
 		if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
 
-			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
-				perror ("MEMSETOOBSEL");
-				close (fd);
-				exit (EXIT_FAILURE);
+			if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
+				perror("MEMSETOOBSEL");
+				close(fd);
+				exit(EXIT_FAILURE);
 			}
 			oobinfochanged = 1;
 		}
 	}
 
 	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
+		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
 		if (ret == 0) {
 			oobinfochanged = 2;
 		} else {
 			switch (errno) {
 			case ENOTTY:
-				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
-					perror ("MEMGETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
+				if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
+					perror("MEMGETOOBSEL");
+					close(fd);
+					exit(EXIT_FAILURE);
 				}
-				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
-					perror ("MEMSETOOBSEL");
-					close (fd);
-					exit (EXIT_FAILURE);
+				if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
+					perror("MEMSETOOBSEL");
+					close(fd);
+					exit(EXIT_FAILURE);
 				}
 				oobinfochanged = 1;
 				break;
 			default:
-				perror ("MTDFILEMODE");
-				close (fd);
-				exit (EXIT_FAILURE);
+				perror("MTDFILEMODE");
+				close(fd);
+				exit(EXIT_FAILURE);
 			}
 		}
 	}
@@ -387,15 +387,15 @@ int main(int argc, char * const argv[])
 		}
 		if (meminfo.oobsize == 8) {
 			if (forceyaffs) {
-				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
+				fprintf(stderr, "YAFSS cannot operate on 256 Byte page size");
 				goto restoreoob;
 			}
 			/* Adjust number of ecc bytes */
 			jffs2_oobinfo.eccbytes = 3;
 		}
 
-		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
-			perror ("MEMSETOOBSEL");
+		if (ioctl(fd, MEMSETOOBSEL, oobsel) != 0) {
+			perror("MEMSETOOBSEL");
 			goto restoreoob;
 		}
 	}
@@ -432,27 +432,27 @@ int main(int argc, char * const argv[])
 	    imglen = pagelen;
 	} else {
 	    imglen = lseek(ifd, 0, SEEK_END);
-	    lseek (ifd, 0, SEEK_SET);
+	    lseek(ifd, 0, SEEK_SET);
 	}
 
 	// Check, if file is page-aligned
 	if ((!pad) && ((imglen % pagelen) != 0)) {
-		fprintf (stderr, "Input file is not page-aligned. Use the padding "
+		fprintf(stderr, "Input file is not page-aligned. Use the padding "
 				 "option.\n");
 		goto closeall;
 	}
 
 	// Check, if length fits into device
-	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
-		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
+	if (((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
+		fprintf(stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
 				imglen, pagelen, meminfo.writesize, meminfo.size);
-		perror ("Input file does not fit into device");
+		perror("Input file does not fit into device");
 		goto closeall;
 	}
 
 	// Allocate a buffer big enough to contain all the data (OOB included) for one eraseblock
 	filebuf_max = pagelen * meminfo.erasesize / meminfo.writesize;
-	filebuf = (unsigned char*)malloc(filebuf_max);
+	filebuf = (unsigned char *)malloc(filebuf_max);
 	if (!filebuf) {
 		fprintf(stderr, "Failed to allocate memory for file buffer (%d bytes)\n",
 				pagelen * meminfo.erasesize / meminfo.writesize);
@@ -490,7 +490,7 @@ int main(int argc, char * const argv[])
 
 			baderaseblock = false;
 			if (!quiet)
-				fprintf (stdout, "Writing data to block %d at offset 0x%x\n",
+				fprintf(stdout, "Writing data to block %d at offset 0x%x\n",
 						 blockstart / meminfo.erasesize, blockstart);
 
 			/* Check all the blocks in an erase block for bad blocks */
@@ -512,8 +512,8 @@ int main(int argc, char * const argv[])
 				if (baderaseblock) {
 					mtdoffset = blockstart + meminfo.erasesize;
 				}
-				offs +=  meminfo.erasesize / blockalign ;
-			} while ( offs < blockstart + meminfo.erasesize );
+				offs +=  meminfo.erasesize / blockalign;
+			} while (offs < blockstart + meminfo.erasesize);
 
 		}
 
@@ -529,7 +529,7 @@ int main(int argc, char * const argv[])
 				if (cnt == 0) { // EOF
 					break;
 				} else if (cnt < 0) {
-					perror ("File I/O error on input");
+					perror("File I/O error on input");
 					goto closeall;
 				}
 				tinycnt += cnt;
@@ -573,7 +573,6 @@ int main(int argc, char * const argv[])
 			// Read more data for the OOB from the input if there isn't enough in the buffer
 			if ((oobreadbuf + meminfo.oobsize) > (filebuf + filebuf_len)) {
 				int readlen = meminfo.oobsize;
-
 				int alreadyread = (filebuf + filebuf_len) - oobreadbuf;
 				int tinycnt = alreadyread;
 
@@ -582,7 +581,7 @@ int main(int argc, char * const argv[])
 					if (cnt == 0) { // EOF
 						break;
 					} else if (cnt < 0) {
-						perror ("File I/O error on input");
+						perror("File I/O error on input");
 						goto closeall;
 					}
 					tinycnt += cnt;
@@ -641,7 +640,7 @@ int main(int argc, char * const argv[])
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
-				perror ("ioctl(MEMWRITEOOB)");
+				perror("ioctl(MEMWRITEOOB)");
 				goto closeall;
 			}
 		}
@@ -697,10 +696,10 @@ closeall:
 
 restoreoob:
 	if (oobinfochanged == 1) {
-		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
-			perror ("MEMSETOOBSEL");
-			close (fd);
-			exit (EXIT_FAILURE);
+		if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
+			perror("MEMSETOOBSEL");
+			close(fd);
+			exit(EXIT_FAILURE);
 		}
 	}
 
@@ -708,10 +707,9 @@ restoreoob:
 
 	if (failed
 		|| ((ifd != STDIN_FILENO) && (imglen > 0))
-		|| (writebuf < (filebuf + filebuf_len)))
-	{
-		perror ("Data was only partially written due to error\n");
-		exit (EXIT_FAILURE);
+		|| (writebuf < (filebuf + filebuf_len))) {
+		perror("Data was only partially written due to error\n");
+		exit(EXIT_FAILURE);
 	}
 
 	/* Return happy */
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Oct 15 03:44:24 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 15 Oct 2010 00:44:24 -0700
Subject: [PATCH 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
References: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287128665-6573-2-git-send-email-computersforpeace@gmail.com>

The buffers used for dumping page and OOB data needed dynamic
allocation to help eliminate burdens for updating (i.e., every
time there's a new OOB size we don't have to increase the sizes).

Also, there is no need to check flash chips for "standard sizes."
With recent changes to the printing codebase, we should be able to
handle arbitrary sizes with no problem.

More exit operations are now necessary on program failure, so
"goto closeall" is used more liberally.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   71 +++++++++++++++++++++++++++++------------------------------
 1 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 00762a5..c71c7a6 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -265,28 +265,21 @@ nil:
 }
 
 /*
- * Buffers for reading data from flash
- */
-#define NAND_MAX_PAGESIZE 4096
-#define NAND_MAX_OOBSIZE 256
-static unsigned char readbuf[NAND_MAX_PAGESIZE];
-static unsigned char oobbuf[NAND_MAX_OOBSIZE];
-
-/*
  * Main program
  */
 int main(int argc, char * const argv[])
 {
 	unsigned long ofs, end_addr = 0;
 	unsigned long long blockstart = 1;
-	int ret, i, fd, ofd, bs, badblock = 0;
-	struct mtd_oob_buf oob = {0, 16, oobbuf};
+	int ret, i, fd, ofd = 0, bs, badblock = 0;
+	struct mtd_oob_buf oob;
 	mtd_info_t meminfo;
 	char pretty_buf[PRETTY_BUF_LEN];
 	int oobinfochanged = 0 ;
 	struct nand_oobinfo old_oobinfo;
 	struct mtd_ecc_stats stat1, stat2;
 	bool eccstats = false;
+	static unsigned char *readbuf, *oobbuf;
 
 	process_options(argc, argv);
 
@@ -303,21 +296,22 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 224 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 218 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 32 && meminfo.writesize == 1024) &&
-			!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit(EXIT_FAILURE);
+	/* Allocate buffers */
+	oobbuf = malloc(sizeof(oobbuf) * meminfo.oobsize);
+	if (!oobbuf) {
+		perror("malloc");
+		goto closeall;
 	}
-	/* Read the real oob length */
+	readbuf = malloc(sizeof(readbuf) * meminfo.writesize);
+	if (!readbuf) {
+		perror("malloc");
+		goto closeall;
+	}
+
+	/* Fill in oob info */
+	oob.start = 0;
 	oob.length = meminfo.oobsize;
+	oob.ptr = oobbuf;
 
 	if (noecc)  {
 		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
@@ -328,20 +322,17 @@ int main(int argc, char * const argv[])
 			case ENOTTY:
 				if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
 					perror("MEMGETOOBSEL");
-					close(fd);
-					exit(EXIT_FAILURE);
+					goto closeall;
 				}
 				if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
 					perror("MEMSETOOBSEL");
-					close(fd);
-					exit(EXIT_FAILURE);
+					goto closeall;
 				}
 				oobinfochanged = 1;
 				break;
 			default:
 				perror("MTDFILEMODE");
-				close(fd);
-				exit(EXIT_FAILURE);
+				goto closeall;
 			}
 		}
 	} else {
@@ -364,15 +355,13 @@ int main(int argc, char * const argv[])
 		ofd = STDOUT_FILENO;
 	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) {
 		perror(dumpfile);
-		close(fd);
-		exit(EXIT_FAILURE);
+		goto closeall;
 	}
 
 	if (!pretty_print && !forcebinary && isatty(ofd)) {
 		fprintf(stderr, "Not printing binary garbage to tty. Use '-a'\n"
 				"or '--forcebinary' to override.\n");
-		close(fd);
-		exit(EXIT_FAILURE);
+		goto closeall;
 	}
 
 	/* Initialize start/end addresses and block size */
@@ -478,9 +467,11 @@ int main(int argc, char * const argv[])
 			return EXIT_FAILURE;
 		}
 	}
-	/* Close the output file and MTD device */
+	/* Close the output file and MTD device, free memory */
 	close(fd);
 	close(ofd);
+	free(oobbuf);
+	free(readbuf);
 
 	/* Exit happy */
 	return EXIT_SUCCESS;
@@ -492,7 +483,15 @@ closeall:
 			perror("MEMSETOOBSEL");
 		}
 	}
-	close(fd);
-	close(ofd);
+	if (fd) {
+		close(fd);
+		if (ofd) {
+			close(ofd);
+		}
+	}
+	if (oobbuf)
+		free(oobbuf);
+	if (readbuf)
+		free(readbuf);
 	exit(EXIT_FAILURE);
 }
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Oct 15 03:44:25 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 15 Oct 2010 00:44:25 -0700
Subject: [PATCH 3/3] mtd-utils: nandwrite: Large page+oob support
In-Reply-To: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
References: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287128665-6573-3-git-send-email-computersforpeace@gmail.com>

Dynamic allocation of the oob buffer provides the necessary
support for removing the oob size check. Now, new unknown OOB
sizes can be handled correctly (for example, 8KB page + 448B
OOB).

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nandwrite.c |   33 +++++++++++++--------------------
 1 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index e0f5f44..2341694 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -42,9 +42,6 @@
 #include <asm/types.h>
 #include "mtd/mtd-user.h"
 
-#define MAX_PAGE_SIZE	4096
-#define MAX_OOB_SIZE	128
-
 // oob layouts to pass into the kernel as default
 static struct nand_oobinfo none_oobinfo = {
 	.useecc = MTD_NANDECC_OFF,
@@ -276,12 +273,10 @@ int main(int argc, char * const argv[])
 	unsigned char *writebuf = NULL;
 	// points to the OOB for the current page in filebuf
 	unsigned char *oobreadbuf = NULL;
-	unsigned char oobbuf[MAX_OOB_SIZE];
+	unsigned char *oobbuf = NULL;
 
 	process_options(argc, argv);
 
-	erase_buffer(oobbuf, sizeof(oobbuf));
-
 	if (pad && writeoob) {
 		fprintf(stderr, "Can't pad when oob data is present.\n");
 		exit(EXIT_FAILURE);
@@ -304,17 +299,6 @@ int main(int argc, char * const argv[])
 	 * (virtual) block size */
 	meminfo.erasesize *= blockalign;
 
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
-
 	if (mtdoffset & (meminfo.writesize - 1)) {
 		fprintf(stderr, "The start address is not page-aligned !\n"
 				"The pagesize of this NAND Flash is 0x%x.\n",
@@ -455,11 +439,19 @@ int main(int argc, char * const argv[])
 	filebuf = (unsigned char *)malloc(filebuf_max);
 	if (!filebuf) {
 		fprintf(stderr, "Failed to allocate memory for file buffer (%d bytes)\n",
-				pagelen * meminfo.erasesize / meminfo.writesize);
+				filebuf_max);
 		goto closeall;
 	}
 	erase_buffer(filebuf, filebuf_max);
 
+	oobbuf = (unsigned char *)malloc(meminfo.oobsize);
+	if (!oobbuf) {
+		fprintf(stderr, "Failed to allocate memory for oob buffer (%d bytes)\n",
+				meminfo.oobsize);
+		goto closeall;
+	}
+	erase_buffer(oobbuf, meminfo.oobsize);
+
 	/*
 	 * Get data from input and write to the device while there is
 	 * still input to read and we are still within the device
@@ -688,9 +680,10 @@ int main(int argc, char * const argv[])
 	failed = false;
 
 closeall:
-	if (filebuf) {
+	if (filebuf)
 		free(filebuf);
-	}
+	if (oobbuf)
+		free(oobbuf);
 
 	close(ifd);
 
-- 
1.7.0.4




From jacmet at sunsite.dk  Fri Oct 15 04:35:34 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Fri, 15 Oct 2010 10:35:34 +0200
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <1287123245.18576.2.camel@localhost> (Artem Bityutskiy's message
	of "Fri, 15 Oct 2010 09:14:05 +0300")
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
Message-ID: <87pqvbetux.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

Hi,

 Artem> On Thu, 2010-10-14 at 16:54 -0500, H Hartley Sweeten wrote:

 Artem> Could you please bisect the mtd-utils.git tree and find the offending
 Artem> commit.

With big endian atleast, jffs2dump complains about invalid hdr_crc on
1.4.0, but it's working on HEAD. A bisect shows that the commit fixing
it was Mike's:

commit b864c387e8f16273aad1453d6457d847e29c3d25
Author: Mike Frysinger <vapier at gentoo.org>
Date:   Wed Sep 22 22:32:56 2010 -0400

    mtd-utils: clean up zlib.h usage a bit
    
    Hide zlib's crc32 in compr_zlib.c and mkfs.ubifs/compr.c.
    
    jffs2reader.c and mkfs.jffs2.c don't actually use zlib, so punt the
    include from the file.
    
    mkfs.jffs2.c is implicitly using crc32 from zlib.h instead of the
    local mtd_crc32, so fix the local usage.  otherwise we get warnings
    about undefined crc32 because the file was redirecting the prototype.
    
    Signed-off-by: Mike Frysinger <vapier at gentoo.org>
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Hartley, that commit applies OK to 1.4.0, could you give it a try?

Artem: Time for a v1.4.1 release?

-- 
Bye, Peter Korsgaard


From dedekind1 at gmail.com  Fri Oct 15 04:43:38 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 15 Oct 2010 11:43:38 +0300
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <87pqvbetux.fsf@macbook.be.48ers.dk>
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
Message-ID: <1287132218.18576.12.camel@localhost>

On Fri, 2010-10-15 at 10:35 +0200, Peter Korsgaard wrote:
> commit b864c387e8f16273aad1453d6457d847e29c3d25
> Author: Mike Frysinger <vapier at gentoo.org>
> Date:   Wed Sep 22 22:32:56 2010 -0400
> 
>     mtd-utils: clean up zlib.h usage a bit
>     
>     Hide zlib's crc32 in compr_zlib.c and mkfs.ubifs/compr.c.
>     
>     jffs2reader.c and mkfs.jffs2.c don't actually use zlib, so punt the
>     include from the file.
>     
>     mkfs.jffs2.c is implicitly using crc32 from zlib.h instead of the
>     local mtd_crc32, so fix the local usage.  otherwise we get warnings
>     about undefined crc32 because the file was redirecting the prototype.
>     
>     Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>     Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> 
> Hartley, that commit applies OK to 1.4.0, could you give it a try?
> 
> Artem: Time for a v1.4.1 release?

Thanks. If it works, I'll back-port Mike's patch to 1.4.0 and tag it as
1.4.1. So 1.4.1 won't include tons of irrelevant commits.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From jacmet at sunsite.dk  Fri Oct 15 04:52:21 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Fri, 15 Oct 2010 10:52:21 +0200
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <1287132218.18576.12.camel@localhost> (Artem Bityutskiy's message
	of "Fri, 15 Oct 2010 11:43:38 +0300")
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
Message-ID: <87lj5zet2y.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

 >> Artem: Time for a v1.4.1 release?

 Artem> Thanks. If it works, I'll back-port Mike's patch to 1.4.0 and tag it as
 Artem> 1.4.1. So 1.4.1 won't include tons of irrelevant commits.

Great. An easy way to test:

git checkout v1.4.0
make WITHOUT_XATTR=1
./mkfs.jffs2 -e 0x20000 -b -s 0x1000 -d include -o test.jffs2
/usr/sbin/jffs2dump -b -c test.jffs2|head -n 4
Wrong hdr_crc  at  0x00000000, 0x954203f1 instead of 0xf060dc98
Wrong bitmask  at  0x00000004, 0x0000
Wrong hdr_crc  at  0x0000000c, 0xd10532a2 instead of 0xb427edcb
Wrong bitmask  at  0x00000010, 0x0000

git cherry-pick b864c387e8f1
make WITHOUT_XATTR=1
./mkfs.jffs2 -e 0x20000 -b -s 0x1000 -d include -o test.jffs2
/usr/sbin/jffs2dump -b -c test.jffs2|head -n 4
         Dirent     node at 0x0000000c, totlen 0x00000030, #pino     1, version     0, #ino         2, nsize        8, name common.h
         Inode      node at 0x0000003c, totlen 0x00000489, #ino      2, version     1, isize     2939, csize     1093, dsize     2939, offset        0
         Dirent     node at 0x000004c8, totlen 0x0000002f, #pino     1, version     1, #ino         3, nsize        7, name crc32.h
         Inode      node at 0x000004f8, totlen 0x0000011d, #ino      3, version     1, isize      294, csize      217, dsize      294, offset        0

-- 
Bye, Peter Korsgaard


From pev at sketchymonkey.com  Fri Oct 15 07:13:11 2010
From: pev at sketchymonkey.com (David Peverley)
Date: Fri, 15 Oct 2010 12:13:11 +0100
Subject: Understanding OOB data read implementation
Message-ID: <AANLkTi=dc4TSda9218MDJjtqNbGH=wTykt2kEppwLWck@mail.gmail.com>

Hello!

I've been adding OOB data read support into a driver I'm working with
and I'm trying to understand how the offset works. As a starting point
I picked the doc2000.c driver (From the latest kernel.org 2.6.35.7
kernel)

The following happens in the driver :
    static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
                            struct mtd_oob_ops *ops)
    {
            ...
            ofs += ops->ooboffs;
            ...

This is what I don't understand - why does ofs have ooboffs added? In
the MTD char driver mtdchar.c the oob's read gets set up thus :
    static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
            uint32_t length, void __user *ptr, uint32_t __user *retp)
    {
        ...
        ops.ooboffs = start & (mtd->oobsize - 1);
        ...
        start &= ~((uint64_t)mtd->oobsize - 1);
        ret = mtd->read_oob(mtd, start, &ops);
        ...

So... my reading of this is that the requested OOB read offset is
passed into mtd_do_readoob() as the "start" parameter. This is then
copied into the ops structure and passed in to read_oob() as two
copies (via start and again inside the ops structure). This same logic
is also followed in doc2001.c and doc2001plus.c.

If that's the case, I don't understand why in doc2000.c it's being
added - is this not effectively using *double* the requested offset?

Also as a side note I suspect that mtd_do_readoob() would be a smidge
clearer if the above was re-factored to avoid the duplication of the
masking to oobsize :
    static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
            uint32_t length, void __user *ptr, uint32_t __user *retp)
    {
        ...
        start &= ~((uint64_t)mtd->oobsize - 1);
        ...
        ops.ooboffs = start;
        ...
        ret = mtd->read_oob(mtd, start, &ops);
        ...

Cheers all!

~Pev


From pev at sketchymonkey.com  Fri Oct 15 07:29:48 2010
From: pev at sketchymonkey.com (David Peverley)
Date: Fri, 15 Oct 2010 12:29:48 +0100
Subject: Understanding OOB data read implementation (II)
Message-ID: <AANLkTi=+2kVMg+YegwRe1SkWWWfF3-=4ZRmvciBZLkCy@mail.gmail.com>

Hi again...!

I've also noticed after blindly copying it that in the DoC drivers
that the OOB reads use the ops->len for size :
    static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
                            struct mtd_oob_ops *ops)
        ...
        uint8_t *buf = ops->oobbuf;
        size_t len = ops->len;
        ...

Reading mtd.h and the following patch summary :
    http://www.mail-archive.com/git-commits-head at vger.kernel.org/msg03799.html

I suspect this is wrong and should be using ops->ooblen instead. This
is especially true given that mtdchar.c leaves ops->len
uninitialised....! (should mtdchar.c:mtd_do_readoob() not zero the ops
structure as it's a local automatic so not zero-initialised?) Again
this is copied in doc2001.c and doc2001plus.c.

Cheers,

~Pev


From ext-roman.borisov at nokia.com  Fri Oct 15 07:59:40 2010
From: ext-roman.borisov at nokia.com (Roman Borisov)
Date: Fri, 15 Oct 2010 15:59:40 +0400
Subject: question about jffs2: jffs2_scan_dirty_space() return value
Message-ID: <4CB8422C.7000409@nokia.com>

hello,

The question was born when I discovered that in fs/jffs2/scan.c 
jffs2_scan_medium() a return value from fs/jffs2/nodelist.c 
jffs2_scan_dirty_space() is not checked;
However return value from jffs2_scan_dirty_space() is checked anywhere else.
jffs2_scan_dirty_space() investigation showed that it can't return 
anything except 0;

The question is: should the jffs2_scan_dirty_space() be changed to 
return some error instead BUG() macro for example?
<code>
     if (unlikely(size > jeb->free_size)) {
         printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x 
(wasted 0x%x)\n",
                size, jeb->free_size, jeb->wasted_size);
-        BUG();
+    return some_error;
     }
</code>
In this case we also should update jffs2_scan_medium() to check the 
error code.

Thanks,
Roman



From jonas at southpole.se  Fri Oct 15 08:53:28 2010
From: jonas at southpole.se (Jonas Bonn)
Date: Fri, 15 Oct 2010 14:53:28 +0200
Subject: [PATCH 1/1] mtd: m25p80 -- parse partitions from OF tree
Message-ID: <1287147208-11588-1-git-send-email-jonas@southpole.se>

It needs to be possible to define the partitions of an MTD device from an OF
devicetree.  This patch adds a call to of_mtd_parse_partitions if:

i)   there are no commandline partitions defined
ii)  there are no partitions set up by platform_data
iii) and an of_node is present on the device

This permits the following devicetree structure:

flash0: mtd at 0 {
	compatible = "st,m25p10";
	reg = <0>;
	spi-max-frequency = <100000000>;

	#address-cells = <1>;
	#size-cells = <1>;

	partition at 0 {
		label = "bootloader";
		reg = <0x00000000 0x00018000>;
		read-only;
	}

	partition at 18000 {
		label = "data";
		reg = <0x00018000 0x00008000>;
	};
};

Signed-off-by: Jonas Bonn <jonas at southpole.se>
---
 drivers/mtd/devices/m25p80.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 6f512b5..a349498 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -924,6 +924,10 @@ static int __devinit m25p_probe(struct spi_device *spi)
 			nr_parts = data->nr_parts;
 		}
 
+		if (nr_parts <= 0 && spi->dev.of_node) {
+			nr_parts = of_mtd_parse_partitions(&spi->dev, spi->dev.of_node, &parts);
+		}
+
 		if (nr_parts > 0) {
 			for (i = 0; i < nr_parts; i++) {
 				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.7.1



From zhangyd6 at gmail.com  Wed Oct 13 13:54:42 2010
From: zhangyd6 at gmail.com (zhangyd)
Date: Wed, 13 Oct 2010 13:54:42 -0400
Subject: [PATCH] [MTD] [CHIPS] Add JEDEC probe support for the SST38VF6401
	flash chip
Message-ID: <1286992482-6009-1-git-send-email-zhangyd6@gmail.com>

Add SST38VF6401(64Mbit) chip to jedec_probe. Sorry for the wrong description of the flash size in last patch. 

Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
---
 drivers/mtd/chips/jedec_probe.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index d72a5fb..b7a1016 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -163,6 +163,7 @@
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
 #define SST49LF080A	0x005B
+#define SST38VF6401	0x536B
 #define SST36VF3203	0x7354
 
 /* Toshiba */
@@ -1569,6 +1570,18 @@ static const struct amd_flash_info jedec_table[] = {
 		}
 	}, {
 		.mfr_id		= CFI_MFR_ST,
+		.dev_id		= SST38VF6401,
+		.name		= "SST 38VF6401",
+		.devtypes	= CFI_DEVICETYPE_X16,
+		.uaddr		= MTD_UADDR_0X0AAA_0x555,
+		.dev_size	= SIZE_8MiB,
+		.cmd_set	= P_ID_AMD_STD,
+		.nr_regions	= 1,
+		.regions	= {
+			ERASEINFO(0x10000,128),
+		}
+	}, {
+		.mfr_id		= CFI_MFR_ST,
 		.dev_id		= M29F800AB,
 		.name		= "ST M29F800AB",
 		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-- 
1.7.2.3



From w.sang at pengutronix.de  Fri Oct 15 10:01:12 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Fri, 15 Oct 2010 16:01:12 +0200
Subject: [PATCH] [MTD] [CHIPS] Add JEDEC probe support for the
	SST38VF6401 flash chip
In-Reply-To: <1286992482-6009-1-git-send-email-zhangyd6@gmail.com>
References: <1286992482-6009-1-git-send-email-zhangyd6@gmail.com>
Message-ID: <20101015140112.GD4276@pengutronix.de>

On Wed, Oct 13, 2010 at 01:54:42PM -0400, zhangyd wrote:
> Add SST38VF6401(64Mbit) chip to jedec_probe. Sorry for the wrong description of the flash size in last patch. 

Can you explain why CFI can't be used?

> 
> Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
> ---
>  drivers/mtd/chips/jedec_probe.c |   13 +++++++++++++
>  1 files changed, 13 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
> index d72a5fb..b7a1016 100644
> --- a/drivers/mtd/chips/jedec_probe.c
> +++ b/drivers/mtd/chips/jedec_probe.c
> @@ -163,6 +163,7 @@
>  #define SST49LF030A	0x001C
>  #define SST49LF040A	0x0051
>  #define SST49LF080A	0x005B
> +#define SST38VF6401	0x536B
>  #define SST36VF3203	0x7354
>  
>  /* Toshiba */
> @@ -1569,6 +1570,18 @@ static const struct amd_flash_info jedec_table[] = {
>  		}
>  	}, {
>  		.mfr_id		= CFI_MFR_ST,
> +		.dev_id		= SST38VF6401,
> +		.name		= "SST 38VF6401",
> +		.devtypes	= CFI_DEVICETYPE_X16,
> +		.uaddr		= MTD_UADDR_0X0AAA_0x555,
> +		.dev_size	= SIZE_8MiB,
> +		.cmd_set	= P_ID_AMD_STD,
> +		.nr_regions	= 1,
> +		.regions	= {
> +			ERASEINFO(0x10000,128),
> +		}
> +	}, {
> +		.mfr_id		= CFI_MFR_ST,
>  		.dev_id		= M29F800AB,
>  		.name		= "ST M29F800AB",
>  		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
> -- 
> 1.7.2.3
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101015/2b17e397/attachment.sig>

From maximlevitsky at gmail.com  Fri Oct 15 11:20:42 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:42 +0200
Subject: [MTD] My updates [RESEND]
Message-ID: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>

Here are few patches for 2.6.37 that I have in my patch queue for MTD.

Best regards,
	Maxim Levitsky



From maximlevitsky at gmail.com  Fri Oct 15 11:20:43 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:43 +0200
Subject: [PATCH 1/5] MTD: blktrans: Allow to unload the mtdtrans module if its
	block devices aren't open
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287156047-17439-2-git-send-email-maximlevitsky@gmail.com>

Now it once again possible to remove mtdtrans module.
You still need to ensure that block devices of that module aren't mounted.
This is due to the fact that as long as a block device is open, it still exists,
therefore if we were to allow module removal, this block device might became used again.

This time in addition to code review, I also made the code
pass some torture tests like module reload in  a loop + read in a loop +
card insert/removal all at same time.

The blktrans_open/blktrans_release don't take the mtd table lock because:

While device is added (that includes execution of add_mtd_blktrans_dev)
the lock is already taken

Now suppose the device will never be removed. In this case even if we have changes
in mtd table, the entry that we need will stay exactly the same. (Note that we don't
look at table at all, just following private pointer of block device).

Now suppose that someone tries to remove the mtd device.
This will be propagated to trans driver which _ought_ to call del_mtd_blktrans_dev
which will take the per device lock, release the mtd device and set trans->mtd = NULL.

From bogus@does.not.exist.com  Sat Oct  9 07:11:57 2010
From: bogus@does.not.exist.com ()
Date: Sat, 09 Oct 2010 11:11:57 -0000
Subject: No subject
Message-ID: <mailman.6.1287156078.18522.linux-mtd@lists.infradead.org>

(which at that point is likely not to exist)
Also the same care is taken not to trip over NULL mtd pointer in blktrans_dev_release.


Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/mtd_blkdevs.c |   52 ++++++++++++++++++++------------------------
 1 files changed, 24 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 62e6870..352831b 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -176,7 +176,7 @@ static void mtd_blktrans_request(struct request_queue *rq)
 static int blktrans_open(struct block_device *bdev, fmode_t mode)
 {
 	struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk);
-	int ret;
+	int ret = 0;
 
 	if (!dev)
 		return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
@@ -184,17 +184,17 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 	lock_kernel();
 	mutex_lock(&dev->lock);
 
-	if (!dev->mtd) {
-		ret = -ENXIO;
+	if (dev->open++)
 		goto unlock;
-	}
 
-	ret = !dev->open++ && dev->tr->open ? dev->tr->open(dev) : 0;
+	kref_get(&dev->ref);
+	__module_get(dev->tr->owner);
+
+	if (dev->mtd) {
+		ret = dev->tr->open ? dev->tr->open(dev) : 0;
+		__get_mtd_device(dev->mtd);
+	}
 
-	/* Take another reference on the device so it won't go away till
-		last release */
-	if (!ret)
-		kref_get(&dev->ref);
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
@@ -205,7 +205,7 @@ unlock:
 static int blktrans_release(struct gendisk *disk, fmode_t mode)
 {
 	struct mtd_blktrans_dev *dev = blktrans_dev_get(disk);
-	int ret = -ENXIO;
+	int ret = 0;
 
 	if (!dev)
 		return ret;
@@ -213,13 +213,16 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
 	lock_kernel();
 	mutex_lock(&dev->lock);
 
-	/* Release one reference, we sure its not the last one here*/
-	kref_put(&dev->ref, blktrans_dev_release);
-
-	if (!dev->mtd)
+	if (--dev->open)
 		goto unlock;
 
-	ret = !--dev->open && dev->tr->release ? dev->tr->release(dev) : 0;
+	kref_put(&dev->ref, blktrans_dev_release);
+	module_put(dev->tr->owner);
+
+	if (dev->mtd) {
+		ret = dev->tr->release ? dev->tr->release(dev) : 0;
+		__put_mtd_device(dev->mtd);
+	}
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
@@ -385,9 +388,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 
 	gd->queue = new->rq;
 
-	__get_mtd_device(new->mtd);
-	__module_get(tr->owner);
-
 	/* Create processing thread */
 	/* TODO: workqueue ? */
 	new->thread = kthread_run(mtd_blktrans_thread, new,
@@ -410,8 +410,6 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	}
 	return 0;
 error4:
-	module_put(tr->owner);
-	__put_mtd_device(new->mtd);
 	blk_cleanup_queue(new->rq);
 error3:
 	put_disk(new->disk);
@@ -448,17 +446,15 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
 	blk_start_queue(old->rq);
 	spin_unlock_irqrestore(&old->queue_lock, flags);
 
-	/* Ask trans driver for release to the mtd device */
+	/* If the device is currently open, tell trans driver to close it,
+		then put mtd device, and don't touch it again */
 	mutex_lock(&old->lock);
-	if (old->open && old->tr->release) {
-		old->tr->release(old);
-		old->open = 0;
+	if (old->open) {
+		if (old->tr->release)
+			old->tr->release(old);
+		__put_mtd_device(old->mtd);
 	}
 
-	__put_mtd_device(old->mtd);
-	module_put(old->tr->owner);
-
-	/* At that point, we don't touch the mtd anymore */
 	old->mtd = NULL;
 
 	mutex_unlock(&old->lock);
-- 
1.7.1



From maximlevitsky at gmail.com  Fri Oct 15 11:20:44 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:44 +0200
Subject: [PATCH 2/5] MTD: blktrans: kill the BKL.
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287156047-17439-3-git-send-email-maximlevitsky@gmail.com>

It not needed, because I already added locking for all fops
methods.

Signed-off-by: Maxim Levitsky
---
 drivers/mtd/mtd_blkdevs.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 352831b..040c2d9 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -181,7 +181,6 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 	if (!dev)
 		return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/
 
-	lock_kernel();
 	mutex_lock(&dev->lock);
 
 	if (dev->open++)
@@ -198,7 +197,6 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
 	return ret;
 }
 
@@ -210,7 +208,6 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
 	if (!dev)
 		return ret;
 
-	lock_kernel();
 	mutex_lock(&dev->lock);
 
 	if (--dev->open)
@@ -226,7 +223,6 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
 unlock:
 	mutex_unlock(&dev->lock);
 	blktrans_dev_put(dev);
-	unlock_kernel();
 	return ret;
 }
 
@@ -259,7 +255,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
 	if (!dev)
 		return ret;
 
-	lock_kernel();
 	mutex_lock(&dev->lock);
 
 	if (!dev->mtd)
@@ -274,7 +269,6 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode,
 	}
 unlock:
 	mutex_unlock(&dev->lock);
-	unlock_kernel();
 	blktrans_dev_put(dev);
 	return ret;
 }
-- 
1.7.1



From maximlevitsky at gmail.com  Fri Oct 15 11:20:45 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:45 +0200
Subject: [PATCH 3/5] MTD: blktrans: fix a race vs kthread_stop.
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287156047-17439-4-git-send-email-maximlevitsky@gmail.com>

There is small race window that could make kthread_stop hang forever.
I found that while hacking the IR subsystem.

Signed-off-by: Maxim Levitsky <maximlevisky at gmail.com>
---
 drivers/mtd/mtd_blkdevs.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 040c2d9..a919587 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -133,6 +133,10 @@ static int mtd_blktrans_thread(void *arg)
 
 		if (!req && !(req = blk_fetch_request(rq))) {
 			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
 			spin_unlock_irq(rq->queue_lock);
 			schedule();
 			spin_lock_irq(rq->queue_lock);
-- 
1.7.1



From maximlevitsky at gmail.com  Fri Oct 15 11:20:46 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:46 +0200
Subject: [PATCH 4/5] MTD: r852: remove useless pci powerup/down from
	suspend/resume routines.
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287156047-17439-5-git-send-email-maximlevitsky@gmail.com>

It turns out that pci core now handles these, so this code is redundand
and can even cause bugs

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/nand/r852.c |   30 +-----------------------------
 drivers/mtd/nand/r852.h |    2 --
 2 files changed, 1 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 5169ca6..d9d7efb 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -757,11 +757,6 @@ static irqreturn_t r852_irq(int irq, void *data)
 
 	spin_lock_irqsave(&dev->irqlock, flags);
 
-	/* We can recieve shared interrupt while pci is suspended
-		in that case reads will return 0xFFFFFFFF.... */
-	if (dev->insuspend)
-		goto out;
-
 	/* handle card detection interrupts first */
 	card_status = r852_read_reg(dev, R852_CARD_IRQ_STA);
 	r852_write_reg(dev, R852_CARD_IRQ_STA, card_status);
@@ -1035,7 +1030,6 @@ void r852_shutdown(struct pci_dev *pci_dev)
 int r852_suspend(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
-	unsigned long flags;
 
 	if (dev->ctlreg & R852_CTL_CARDENABLE)
 		return -EBUSY;
@@ -1047,43 +1041,22 @@ int r852_suspend(struct device *device)
 	r852_disable_irqs(dev);
 	r852_engine_disable(dev);
 
-	spin_lock_irqsave(&dev->irqlock, flags);
-	dev->insuspend = 1;
-	spin_unlock_irqrestore(&dev->irqlock, flags);
-
-	/* At that point, even if interrupt handler is running, it will quit */
-	/* So wait for this to happen explictly */
-	synchronize_irq(dev->irq);
-
 	/* If card was pulled off just during the suspend, which is very
 		unlikely, we will remove it on resume, it too late now
 		anyway... */
 	dev->card_unstable = 0;
-
-	pci_save_state(to_pci_dev(device));
-	return pci_prepare_to_sleep(to_pci_dev(device));
+	return 0;
 }
 
 int r852_resume(struct device *device)
 {
 	struct r852_device *dev = pci_get_drvdata(to_pci_dev(device));
-	unsigned long flags;
-
-	/* Turn on the hardware */
-	pci_back_from_sleep(to_pci_dev(device));
-	pci_restore_state(to_pci_dev(device));
 
 	r852_disable_irqs(dev);
 	r852_card_update_present(dev);
 	r852_engine_disable(dev);
 
 
-	/* Now its safe for IRQ to run */
-	spin_lock_irqsave(&dev->irqlock, flags);
-	dev->insuspend = 0;
-	spin_unlock_irqrestore(&dev->irqlock, flags);
-
-
 	/* If card status changed, just do the work */
 	if (dev->card_detected != dev->card_registred) {
 		dbg("card was %s during low power state",
@@ -1121,7 +1094,6 @@ MODULE_DEVICE_TABLE(pci, r852_pci_id_tbl);
 
 SIMPLE_DEV_PM_OPS(r852_pm_ops, r852_suspend, r852_resume);
 
-
 static struct pci_driver r852_pci_driver = {
 	.name		= DRV_NAME,
 	.id_table	= r852_pci_id_tbl,
diff --git a/drivers/mtd/nand/r852.h b/drivers/mtd/nand/r852.h
index 8096cc2..e6a21d9 100644
--- a/drivers/mtd/nand/r852.h
+++ b/drivers/mtd/nand/r852.h
@@ -140,8 +140,6 @@ struct r852_device {
 	/* interrupt handling */
 	spinlock_t irqlock;		/* IRQ protecting lock */
 	int irq;			/* irq num */
-	int insuspend;			/* device is suspended */
-
 	/* misc */
 	void *tmp_buffer;		/* temporary buffer */
 	uint8_t ctlreg;			/* cached contents of control reg */
-- 
1.7.1



From maximlevitsky at gmail.com  Fri Oct 15 11:20:47 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 15 Oct 2010 17:20:47 +0200
Subject: [PATCH 5/5] mtd: sm_ftl: cosmetic, use bool when possible
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287156047-17439-6-git-send-email-maximlevitsky@gmail.com>

I didn't know that kernel allows use of that typedef.

Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
---
 drivers/mtd/sm_ftl.h |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/sm_ftl.h b/drivers/mtd/sm_ftl.h
index e30e48e..43bb730 100644
--- a/drivers/mtd/sm_ftl.h
+++ b/drivers/mtd/sm_ftl.h
@@ -20,7 +20,7 @@
 
 
 struct ftl_zone {
-	int initialized;
+	bool initialized;
 	int16_t *lba_to_phys_table;		/* LBA to physical table */
 	struct kfifo free_sectors;	/* queue of free sectors */
 };
@@ -37,8 +37,8 @@ struct sm_ftl {
 	int zone_count;			/* number of zones */
 	int max_lba;			/* maximum lba in a zone */
 	int smallpagenand;		/* 256 bytes/page nand */
-	int readonly;			/* is FS readonly */
-	int unstable;
+	bool readonly;			/* is FS readonly */
+	bool unstable;
 	int cis_block;			/* CIS block location */
 	int cis_boffset;		/* CIS offset in the block */
 	int cis_page_offset;		/* CIS offset in the page */
@@ -49,7 +49,7 @@ struct sm_ftl {
 	int cache_zone;			/* zone of cached block */
 	unsigned char *cache_data;	/* cached block data */
 	long unsigned int cache_data_invalid_bitmap;
-	int cache_clean;
+	bool cache_clean;
 	struct work_struct flush_work;
 	struct timer_list timer;
 
-- 
1.7.1



From grant.likely at secretlab.ca  Fri Oct 15 11:31:45 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Fri, 15 Oct 2010 09:31:45 -0600
Subject: [PATCH 1/1] mtd: m25p80 -- parse partitions from OF tree
In-Reply-To: <1287147208-11588-1-git-send-email-jonas@southpole.se>
References: <1287147208-11588-1-git-send-email-jonas@southpole.se>
Message-ID: <20101015153145.GD2429@angua.secretlab.ca>

On Fri, Oct 15, 2010 at 02:53:28PM +0200, Jonas Bonn wrote:
> It needs to be possible to define the partitions of an MTD device from an OF
> devicetree.  This patch adds a call to of_mtd_parse_partitions if:

Thanks Jonas.  I've actually already got a patch that does the exact
ame thing in my private tree.  However, it requires an ugly #ifdef
statement because the of_node pointer is not available when CONFIG_OF
is not selected.  Before I commit to this patch, I want to see if I
can come up with a cleaner way for drivers to reference of_node when
CONFIG_OF is not set.  I could use a macro, but I'd rather not have to
wrap every reference with a macro.

Regardless, it is on my radar, and I hope to settle on a solution
sometime in the next week.

g.

> 
> i)   there are no commandline partitions defined
> ii)  there are no partitions set up by platform_data
> iii) and an of_node is present on the device
> 
> This permits the following devicetree structure:
> 
> flash0: mtd at 0 {
> 	compatible = "st,m25p10";
> 	reg = <0>;
> 	spi-max-frequency = <100000000>;
> 
> 	#address-cells = <1>;
> 	#size-cells = <1>;
> 
> 	partition at 0 {
> 		label = "bootloader";
> 		reg = <0x00000000 0x00018000>;
> 		read-only;
> 	}
> 
> 	partition at 18000 {
> 		label = "data";
> 		reg = <0x00018000 0x00008000>;
> 	};
> };
> 
> Signed-off-by: Jonas Bonn <jonas at southpole.se>
> ---
>  drivers/mtd/devices/m25p80.c |    4 ++++
>  1 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index 6f512b5..a349498 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -924,6 +924,10 @@ static int __devinit m25p_probe(struct spi_device *spi)
>  			nr_parts = data->nr_parts;
>  		}
>  
> +		if (nr_parts <= 0 && spi->dev.of_node) {
> +			nr_parts = of_mtd_parse_partitions(&spi->dev, spi->dev.of_node, &parts);
> +		}
> +
>  		if (nr_parts > 0) {
>  			for (i = 0; i < nr_parts; i++) {
>  				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
> -- 
> 1.7.1
> 
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss


From vapier.adi at gmail.com  Fri Oct 15 13:55:39 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 15 Oct 2010 13:55:39 -0400
Subject: [PATCH 2/3] mtd-utils: nanddump: Dynamic buffer,
	increase pagesize/oobsize
In-Reply-To: <1287128665-6573-2-git-send-email-computersforpeace@gmail.com>
References: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
	<1287128665-6573-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTi=XdvN2vGu7Z5M7jj=z_qrx=9F93WiDnPYkcDgY@mail.gmail.com>

On Fri, Oct 15, 2010 at 03:44, Brian Norris wrote:
> + ? ? ? static unsigned char *readbuf, *oobbuf;

no need to make these static still

> + ? ? ? oobbuf = malloc(sizeof(oobbuf) * meminfo.oobsize);
> +       readbuf = malloc(sizeof(readbuf) * meminfo.writesize);

include common.h and use xmalloc

> - ? ? ? close(fd);
> - ? ? ? close(ofd);
> + ? ? ? if (fd) {
> + ? ? ? ? ? ? ? close(fd);
> + ? ? ? ? ? ? ? if (ofd) {
> + ? ? ? ? ? ? ? ? ? ? ? close(ofd);
> + ? ? ? ? ? ? ? }
> + ? ? ? }

0 is a valid fd, thus these checks on the value of the fd dont make
much sense.  i would leave the code as it was.

> + ? ? ? if (oobbuf)
> + ? ? ? ? ? ? ? free(oobbuf);
> + ? ? ? if (readbuf)
> + ? ? ? ? ? ? ? free(readbuf);

drop the "if".  free(NULL) works just fine.
-mike


From vapier.adi at gmail.com  Fri Oct 15 14:58:09 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 15 Oct 2010 14:58:09 -0400
Subject: [PATCH 3/3] mtd-utils: nandwrite: Large page+oob support
In-Reply-To: <1287128665-6573-3-git-send-email-computersforpeace@gmail.com>
References: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
	<1287128665-6573-3-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTik2v8=Lx+HKFTQdgh4czjYuz6P5uevThvAOFcAE@mail.gmail.com>

On Fri, Oct 15, 2010 at 03:44, Brian Norris wrote:
> + ? ? ? oobbuf = (unsigned char *)malloc(meminfo.oobsize);

include common.h and use xmalloc.  also, the malloc cast is useless, so drop it.
> - ? ? ? if (filebuf) {
> + ? ? ? if (filebuf)
> ? ? ? ? ? ? ? ?free(filebuf);
> - ? ? ? }
> + ? ? ? if (oobbuf)
> + ? ? ? ? ? ? ? free(oobbuf);

free(NULL) works fine, so drop the "if" check.
-mike


From eric at eukrea.com  Fri Oct 15 15:34:47 2010
From: eric at eukrea.com (=?UTF-8?B?RXJpYyBCw6luYXJk?=)
Date: Fri, 15 Oct 2010 21:34:47 +0200
Subject: [PATCH] mtd: mxc_nand: do not depend on disabling the irq in
	the interrupt handler
In-Reply-To: <1285240612.29268.76.camel@localhost>
References: <1285054802-21388-1-git-send-email-s.hauer@pengutronix.de>	<1285054802-21388-2-git-send-email-s.hauer@pengutronix.de>
	<1285240612.29268.76.camel@localhost>
Message-ID: <4CB8ACD7.6070206@eukrea.com>

Hi David,

Le 23/09/2010 13:16, Artem Bityutskiy a ?crit :
> On Tue, 2010-09-21 at 09:40 +0200, Sascha Hauer wrote:
>> This patch reverts the driver to enabling/disabling the NFC interrupt
>> mask rather than enabling/disabling the system interrupt. This cleans
>> up the driver so that it doesn't rely on interrupts being disabled
>> within the interrupt handler.
>> For i.MX21 we keep the current behaviour, that is calling
>> enable_irq/disable_irq_nosync to enable/disable interrupts.
>> This patch is based on earlier work by John Ogness.
>>
>> Signed-off-by: Sascha Hauer<s.hauer at pengutronix.de>
>> Acked-by: John Ogness<john.ogness at linutronix.de>
>> Tested-by: John Ogness<john.ogness at linutronix.de>
>
> I've created l2-mtd-2.6.git/for-2.6.36 branch, pushed your patch there,
> pinged dwmw2 for you. I do not give you any guarantees this will reach
> 2.6.36, you have to ping dwmw2.
>
Would that be possible to merge Artem's l2-mtd-2.6.git/for-2.6.36 branch for 
2.6.36 (or at least cherry-pick 34e15930f2c322389d4f946bf891601a2d1e4280 from 
this branch) ? Without it mxc-nand is broken in 2.6.36.

Many thanks
Eric


From sblachman at cranems.com  Fri Oct 15 17:26:50 2010
From: sblachman at cranems.com (Blachman, Steven)
Date: Fri, 15 Oct 2010 16:26:50 -0500
Subject: jffs2 file corruption, clues needed
Message-ID: <45D7FBEF6D444F41AEF557AF2DB5F301047281BE@hakuna.cranems.int>

I am having problems with corrupted files on jffs2 and am looking for
some help finding the cause.

The kernel is version 2.6.27.8 and jffs2 is running on NAND.  Out of
several thousand devices, some have
been returned inoperable because of corrupted files.  The file
corruption is sometimes in the form of a
single-bit error and sometimes in multiple 4K byte chunks.  The 4K
chunks are sometimes all 0s, sometimes
all 1s, sometimes seemingly random, and are occasionally recognizable
pieces of a log file.  In all cases the file
appears to be viewed as valid by jffs2.  I can typically execute such a
file for example although the program
usually crashes.

Most of these files are never written by the application and the systems
often worked for some time before
becoming corrupted.  I do have atime active so perhaps this is causing
thrash to the never written files that
allows them to be garbage collected and therefore subject to this. Is
this correct?

Tests of the NAND on these devices have shown no problems and raw NAND
dumps show no bad blocks.
There are no ECC errors from MTD raw NAND dumps. It looks as if the
files were written wrong!

I have a couple of devices whose raw MTD NAND dumps return a consistent
data set while repeated jffs2 tars
get different results (jffs2 mounted read only of course).

I am hoping for some sugesstions about where I should look for the
problem.  I suspect an original hardware
error caused all this havoc downstream.  How can I go about trying to
localize this?

I have looked at the CVS logs and see that there are a few corrupted
file-related changes but it is not clear
to me that any of these could result in this pathology.   Maybe this has
been fixed already!

I appreciate any clues,
Steven




From computersforpeace at gmail.com  Fri Oct 15 20:35:31 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 15 Oct 2010 17:35:31 -0700
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
Message-ID: <1287189331-9475-1-git-send-email-computersforpeace@gmail.com>

The buffers used for dumping page and OOB data needed dynamic
allocation to help eliminate burdens for updating (i.e., every
time there's a new OOB size we don't have to increase the sizes).

Also, there is no need to check flash chips for "standard sizes."
With recent changes to the printing codebase, we should be able to
handle arbitrary sizes with no problem.

More exit operations are now necessary on program failure, so
"goto closeall" is used more liberally.

Also, common.h is included for the use of xmalloc.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   56 +++++++++++++++++++++-----------------------------------
 1 files changed, 21 insertions(+), 35 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 00762a5..3e7692f 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -32,6 +32,7 @@
 
 #include <asm/types.h>
 #include <mtd/mtd-user.h>
+#include "common.h"
 
 static struct nand_oobinfo none_oobinfo = {
 	.useecc = MTD_NANDECC_OFF,
@@ -265,28 +266,21 @@ nil:
 }
 
 /*
- * Buffers for reading data from flash
- */
-#define NAND_MAX_PAGESIZE 4096
-#define NAND_MAX_OOBSIZE 256
-static unsigned char readbuf[NAND_MAX_PAGESIZE];
-static unsigned char oobbuf[NAND_MAX_OOBSIZE];
-
-/*
  * Main program
  */
 int main(int argc, char * const argv[])
 {
 	unsigned long ofs, end_addr = 0;
 	unsigned long long blockstart = 1;
-	int ret, i, fd, ofd, bs, badblock = 0;
-	struct mtd_oob_buf oob = {0, 16, oobbuf};
+	int ret, i, fd, ofd = 0, bs, badblock = 0;
+	struct mtd_oob_buf oob;
 	mtd_info_t meminfo;
 	char pretty_buf[PRETTY_BUF_LEN];
 	int oobinfochanged = 0 ;
 	struct nand_oobinfo old_oobinfo;
 	struct mtd_ecc_stats stat1, stat2;
 	bool eccstats = false;
+	unsigned char *readbuf = NULL, *oobbuf = NULL;
 
 	process_options(argc, argv);
 
@@ -303,21 +297,14 @@ int main(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 224 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 218 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 32 && meminfo.writesize == 1024) &&
-			!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
-	/* Read the real oob length */
+	/* Allocate buffers */
+	oobbuf = xmalloc(sizeof(oobbuf) * meminfo.oobsize);
+	readbuf = xmalloc(sizeof(readbuf) * meminfo.writesize);
+
+	/* Fill in oob info */
+	oob.start = 0;
 	oob.length = meminfo.oobsize;
+	oob.ptr = oobbuf;
 
 	if (noecc)  {
 		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
@@ -328,20 +315,17 @@ int main(int argc, char * const argv[])
 			case ENOTTY:
 				if (ioctl(fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
 					perror("MEMGETOOBSEL");
-					close(fd);
-					exit(EXIT_FAILURE);
+					goto closeall;
 				}
 				if (ioctl(fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
 					perror("MEMSETOOBSEL");
-					close(fd);
-					exit(EXIT_FAILURE);
+					goto closeall;
 				}
 				oobinfochanged = 1;
 				break;
 			default:
 				perror("MTDFILEMODE");
-				close(fd);
-				exit(EXIT_FAILURE);
+				goto closeall;
 			}
 		}
 	} else {
@@ -364,15 +348,13 @@ int main(int argc, char * const argv[])
 		ofd = STDOUT_FILENO;
 	} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644)) == -1) {
 		perror(dumpfile);
-		close(fd);
-		exit(EXIT_FAILURE);
+		goto closeall;
 	}
 
 	if (!pretty_print && !forcebinary && isatty(ofd)) {
 		fprintf(stderr, "Not printing binary garbage to tty. Use '-a'\n"
 				"or '--forcebinary' to override.\n");
-		close(fd);
-		exit(EXIT_FAILURE);
+		goto closeall;
 	}
 
 	/* Initialize start/end addresses and block size */
@@ -478,9 +460,11 @@ int main(int argc, char * const argv[])
 			return EXIT_FAILURE;
 		}
 	}
-	/* Close the output file and MTD device */
+	/* Close the output file and MTD device, free memory */
 	close(fd);
 	close(ofd);
+	free(oobbuf);
+	free(readbuf);
 
 	/* Exit happy */
 	return EXIT_SUCCESS;
@@ -494,5 +478,7 @@ closeall:
 	}
 	close(fd);
 	close(ofd);
+	free(oobbuf);
+	free(readbuf);
 	exit(EXIT_FAILURE);
 }
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Oct 15 22:12:25 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 15 Oct 2010 19:12:25 -0700
Subject: [PATCH v2 3/3] mtd-utils: nandwrite: Large page+oob support
In-Reply-To: <AANLkTik2v8=Lx+HKFTQdgh4czjYuz6P5uevThvAOFcAE@mail.gmail.com>
References: <AANLkTik2v8=Lx+HKFTQdgh4czjYuz6P5uevThvAOFcAE@mail.gmail.com>
Message-ID: <1287195145-10054-1-git-send-email-computersforpeace@gmail.com>

Dynamic allocation of the oob buffer provides the necessary
support for removing the oob size check. Now, new unknown OOB
sizes can be handled correctly (for example, 8KB page + 448B
OOB).

Included common.h for the use of xmalloc.

Memory freeing should occur on "restoreoob" as well as on
"closeall."

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nandwrite.c |   36 +++++++++---------------------------
 1 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/nandwrite.c b/nandwrite.c
index e0f5f44..1403378 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -41,9 +41,7 @@
 
 #include <asm/types.h>
 #include "mtd/mtd-user.h"
-
-#define MAX_PAGE_SIZE	4096
-#define MAX_OOB_SIZE	128
+#include "common.h"
 
 // oob layouts to pass into the kernel as default
 static struct nand_oobinfo none_oobinfo = {
@@ -276,12 +274,10 @@ int main(int argc, char * const argv[])
 	unsigned char *writebuf = NULL;
 	// points to the OOB for the current page in filebuf
 	unsigned char *oobreadbuf = NULL;
-	unsigned char oobbuf[MAX_OOB_SIZE];
+	unsigned char *oobbuf = NULL;
 
 	process_options(argc, argv);
 
-	erase_buffer(oobbuf, sizeof(oobbuf));
-
 	if (pad && writeoob) {
 		fprintf(stderr, "Can't pad when oob data is present.\n");
 		exit(EXIT_FAILURE);
@@ -304,17 +300,6 @@ int main(int argc, char * const argv[])
 	 * (virtual) block size */
 	meminfo.erasesize *= blockalign;
 
-	/* Make sure device page sizes are valid */
-	if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
-			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
-			!(meminfo.oobsize == 64 && meminfo.writesize == 4096) &&
-			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
-		fprintf(stderr, "Unknown flash (not normal NAND)\n");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
-
 	if (mtdoffset & (meminfo.writesize - 1)) {
 		fprintf(stderr, "The start address is not page-aligned !\n"
 				"The pagesize of this NAND Flash is 0x%x.\n",
@@ -452,14 +437,12 @@ int main(int argc, char * const argv[])
 
 	// Allocate a buffer big enough to contain all the data (OOB included) for one eraseblock
 	filebuf_max = pagelen * meminfo.erasesize / meminfo.writesize;
-	filebuf = (unsigned char *)malloc(filebuf_max);
-	if (!filebuf) {
-		fprintf(stderr, "Failed to allocate memory for file buffer (%d bytes)\n",
-				pagelen * meminfo.erasesize / meminfo.writesize);
-		goto closeall;
-	}
+	filebuf = xmalloc(filebuf_max);
 	erase_buffer(filebuf, filebuf_max);
 
+	oobbuf = xmalloc(meminfo.oobsize);
+	erase_buffer(oobbuf, meminfo.oobsize);
+
 	/*
 	 * Get data from input and write to the device while there is
 	 * still input to read and we are still within the device
@@ -688,13 +671,12 @@ int main(int argc, char * const argv[])
 	failed = false;
 
 closeall:
-	if (filebuf) {
-		free(filebuf);
-	}
-
 	close(ifd);
 
 restoreoob:
+	free(filebuf);
+	free(oobbuf);
+
 	if (oobinfochanged == 1) {
 		if (ioctl(fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
 			perror("MEMSETOOBSEL");
-- 
1.7.0.4




From w.sang at pengutronix.de  Sat Oct 16 01:12:01 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Sat, 16 Oct 2010 07:12:01 +0200
Subject: [PATCH 2/5] MTD: blktrans: kill the BKL.
In-Reply-To: <1287156047-17439-3-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
	<1287156047-17439-3-git-send-email-maximlevitsky@gmail.com>
Message-ID: <20101016051201.GA2992@pengutronix.de>

On Fri, Oct 15, 2010 at 05:20:44PM +0200, Maxim Levitsky wrote:
> It not needed, because I already added locking for all fops
> methods.
> 
> Signed-off-by: Maxim Levitsky

This SoB got damaged.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101016/615f9097/attachment-0001.sig>

From zhangyd6 at gmail.com  Sat Oct 16 02:45:00 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Sat, 16 Oct 2010 14:45:00 +0800
Subject: [PATCH] [MTD] [CHIPS] Add JEDEC probe support for the SST38VF6401
	flash chip
In-Reply-To: <20101015140112.GD4276@pengutronix.de>
References: <1286992482-6009-1-git-send-email-zhangyd6@gmail.com>
	<20101015140112.GD4276@pengutronix.de>
Message-ID: <AANLkTi=7vMoiwdStTW_fi0rvJ1iuU8oRbt5-kMdK29gE@mail.gmail.com>

hi Sang
   According to the datasheet, the flash has no externded Query table,
so i try it in the CFI probe mode it failed. The sector-erase size
operates the whole memory, so does the block-erase size. So i use the
JEDEC probe mode. Sorry for the noise.

On Fri, Oct 15, 2010 at 10:01 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> On Wed, Oct 13, 2010 at 01:54:42PM -0400, zhangyd wrote:
>> Add SST38VF6401(64Mbit) chip to jedec_probe. Sorry for the wrong description of the flash size in last patch.
>
> Can you explain why CFI can't be used?
>
>>
>> Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
>> ---
>> ?drivers/mtd/chips/jedec_probe.c | ? 13 +++++++++++++
>> ?1 files changed, 13 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
>> index d72a5fb..b7a1016 100644
>> --- a/drivers/mtd/chips/jedec_probe.c
>> +++ b/drivers/mtd/chips/jedec_probe.c
>> @@ -163,6 +163,7 @@
>> ?#define SST49LF030A ?0x001C
>> ?#define SST49LF040A ?0x0051
>> ?#define SST49LF080A ?0x005B
>> +#define SST38VF6401 ?0x536B
>> ?#define SST36VF3203 ?0x7354
>>
>> ?/* Toshiba */
>> @@ -1569,6 +1570,18 @@ static const struct amd_flash_info jedec_table[] = {
>> ? ? ? ? ? ? ? }
>> ? ? ? }, {
>> ? ? ? ? ? ? ? .mfr_id ? ? ? ? = CFI_MFR_ST,
>> + ? ? ? ? ? ? .dev_id ? ? ? ? = SST38VF6401,
>> + ? ? ? ? ? ? .name ? ? ? ? ? = "SST 38VF6401",
>> + ? ? ? ? ? ? .devtypes ? ? ? = CFI_DEVICETYPE_X16,
>> + ? ? ? ? ? ? .uaddr ? ? ? ? ?= MTD_UADDR_0X0AAA_0x555,
>> + ? ? ? ? ? ? .dev_size ? ? ? = SIZE_8MiB,
>> + ? ? ? ? ? ? .cmd_set ? ? ? ?= P_ID_AMD_STD,
>> + ? ? ? ? ? ? .nr_regions ? ? = 1,
>> + ? ? ? ? ? ? .regions ? ? ? ?= {
>> + ? ? ? ? ? ? ? ? ? ? ERASEINFO(0x10000,128),
>> + ? ? ? ? ? ? }
>> + ? ? }, {
>> + ? ? ? ? ? ? .mfr_id ? ? ? ? = CFI_MFR_ST,
>> ? ? ? ? ? ? ? .dev_id ? ? ? ? = M29F800AB,
>> ? ? ? ? ? ? ? .name ? ? ? ? ? = "ST M29F800AB",
>> ? ? ? ? ? ? ? .devtypes ? ? ? = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
>> --
>> 1.7.2.3
>>
>>
>> ______________________________________________________
>> Linux MTD discussion mailing list
>> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
>
> iEYEARECAAYFAky4XqcACgkQD27XaX1/VRtKRQCfemn4m3IOVP15NugnbKdkbKgR
> yzoAn2NWzpp/F1GPUO+TW3vB3j9aZR2r
> =Ak1U
> -----END PGP SIGNATURE-----
>
>


From zhangyd6 at gmail.com  Sat Oct 16 03:08:46 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Sat, 16 Oct 2010 15:08:46 +0800
Subject: [Help] SST39VF6401B Support
Message-ID: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>

hi

>Just to apply the patch and see what happens. The most important part
>of this patch is:
>
>Please refer to the data sheets Table 6:
>39VF6401B data sheet http://www.sst.com/downloads/datasheet/S71288.pdf
>39VF6401 data sheet http://www.sst.com/downloads/datasheet/S71223-03.pdf
>
>The difference in the 6th bus write cycle. 39VF6401B uses 0x50 and
>39VF6401 uses 0x30.
>
>Without this even if the chip gets detected you cannot write to it.
>
>I haven't look at this since my try to submit this patch, so I don't
>know how to fix the stuff for cfi_probe.

 Recently, i use the 39VF6401B flash, and i apply your patch. The chip
can be get detected. But when i erase one sector, it use 0x30 to erase
one block. The size of a block is much bigger than a sector as we
know.So i use the JEDEC probe to detect the flash. And i make the
erase size to one block-erase size. And it works fine. So i think
the  chip(39VF6401B)  should not be CFI compliant, maybe the  JEDEC
mode is better.

Regards,
zhang


From vapier at gentoo.org  Sat Oct 16 05:14:53 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 16 Oct 2010 05:14:53 -0400
Subject: [Uclinux-dist-devel] [PATCH] mtd: Blackfin NFC: fix build error
	after nand_scan_ident() change
In-Reply-To: <1282974300-11664-1-git-send-email-vapier@gentoo.org>
References: <1282974300-11664-1-git-send-email-vapier@gentoo.org>
Message-ID: <AANLkTiktR-zNsv4KrnOBh3PxXZTHa6UypzqnwSBpE1=R@mail.gmail.com>

stable team: could you pick this up for 2.6.35.x ?

it has been merged in mainline as eac15a429a27cb74115daaf4c1127c5e854d50e4
-mike


From w.sang at pengutronix.de  Sat Oct 16 06:07:44 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Sat, 16 Oct 2010 12:07:44 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
Message-ID: <20101016100744.GA10815@pengutronix.de>

Hi,

On Sat, Oct 16, 2010 at 03:08:46PM +0800, yidong zhang wrote:
> hi
> 
> >Just to apply the patch and see what happens. The most important part
> >of this patch is:
> >
> >Please refer to the data sheets Table 6:
> >39VF6401B data sheet http://www.sst.com/downloads/datasheet/S71288.pdf
> >39VF6401 data sheet http://www.sst.com/downloads/datasheet/S71223-03.pdf
> >
> >The difference in the 6th bus write cycle. 39VF6401B uses 0x50 and
> >39VF6401 uses 0x30.
> >
> >Without this even if the chip gets detected you cannot write to it.
> >
> >I haven't look at this since my try to submit this patch, so I don't
> >know how to fix the stuff for cfi_probe.
> 
>  Recently, i use the 39VF6401B flash, and i apply your patch. The chip
> can be get detected. But when i erase one sector, it use 0x30 to erase
> one block. The size of a block is much bigger than a sector as we
> know.So i use the JEDEC probe to detect the flash. And i make the
> erase size to one block-erase size. And it works fine. So i think
> the  chip(39VF6401B)  should not be CFI compliant, maybe the  JEDEC
> mode is better.

Please have a look at cfi_cmdset_0002.c, especially the table
cfi_nopri_fixup_table. Without verifying the details, I assume you just have to
add the IDs there and then you can have CFI.

Kind regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101016/44348bec/attachment.sig>

From zhangyd6 at gmail.com  Sat Oct 16 08:25:44 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Sat, 16 Oct 2010 20:25:44 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <20101016100744.GA10815@pengutronix.de>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
Message-ID: <AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>

Hi
  Thanks for your reply. In the cfi_nopri_fixup_table, i added the
below code as you did.
{ CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
And the flash can get detected. But i still have one confusion.
According to the  data sheets Table 6, in the 6th bus write cycle.
39VF6401B uses 0x50 and 39VF6401 uses 0x30. If 39VF6401B uses 0x30 in
the 6th bus write cycle, it will erase a block-size(64KByte). When you
want to erase one sector-size(4KByte), the driver actually erases one
block-size(64KByte).

On Sat, Oct 16, 2010 at 6:07 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> Hi,
>
> On Sat, Oct 16, 2010 at 03:08:46PM +0800, yidong zhang wrote:
>> hi
>>
>> >Just to apply the patch and see what happens. The most important part
>> >of this patch is:
>> >
>> >Please refer to the data sheets Table 6:
>> >39VF6401B data sheet http://www.sst.com/downloads/datasheet/S71288.pdf
>> >39VF6401 data sheet http://www.sst.com/downloads/datasheet/S71223-03.pdf
>> >
>> >The difference in the 6th bus write cycle. 39VF6401B uses 0x50 and
>> >39VF6401 uses 0x30.
>> >
>> >Without this even if the chip gets detected you cannot write to it.
>> >
>> >I haven't look at this since my try to submit this patch, so I don't
>> >know how to fix the stuff for cfi_probe.
>>
>> ?Recently, i use the 39VF6401B flash, and i apply your patch. The chip
>> can be get detected. But when i erase one sector, it use 0x30 to erase
>> one block. The size of a block is much bigger than a sector as we
>> know.So i use the JEDEC probe to detect the flash. And i make the
>> erase size to one block-erase size. And it works fine. So i think
>> the ?chip(39VF6401B) ?should not be CFI compliant, maybe the ?JEDEC
>> mode is better.
>
> Please have a look at cfi_cmdset_0002.c, especially the table
> cfi_nopri_fixup_table. Without verifying the details, I assume you just have to
> add the IDs there and then you can have CFI.
>
> Kind regards,
>
> ? Wolfram
>
> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAky5eXAACgkQD27XaX1/VRs0SwCfe5vFN1rR5mJ+c6agYoJPRYw2
> OksAoJy1j0EZTRN0FYHyfWRONIbaOSZj
> =Mipu
> -----END PGP SIGNATURE-----
>
>


From w.sang at pengutronix.de  Sat Oct 16 08:56:22 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Sat, 16 Oct 2010 14:56:22 +0200
Subject: [PATCH] [MTD] cfi_cmdset_0002: code cleanups
Message-ID: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>

- remove disabled code (hasn't been touched since the beginning of git
  and should be reimplemented if really needed)
- convert remaining c++-comments to plain c-style

Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
Cc: yidong zhang <zhangyd6 at gmail.com>
Cc: Guillaume LECERF <glecerf at gmail.com>
Cc: David Woodhouse <David.Woodhouse at intel.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   47 ++++++-----------------------------
 1 files changed, 8 insertions(+), 39 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 3e6c47b..1934476 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -317,14 +317,14 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
 
 /* Used to fix CFI-Tables of chips without Extended Query Tables */
 static struct cfi_fixup cfi_nopri_fixup_table[] = {
-	{ CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, // SST39VF1602
-	{ CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, // SST39VF1601
-	{ CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, // SST39VF3202
-	{ CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, // SST39VF3201
-	{ CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B
-	{ CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B
-	{ CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B
-	{ CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
+	{ CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */
+	{ CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */
+	{ CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */
+	{ CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */
+	{ CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */
+	{ CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */
+	{ CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */
+	{ CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */
 	{ 0, 0, NULL, NULL }
 };
 
@@ -545,15 +545,6 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 		printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
 		goto setup_err;
 	}
-#if 0
-	// debug
-	for (i=0; i<mtd->numeraseregions;i++){
-		printk("%d: offset=0x%x,size=0x%x,blocks=%d\n",
-		       i,mtd->eraseregions[i].offset,
-		       mtd->eraseregions[i].erasesize,
-		       mtd->eraseregions[i].numblocks);
-	}
-#endif
 
 	__module_get(THIS_MODULE);
 	register_reboot_notifier(&mtd->reboot_notifier);
@@ -1025,9 +1016,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
 	mutex_lock(&chip->mutex);
 
 	if (chip->state != FL_READY){
-#if 0
-		printk(KERN_DEBUG "Waiting for chip to read, status = %d\n", chip->state);
-#endif
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&chip->wq, &wait);
 
@@ -1035,10 +1023,6 @@ static inline int do_read_secsi_onechip(struct map_info *map, struct flchip *chi
 
 		schedule();
 		remove_wait_queue(&chip->wq, &wait);
-#if 0
-		if(signal_pending(current))
-			return -EINTR;
-#endif
 		timeo = jiffies + HZ;
 
 		goto retry;
@@ -1246,9 +1230,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
 		mutex_lock(&cfi->chips[chipnum].mutex);
 
 		if (cfi->chips[chipnum].state != FL_READY) {
-#if 0
-			printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
-#endif
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&cfi->chips[chipnum].wq, &wait);
 
@@ -1256,10 +1237,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
 
 			schedule();
 			remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
-#if 0
-			if(signal_pending(current))
-				return -EINTR;
-#endif
 			goto retry;
 		}
 
@@ -1324,9 +1301,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
 		mutex_lock(&cfi->chips[chipnum].mutex);
 
 		if (cfi->chips[chipnum].state != FL_READY) {
-#if 0
-			printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
-#endif
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			add_wait_queue(&cfi->chips[chipnum].wq, &wait);
 
@@ -1334,10 +1308,6 @@ static int cfi_amdstd_write_words(struct mtd_info *mtd, loff_t to, size_t len,
 
 			schedule();
 			remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
-#if 0
-			if(signal_pending(current))
-				return -EINTR;
-#endif
 			goto retry1;
 		}
 
@@ -1396,7 +1366,6 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	//cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 
 	/* Write Buffer Load */
 	map_write(map, CMD(0x25), cmd_adr);
-- 
1.7.1



From w.sang at pengutronix.de  Sat Oct 16 09:17:52 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Sat, 16 Oct 2010 15:17:52 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
Message-ID: <20101016131752.GA2676@pengutronix.de>

On Sat, Oct 16, 2010 at 08:25:44PM +0800, yidong zhang wrote:
> Hi
>   Thanks for your reply. In the cfi_nopri_fixup_table, i added the
> below code as you did.
> { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B

OK, please just use C-style comments (I just sent another patch
converting the others). Also, would be nice if you could check the
datasheet for other IDs mentioned there and add them, too.

> And the flash can get detected. But i still have one confusion.
> According to the  data sheets Table 6, in the 6th bus write cycle.
> 39VF6401B uses 0x50 and 39VF6401 uses 0x30. If 39VF6401B uses 0x30 in

Ouch! Is this true for the other 39VF*-non-B and B-versions, too?

Adding Guillaume to CC...

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101016/7f129cd3/attachment.sig>

From zhangyd6 at gmail.com  Sat Oct 16 10:20:16 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Sat, 16 Oct 2010 22:20:16 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <20101016131752.GA2676@pengutronix.de>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
Message-ID: <AANLkTimfD5u0d7FaY2nHp-QcA2WH0d0v01qUbA8Jbhrf@mail.gmail.com>

On Sat, Oct 16, 2010 at 9:17 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> On Sat, Oct 16, 2010 at 08:25:44PM +0800, yidong zhang wrote:
>> Hi
>> ? Thanks for your reply. In the cfi_nopri_fixup_table, i added the
>> below code as you did.
>> { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>
> OK, please just use C-style comments (I just sent another patch
> converting the others). Also, would be nice if you could check the
> datasheet for other IDs mentioned there and add them, too.
>
>> And the flash can get detected. But i still have one confusion.
>> According to the ?data sheets Table 6, in the 6th bus write cycle.
>> 39VF6401B uses 0x50 and 39VF6401 uses 0x30. If 39VF6401B uses 0x30 in
>
> Ouch! Is this true for the other 39VF*-non-B and B-versions, too?

Yeah,  it is true for the other  39vf*-no-B and B-versions listed on
the cfi_nopri_fixup_table. And many other chips look like the
39VF*-B-versions.



>
> Adding Guillaume to CC...
>
> Regards,
>
> ? Wolfram
>
> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
>
> iEYEARECAAYFAky5pgAACgkQD27XaX1/VRuEjQCeNCz+zi5WcYZkPqs2e5qPHn2C
> 4dYAn20dlxN5m+SdRDqtaspFiEFR0KAY
> =q/e2
> -----END PGP SIGNATURE-----
>
>


From dedekind1 at gmail.com  Sat Oct 16 11:49:27 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 18:49:27 +0300
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <87lj5zet2y.fsf@macbook.be.48ers.dk>
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
	<87lj5zet2y.fsf@macbook.be.48ers.dk>
Message-ID: <1287244167.1781.2.camel@brekeke>

On Fri, 2010-10-15 at 10:52 +0200, Peter Korsgaard wrote:
> >>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:
> 
>  >> Artem: Time for a v1.4.1 release?
> 
>  Artem> Thanks. If it works, I'll back-port Mike's patch to 1.4.0 and tag it as
>  Artem> 1.4.1. So 1.4.1 won't include tons of irrelevant commits.
> 
> Great. An easy way to test:

Done. You can find v1.4.1 tag, tarball, and announcement in the "news"
section of the web site.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:08:47 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:08:47 +0300
Subject: [PATCH 1/2] nanddump: verify that start address is page aligned
In-Reply-To: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>
References: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>
Message-ID: <1287256127.1781.32.camel@brekeke>

On Tue, 2010-10-12 at 10:23 +0200, Baruch Siach wrote:
> Make nanddump consistent with nandwrite, which does not accept non page aligned
> start addresses. Thus, non page aligned dumps are useless.
> 
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
>  nanddump.c |    6 ++++++
>  1 files changed, 6 insertions(+), 0 deletions(-)
> 
> diff --git a/nanddump.c b/nanddump.c
> index 0fdf736..d6d1352 100644
> --- a/nanddump.c
> +++ b/nanddump.c
> @@ -377,6 +377,12 @@ int main(int argc, char * const argv[])
>  	}
>  
>  	/* Initialize start/end addresses and block size */
> +	if (start_addr & (meminfo.writesize - 1)) {
> +		fprintf(stderr, "The start address is not page-aligned !\n"
> +				"The pagesize of this NAND Flash is 0x%x.\n",
> +				meminfo.writesize);
> +		goto closeall;
> +	}

I'm fine with this change in general, but theoretically we may have a
user who relies on this. Could you please instead print a warning but
preserve the old behavior. Then in after the next release we can make
remove the warning and turn it into an error, just like this patch do.
This will potentially be user-friendly.

Add a new record to the feature-removal-schedule.txt file. I'll then
turn the warning into an error at some point.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:11:02 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:11:02 +0300
Subject: [PATCH 2/2] nanddump: always check the first erase block
In-Reply-To: <c0bf28b432c6f1e6e5ed634ff64afcf46762503a.1286871735.git.baruch@tkos.co.il>
References: <50168b5d486e28a9d7f7685537710e05242c4f12.1286871735.git.baruch@tkos.co.il>
	<c0bf28b432c6f1e6e5ed634ff64afcf46762503a.1286871735.git.baruch@tkos.co.il>
Message-ID: <1287256262.1781.33.camel@brekeke>

On Tue, 2010-10-12 at 10:23 +0200, Baruch Siach wrote:
> Check the first block even when start_addr is not eraseblock aligned.
> 
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
>  nanddump.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)

Pushed to mtd-utils, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:17:27 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:17:27 +0300
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the
	partitions by OF node
In-Reply-To: <1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
Message-ID: <1287256647.1781.34.camel@brekeke>

On Tue, 2010-10-12 at 18:18 +0800, Mingkai Hu wrote:
> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
> Acked-by: Grant Likely <grant.likely at secretlab.ca>
> ---
> v4:
>  - Updated to latest kernel base(Linux 2.6.36-rc7).
>  - Made changes according to Grant's comments.

Looks good to me, pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:28:25 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:28:25 +0300
Subject: [PATCH 1/3] mtd-utils: nanddump/nandwrite: Style fixups
In-Reply-To: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
References: <1287128665-6573-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287257305.1781.40.camel@brekeke>

On Fri, 2010-10-15 at 00:44 -0700, Brian Norris wrote:
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  nanddump.c  |   58 ++++++++++++++----------------
>  nandwrite.c |  114 +++++++++++++++++++++++++++++------------------------------
>  2 files changed, 83 insertions(+), 89 deletions(-)

Pushed to mtd-utils.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:34:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:34:48 +0300
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
	<1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287257688.1781.42.camel@brekeke>

On Fri, 2010-10-15 at 17:35 -0700, Brian Norris wrote:
> The buffers used for dumping page and OOB data needed dynamic
> allocation to help eliminate burdens for updating (i.e., every
> time there's a new OOB size we don't have to increase the sizes).
> 
> Also, there is no need to check flash chips for "standard sizes."
> With recent changes to the printing codebase, we should be able to
> handle arbitrary sizes with no problem.
> 
> More exit operations are now necessary on program failure, so
> "goto closeall" is used more liberally.
> 
> Also, common.h is included for the use of xmalloc.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

The patches look OK for me, but I'll wait a little in case there is
going to be more review.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:37:22 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:37:22 +0300
Subject: Understanding OOB data read implementation (II)
In-Reply-To: <AANLkTi=+2kVMg+YegwRe1SkWWWfF3-=4ZRmvciBZLkCy@mail.gmail.com>
References: <AANLkTi=+2kVMg+YegwRe1SkWWWfF3-=4ZRmvciBZLkCy@mail.gmail.com>
Message-ID: <1287257842.1781.43.camel@brekeke>

On Fri, 2010-10-15 at 12:29 +0100, David Peverley wrote:
> Hi again...!
> 
> I've also noticed after blindly copying it that in the DoC drivers
> that the OOB reads use the ops->len for size :
>     static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
>                             struct mtd_oob_ops *ops)
>         ...
>         uint8_t *buf = ops->oobbuf;
>         size_t len = ops->len;
>         ...
> 
> Reading mtd.h and the following patch summary :
>     http://www.mail-archive.com/git-commits-head at vger.kernel.org/msg03799.html
> 
> I suspect this is wrong and should be using ops->ooblen instead. This
> is especially true given that mtdchar.c leaves ops->len
> uninitialised....! (should mtdchar.c:mtd_do_readoob() not zero the ops
> structure as it's a local automatic so not zero-initialised?) Again
> this is copied in doc2001.c and doc2001plus.c.

If you can test the change - please send a patch.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Oct 16 15:40:43 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 16 Oct 2010 22:40:43 +0300
Subject: [PATCH] [MTD] cfi_cmdset_0002: code cleanups
In-Reply-To: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>
References: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>
Message-ID: <1287258043.1781.45.camel@brekeke>

On Sat, 2010-10-16 at 14:56 +0200, Wolfram Sang wrote:
> - remove disabled code (hasn't been touched since the beginning of git
>   and should be reimplemented if really needed)
> - convert remaining c++-comments to plain c-style
> 
> Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
> Cc: yidong zhang <zhangyd6 at gmail.com>
> Cc: Guillaume LECERF <glecerf at gmail.com>
> Cc: David Woodhouse <David.Woodhouse at intel.com>
> ---
>  drivers/mtd/chips/cfi_cmdset_0002.c |   47 ++++++-----------------------------
>  1 files changed, 8 insertions(+), 39 deletions(-)

Pushed to l2-mtd-2.6.git.

Just FYI, we use "mtd:" prefix for MTD patches. Please, do not use [MTD]
- git am kills it. I think [SUBSYSTEM] prefixes is some ancient pre-git
era stuff. Modern way is to use "SUBSYSTEM:".

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From jacmet at sunsite.dk  Sat Oct 16 16:19:33 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Sat, 16 Oct 2010 22:19:33 +0200
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <1287244167.1781.2.camel@brekeke> (Artem Bityutskiy's message of
	"Sat, 16 Oct 2010 18:49:27 +0300")
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
	<87lj5zet2y.fsf@macbook.be.48ers.dk> <1287244167.1781.2.camel@brekeke>
Message-ID: <878w1xevqi.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

Hi,

 >> Great. An easy way to test:

 Artem> Done. You can find v1.4.1 tag, tarball, and announcement in the "news"
 Artem> section of the web site.

Wow, a tarball right away - Thanks ;)

-- 
Bye, Peter Korsgaard


From computersforpeace at gmail.com  Sat Oct 16 16:54:05 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Sat, 16 Oct 2010 13:54:05 -0700
Subject: [PATCH] mtd-utils: flash_erase: Fix output of offsets
Message-ID: <1287262445-19654-1-git-send-email-computersforpeace@gmail.com>

Need to use unsigned arithmetic and a 64-bit cast in order to
calculate and output the correct offset for eraseblocks at large
offsets. Signed integer arithmetic does not produce the correct
result "uint64_t" result, so for offsets over 2GB we get
messages like:

	Erasing 512 Kibyte @ ffffffff83180000 -- 4308642136 % complete.

Note that this error was not affecting proper erasure; it just
produced incorrect status messages.

Also, we should not add an extra eraseblock for the final status
message; this gives misleading output when, for example, the
following statement is executed:

	$ flash_erase /dev/mtd0 0 1
	Erasing 512 Kibyte @ 80000 -- 100 % complete

We aren't erasing at offset 0x80000; it should display offset 0.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 flash_erase.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/flash_erase.c b/flash_erase.c
index 8929054..1a7b52e 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -93,7 +93,8 @@ int main(int argc, char *argv[])
 {
 	libmtd_t mtd_desc;
 	struct mtd_dev_info mtd;
-	int fd, clmpos = 0, clmlen = 8, eb, eb_start, eb_cnt;
+	int fd, clmpos = 0, clmlen = 8;
+	unsigned int eb, eb_start, eb_cnt;
 	int isNAND;
 	int error = 0;
 	uint64_t offset = 0;
@@ -232,7 +233,7 @@ int main(int argc, char *argv[])
 		eb_cnt = (mtd.size / mtd.eb_size) - eb_start;
 
 	for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
-		offset = eb * mtd.eb_size;
+		offset = (uint64_t)eb * mtd.eb_size;
 
 		if (!noskipbad) {
 			int ret = mtd_is_bad(&mtd, fd, eb);
@@ -285,7 +286,6 @@ int main(int argc, char *argv[])
 		}
 		verbose(!quiet, " Cleanmarker written at %"PRIx64, offset);
 	}
-	offset += mtd.eb_size;
 	show_progress(&mtd, offset, eb, eb_start, eb_cnt);
 	bareverbose(!quiet, "\n");
 
-- 
1.7.0.4




From vapier.adi at gmail.com  Sat Oct 16 17:24:58 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Sat, 16 Oct 2010 17:24:58 -0400
Subject: [PATCH] mtd-utils: flash_erase: Fix output of offsets
In-Reply-To: <1287262445-19654-1-git-send-email-computersforpeace@gmail.com>
References: <1287262445-19654-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTimJZUjGCN18pn64hf263bKvQ27HAfUUiq1hOKrf@mail.gmail.com>

On Sat, Oct 16, 2010 at 16:54, Brian Norris wrote:
> Also, we should not add an extra eraseblock for the final status
> message; this gives misleading output when, for example, the
> following statement is executed:
>
> ? ? ? ?$ flash_erase /dev/mtd0 0 1
> ? ? ? ?Erasing 512 Kibyte @ 80000 -- 100 % complete
>
> We aren't erasing at offset 0x80000; it should display offset 0.

yeah, this was to fix the display not getting to 100%, but then i
fixed it another way and forgot to undo this line

Acked-by: Mike Frysinger <vapier at gentoo.org>
-mike


From vapier at gentoo.org  Sat Oct 16 18:26:59 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 16 Oct 2010 18:26:59 -0400
Subject: [PATCH] mtd: Blackfin NFC: fix badblock location with BootROM OOB
Message-ID: <1287268019-9426-1-git-send-email-vapier@gentoo.org>

The bbt structure isn't actually used, just the badblockpos.  This lets
the driver correctly handle badblocks with the different OOB layout with
certain sized flashes.  Previously, the blocks would all be reported as
bad and be completely unusable.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 drivers/mtd/nand/bf5xx_nand.c |   14 ++++----------
 1 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
index 6fbeefa..79947be 100644
--- a/drivers/mtd/nand/bf5xx_nand.c
+++ b/drivers/mtd/nand/bf5xx_nand.c
@@ -110,15 +110,6 @@ static const unsigned short bfin_nfc_pin_req[] =
 	 0};
 
 #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
-static uint8_t bbt_pattern[] = { 0xff };
-
-static struct nand_bbt_descr bootrom_bbt = {
-	.options = 0,
-	.offs = 63,
-	.len = 1,
-	.pattern = bbt_pattern,
-};
-
 static struct nand_ecclayout bootrom_ecclayout = {
 	.eccbytes = 24,
 	.eccpos = {
@@ -809,7 +800,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
 	/* setup hardware ECC data struct */
 	if (hardware_ecc) {
 #ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
-		chip->badblock_pattern = &bootrom_bbt;
 		chip->ecc.layout = &bootrom_ecclayout;
 #endif
 		chip->read_buf      = bf5xx_nand_dma_read_buf;
@@ -830,6 +820,10 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
 		goto out_err_nand_scan;
 	}
 
+#ifdef CONFIG_MTD_NAND_BF5XX_BOOTROM_ECC
+	chip->badblockpos = 63;
+#endif
+
 	/* add NAND partition */
 	bf5xx_nand_add_partition(info);
 
-- 
1.7.3.1



From vapier at gentoo.org  Sat Oct 16 18:31:14 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 16 Oct 2010 18:31:14 -0400
Subject: [PATCH] mtd/maps: gpio-addr-flash: fix warnings and make more portable
Message-ID: <1287268274-9750-1-git-send-email-vapier@gentoo.org>

As reported on lkml, building this module for HIMEM systems spews warnings
about mismatch in pointer types.  Further, we need to use ioremap() in order
to properly access the flash memory on most systems rather than just doing
it directly.

Reported-by: Alan Cox <alan at linux.intel.com>
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 drivers/mtd/maps/gpio-addr-flash.c |   10 +++++++---
 1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 32e89d7..af5707a 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -208,10 +208,14 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 	if (!state)
 		return -ENOMEM;
 
+	/*
+	 * We cast start/end to known types in the boards file, so cast
+	 * away their pointer types here to the known types (gpios->xxx).
+	 */
 	state->gpio_count     = gpios->end;
-	state->gpio_addrs     = (void *)gpios->start;
+	state->gpio_addrs     = (void *)(unsigned long)gpios->start;
 	state->gpio_values    = (void *)(state + 1);
-	state->win_size       = memory->end - memory->start + 1;
+	state->win_size       = resource_size(memory);
 	memset(state->gpio_values, 0xff, arr_size);
 
 	state->map.name       = DRIVER_NAME;
@@ -221,7 +225,7 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 	state->map.copy_to    = gf_copy_to;
 	state->map.bankwidth  = pdata->width;
 	state->map.size       = state->win_size * (1 << state->gpio_count);
-	state->map.virt       = (void __iomem *)memory->start;
+	state->map.virt       = ioremap_nocache(memory->start, state->map.size);
 	state->map.phys       = NO_XIP;
 	state->map.map_priv_1 = (unsigned long)state;
 
-- 
1.7.3.1



From maximlevitsky at gmail.com  Sat Oct 16 18:46:27 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Sun, 17 Oct 2010 00:46:27 +0200
Subject: [PATCH 2/5] MTD: blktrans: kill the BKL.
In-Reply-To: <20101016051201.GA2992@pengutronix.de>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
	<1287156047-17439-3-git-send-email-maximlevitsky@gmail.com>
	<20101016051201.GA2992@pengutronix.de>
Message-ID: <1287269187.17093.0.camel@maxim-laptop>

On Sat, 2010-10-16 at 07:12 +0200, Wolfram Sang wrote:
> On Fri, Oct 15, 2010 at 05:20:44PM +0200, Maxim Levitsky wrote:
> > It not needed, because I already added locking for all fops
> > methods.
> > 
> > Signed-off-by: Maxim Levitsky
> 
> This SoB got damaged.
> 

Should I resend it?
Signed-of-by: Maxim Levitsky <maximlevitky at gmail.com>

Best regards,
	Maxim Levitsky



From grant.likely at secretlab.ca  Sat Oct 16 21:05:33 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Sat, 16 Oct 2010 19:05:33 -0600
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the partitions
	by OF node
In-Reply-To: <1287256647.1781.34.camel@brekeke>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
	<1287256647.1781.34.camel@brekeke>
Message-ID: <AANLkTimr03KAKnz5sfwm19=KzB-ik95WM_qQO0YP9qVs@mail.gmail.com>

On Sat, Oct 16, 2010 at 1:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2010-10-12 at 18:18 +0800, Mingkai Hu wrote:
>> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
>> Acked-by: Grant Likely <grant.likely at secretlab.ca>
>> ---
>> v4:
>> ?- Updated to latest kernel base(Linux 2.6.36-rc7).
>> ?- Made changes according to Grant's comments.
>
> Looks good to me, pushed to l2-mtd-2.6.git, thanks.

Wait!  It will break whenever CONFIG_OF is not set.  I broke
linux-next with this patch.  It can be solved by wrapping the block
with #ifdef CONFIG_OF, but I'd like to find a better solution.

g.


From madap_vamshikrishna at yahoo.co.in  Sat Oct 16 23:47:42 2010
From: madap_vamshikrishna at yahoo.co.in (vamshikrishna madap)
Date: Sun, 17 Oct 2010 09:17:42 +0530
Subject: dussera wishes
Message-ID: <AANLkTims6xH9im5ygpo0dUGGdS=hQMvnHkLh4QMpW2HP@mail.gmail.com>

Wish you all a happy and prosperous dussera.

Regards,
Vamshi


From dedekind1 at gmail.com  Sun Oct 17 03:44:50 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 10:44:50 +0300
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the
	partitions by OF node
In-Reply-To: <AANLkTimr03KAKnz5sfwm19=KzB-ik95WM_qQO0YP9qVs@mail.gmail.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
	<1287256647.1781.34.camel@brekeke>
	<AANLkTimr03KAKnz5sfwm19=KzB-ik95WM_qQO0YP9qVs@mail.gmail.com>
Message-ID: <1287301490.1951.0.camel@localhost>

On Sat, 2010-10-16 at 19:05 -0600, Grant Likely wrote:
> On Sat, Oct 16, 2010 at 1:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Tue, 2010-10-12 at 18:18 +0800, Mingkai Hu wrote:
> >> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
> >> Acked-by: Grant Likely <grant.likely at secretlab.ca>
> >> ---
> >> v4:
> >>  - Updated to latest kernel base(Linux 2.6.36-rc7).
> >>  - Made changes according to Grant's comments.
> >
> > Looks good to me, pushed to l2-mtd-2.6.git, thanks.
> 
> Wait!  It will break whenever CONFIG_OF is not set.  I broke
> linux-next with this patch.  It can be solved by wrapping the block
> with #ifdef CONFIG_OF, but I'd like to find a better solution.

OK, removed.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 04:00:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 11:00:34 +0300
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
	<1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287302434.1951.2.camel@localhost>

On Fri, 2010-10-15 at 17:35 -0700, Brian Norris wrote:
> The buffers used for dumping page and OOB data needed dynamic
> allocation to help eliminate burdens for updating (i.e., every
> time there's a new OOB size we don't have to increase the sizes).
> 
> Also, there is no need to check flash chips for "standard sizes."
> With recent changes to the printing codebase, we should be able to
> handle arbitrary sizes with no problem.
> 
> More exit operations are now necessary on program failure, so
> "goto closeall" is used more liberally.
> 
> Also, common.h is included for the use of xmalloc.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---

Patches did not apply cleanly, but I've resolved conflicts an pushed
them, thank you.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 04:04:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 11:04:15 +0300
Subject: [PATCH] mtd-utils: flash_erase: Fix output of offsets
In-Reply-To: <1287262445-19654-1-git-send-email-computersforpeace@gmail.com>
References: <1287262445-19654-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287302655.1951.3.camel@localhost>

On Sat, 2010-10-16 at 13:54 -0700, Brian Norris wrote:
> Need to use unsigned arithmetic and a 64-bit cast in order to
> calculate and output the correct offset for eraseblocks at large
> offsets. Signed integer arithmetic does not produce the correct
> result "uint64_t" result, so for offsets over 2GB we get
> messages like:
> 
> 	Erasing 512 Kibyte @ ffffffff83180000 -- 4308642136 % complete.
> 
> Note that this error was not affecting proper erasure; it just
> produced incorrect status messages.
> 
> Also, we should not add an extra eraseblock for the final status
> message; this gives misleading output when, for example, the
> following statement is executed:
> 
> 	$ flash_erase /dev/mtd0 0 1
> 	Erasing 512 Kibyte @ 80000 -- 100 % complete
> 
> We aren't erasing at offset 0x80000; it should display offset 0.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 04:49:51 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 11:49:51 +0300
Subject: [PATCH] mtd: Blackfin NFC: fix badblock location with BootROM OOB
In-Reply-To: <1287268019-9426-1-git-send-email-vapier@gentoo.org>
References: <1287268019-9426-1-git-send-email-vapier@gentoo.org>
Message-ID: <1287305391.1951.4.camel@localhost>

On Sat, 2010-10-16 at 18:26 -0400, Mike Frysinger wrote:
> The bbt structure isn't actually used, just the badblockpos.  This lets
> the driver correctly handle badblocks with the different OOB layout with
> certain sized flashes.  Previously, the blocks would all be reported as
> bad and be completely unusable.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  drivers/mtd/nand/bf5xx_nand.c |   14 ++++----------
>  1 files changed, 4 insertions(+), 10 deletions(-)

Taken both patches to l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 04:51:27 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 11:51:27 +0300
Subject: [PATCH 2/5] MTD: blktrans: kill the BKL.
In-Reply-To: <1287269187.17093.0.camel@maxim-laptop>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
	<1287156047-17439-3-git-send-email-maximlevitsky@gmail.com>
	<20101016051201.GA2992@pengutronix.de>
	<1287269187.17093.0.camel@maxim-laptop>
Message-ID: <1287305487.1951.6.camel@localhost>

On Sun, 2010-10-17 at 00:46 +0200, Maxim Levitsky wrote:
> On Sat, 2010-10-16 at 07:12 +0200, Wolfram Sang wrote:
> > On Fri, Oct 15, 2010 at 05:20:44PM +0200, Maxim Levitsky wrote:
> > > It not needed, because I already added locking for all fops
> > > methods.
> > > 
> > > Signed-off-by: Maxim Levitsky
> > 
> > This SoB got damaged.
> > 
> 
> Should I resend it?
> Signed-of-by: Maxim Levitsky <maximlevitky at gmail.com>

Ideally yes, the maintainer ideally should be able to just git am your
patch without having to copy-paste anything. Also, MTD subsystem's
prefix is "mtd:".

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 06:15:09 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 13:15:09 +0300
Subject: [MTD] My updates [RESEND]
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287310509.1951.13.camel@localhost>

On Fri, 2010-10-15 at 17:20 +0200, Maxim Levitsky wrote:
> Here are few patches for 2.6.37 that I have in my patch queue for MTD.
> 
> Best regards,
> 	Maxim Levitsky

I've just tested this and it fixes the issue Kevin Kernekee reported
here:
http://lists.infradead.org/pipermail/linux-mtd/2010-September/031925.html

CCing him as it is nice to inform reporters about fixes.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 06:22:03 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 13:22:03 +0300
Subject: [MTD] My updates [RESEND]
In-Reply-To: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287310923.1951.14.camel@localhost>

On Fri, 2010-10-15 at 17:20 +0200, Maxim Levitsky wrote:
> Here are few patches for 2.6.37 that I have in my patch queue for MTD.
> 
> Best regards,
> 	Maxim Levitsky

I've added this series to my l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Sun Oct 17 12:19:00 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Sun, 17 Oct 2010 09:19:00 -0700
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <1287302434.1951.2.camel@localhost>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>	
	<1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
	<1287302434.1951.2.camel@localhost>
Message-ID: <4CBB21F4.4030105@gmail.com>

On 10/17/2010 1:00 AM, Artem Bityutskiy wrote:
> Patches did not apply cleanly, but I've resolved conflicts an pushed
> them, thank you.

Perhaps this is because (as far as I can tell) you didn't actually push
the first one (style fixups) like you said you did? :) I can rebase it
and resend if that's a problem.

Brian


From dedekind1 at gmail.com  Sun Oct 17 14:03:30 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 21:03:30 +0300
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <4CBB21F4.4030105@gmail.com>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
	<1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
	<1287302434.1951.2.camel@localhost>  <4CBB21F4.4030105@gmail.com>
Message-ID: <1287338610.1781.67.camel@brekeke>

On Sun, 2010-10-17 at 09:19 -0700, Brian Norris wrote:
> On 10/17/2010 1:00 AM, Artem Bityutskiy wrote:
> > Patches did not apply cleanly, but I've resolved conflicts an pushed
> > them, thank you.
> 
> Perhaps this is because (as far as I can tell) you didn't actually push
> the first one (style fixups) like you said you did? :) I can rebase it
> and resend if that's a problem.

Uhhh, I'll sort it out, apologies.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sun Oct 17 14:23:55 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 17 Oct 2010 21:23:55 +0300
Subject: [PATCH v2 2/3] mtd-utils: nanddump: Dynamic buffer, increase
	pagesize/oobsize
In-Reply-To: <1287338610.1781.67.camel@brekeke>
References: <AANLkTi%3DXdvN2vGu7Z5M7jj%3Dz_qrx%3D9F93WiDnPYkcDgY@mail.gmail.com>
	<1287189331-9475-1-git-send-email-computersforpeace@gmail.com>
	<1287302434.1951.2.camel@localhost>  <4CBB21F4.4030105@gmail.com>
	<1287338610.1781.67.camel@brekeke>
Message-ID: <1287339835.1781.68.camel@brekeke>

On Sun, 2010-10-17 at 21:03 +0300, Artem Bityutskiy wrote:
> On Sun, 2010-10-17 at 09:19 -0700, Brian Norris wrote:
> > On 10/17/2010 1:00 AM, Artem Bityutskiy wrote:
> > > Patches did not apply cleanly, but I've resolved conflicts an pushed
> > > them, thank you.
> > 
> > Perhaps this is because (as far as I can tell) you didn't actually push
> > the first one (style fixups) like you said you did? :) I can rebase it
> > and resend if that's a problem.
> 
> Uhhh, I'll sort it out, apologies.

Done. Now pushed for real.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From julia at diku.dk  Sun Oct 17 14:48:31 2010
From: julia at diku.dk (Julia Lawall)
Date: Sun, 17 Oct 2010 20:48:31 +0200
Subject: [PATCH 3/3] fs/jffs2/dir.c: Use kasprintf
In-Reply-To: <1287341311-11161-1-git-send-email-julia@diku.dk>
References: <1287341311-11161-1-git-send-email-julia@diku.dk>
Message-ID: <1287341311-11161-4-git-send-email-julia@diku.dk>

Convert a sequence of kmalloc and memcpy to use kasprintf.  The argument is
checked for being a string by the presence of a previous call to strlen.

The semantic patch that performs this transformation is:
(http://coccinelle.lip6.fr/)

// <smpl>
@@
expression a,flag,len;
expression arg,e1,e2;
statement S;
@@

  len = strlen(arg)
  ... when != len = e1
      when != arg = e2
  a =
-  \(kmalloc\|kzalloc\)(len+1,flag)
+  kasprintf(flag,"%s",arg)
  <... when != a
  if (a == NULL || ...) S
  ...>
- memcpy(a,arg,len+1);
// </smpl>

Signed-off-by: Julia Lawall <julia at diku.dk>

---
 fs/jffs2/dir.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index ed78a3c..8ee5675 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -367,7 +367,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 	}
 
 	/* We use f->target field to store the target path. */
-	f->target = kmalloc(targetlen + 1, GFP_KERNEL);
+	f->target = kasprintf(GFP_KERNEL, "%s", target);
 	if (!f->target) {
 		printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
 		mutex_unlock(&f->sem);
@@ -376,7 +376,6 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 		goto fail;
 	}
 
-	memcpy(f->target, target, targetlen + 1);
 	D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target));
 
 	/* No data here. Only a metadata node, which will be



From julia at diku.dk  Sun Oct 17 15:56:15 2010
From: julia at diku.dk (Julia Lawall)
Date: Sun, 17 Oct 2010 21:56:15 +0200 (CEST)
Subject: [PATCH 3/3] fs/jffs2/dir.c: Use kmemdup
In-Reply-To: <1287341849.20968.62.camel@Joe-Laptop>
References: <1287341311-11161-1-git-send-email-julia@diku.dk> 
	<1287341311-11161-4-git-send-email-julia@diku.dk>
	<1287341849.20968.62.camel@Joe-Laptop>
Message-ID: <Pine.LNX.4.64.1010172155240.394@ask.diku.dk>

Convert a sequence of kmalloc and memcpy to use kmemdup.

The semantic patch that performs this transformation is:
(http://coccinelle.lip6.fr/)

// <smpl>
@@
expression a,flag,len;
expression arg,e1,e2;
statement S;
@@

  a =
-  \(kmalloc\|kzalloc\)(len,flag)
+  kmemdup(arg,len,flag)
  <... when != a
  if (a == NULL || ...) S
  ...>
- memcpy(a,arg,len+1);
// </smpl>

Signed-off-by: Julia Lawall <julia at diku.dk>

---
 fs/jffs2/dir.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff -u -p a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -367,7 +367,7 @@ static int jffs2_symlink (struct inode *
 	}
 
 	/* We use f->target field to store the target path. */
-	f->target = kmalloc(targetlen + 1, GFP_KERNEL);
+	f->target = kmemdup(target, targetlen + 1, GFP_KERNEL);
 	if (!f->target) {
 		printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
 		mutex_unlock(&f->sem);
@@ -376,7 +376,6 @@ static int jffs2_symlink (struct inode *
 		goto fail;
 	}
 
-	memcpy(f->target, target, targetlen + 1);
 	D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target));
 
 	/* No data here. Only a metadata node, which will be


From fggs at terra.com.br  Sun Oct 17 16:22:27 2010
From: fggs at terra.com.br (=?UTF-8?Q?Fl=C3=A1vio_Silveira?=)
Date: Sun, 17 Oct 2010 18:22:27 -0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTi=cnQpszRyVXfCOF=kFwc5v8-2pKKnTJXm45_jK@mail.gmail.com>
References: <E73F778B634944A0B8D4333B7BD012E4@THOR><AANLkTin2b-QovauogfjMZP_7KeChY5oWsMPFBAiC2ERE@mail.gmail.com><74A5BE60138147F696E151AACD52EDEE@THOR><AANLkTintkdKGpkUGMkgGbVK6Pb3cttspwnuPQR=DJxnm@mail.gmail.com><D3A375B91F5944B38630B07214914DF8@THOR><AANLkTinotjfB26VPmF7_vx8M1kX5cYMzygFMk8X6exww@mail.gmail.com><341EADF720C14B4F86C63204D9C60723@THOR><AANLkTikXbKZLFOCBDkrwgVPJEYTwF88xBtYFnwaTQH+5@mail.gmail.com><6E1A182A06054C5A99BD3C0D3202C24F@THOR><AANLkTi=qZ_wYcHHfKjaJsvf-ODgnECDOTEHmuorpA7K2@mail.gmail.com><DB610A768D2B46C7A888B2DBECEBEC79@THOR><AANLkTi=7WAJL4S5jJQQAHSp=KK2t5a5BwSow5r7Mco99@mail.gmail.com><8129711D4006470194ABF97D154047CF@THOR>
	<AANLkTi=cnQpszRyVXfCOF=kFwc5v8-2pKKnTJXm45_jK@mail.gmail.com>
Message-ID: <D3E9E99BD9504AE0818978A598F6F5E8@THOR>

Sorry for the delay, I was travelling.

Not yet, I couldn't build a firmware without your patch to test it, perhaps 
in the middle of this week, but I'm guessing it is needed.

Flavio

----- Original Message ----- 
From: "Guillaume LECERF" <glecerf at gmail.com>
To: "Fl?vio Silveira" <fggs at terra.com.br>
Cc: <linux-mtd at lists.infradead.org>
Sent: Tuesday, October 12, 2010 8:48 AM
Subject: Re: [Help] SST39VF6401B Support


> 2010/10/5 Fl?vio Silveira <fggs at terra.com.br>:
>> Actually yes, I applied your patch to kernel 2.6.35.4 and it detects the
>> chip.
>> I just need to test without your patch to see the difference.
>
> Up.
>
> Did you had time to test without the patch to see if it's actually needed 
> ?
>
> -- 
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
> 



From dedekind1 at gmail.com  Sun Oct 17 23:43:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 06:43:34 +0300
Subject: [PATCH 3/3] fs/jffs2/dir.c: Use kmemdup
In-Reply-To: <Pine.LNX.4.64.1010172155240.394@ask.diku.dk>
References: <1287341311-11161-1-git-send-email-julia@diku.dk>
	<1287341311-11161-4-git-send-email-julia@diku.dk>
	<1287341849.20968.62.camel@Joe-Laptop>
	<Pine.LNX.4.64.1010172155240.394@ask.diku.dk>
Message-ID: <1287373414.1972.25.camel@localhost>

On Sun, 2010-10-17 at 21:56 +0200, Julia Lawall wrote:
> Convert a sequence of kmalloc and memcpy to use kmemdup.
> 
> The semantic patch that performs this transformation is:
> (http://coccinelle.lip6.fr/)
> 
> // <smpl>
> @@
> expression a,flag,len;
> expression arg,e1,e2;
> statement S;
> @@
> 
>   a =
> -  \(kmalloc\|kzalloc\)(len,flag)
> +  kmemdup(arg,len,flag)
>   <... when != a
>   if (a == NULL || ...) S
>   ...>
> - memcpy(a,arg,len+1);
> // </smpl>
> 
> Signed-off-by: Julia Lawall <julia at diku.dk>
> 
> ---
>  fs/jffs2/dir.c |    3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)

Picked this one and put to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Sun Oct 17 23:43:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 06:43:34 +0300
Subject: [PATCH 3/3] fs/jffs2/dir.c: Use kmemdup
In-Reply-To: <Pine.LNX.4.64.1010172155240.394@ask.diku.dk>
References: <1287341311-11161-1-git-send-email-julia@diku.dk>
	<1287341311-11161-4-git-send-email-julia@diku.dk>
	<1287341849.20968.62.camel@Joe-Laptop>
	<Pine.LNX.4.64.1010172155240.394@ask.diku.dk>
Message-ID: <1287373414.1972.25.camel@localhost>

On Sun, 2010-10-17 at 21:56 +0200, Julia Lawall wrote:
> Convert a sequence of kmalloc and memcpy to use kmemdup.
> 
> The semantic patch that performs this transformation is:
> (http://coccinelle.lip6.fr/)
> 
> // <smpl>
> @@
> expression a,flag,len;
> expression arg,e1,e2;
> statement S;
> @@
> 
>   a =
> -  \(kmalloc\|kzalloc\)(len,flag)
> +  kmemdup(arg,len,flag)
>   <... when != a
>   if (a == NULL || ...) S
>   ...>
> - memcpy(a,arg,len+1);
> // </smpl>
> 
> Signed-off-by: Julia Lawall <julia at diku.dk>
> 
> ---
>  fs/jffs2/dir.c |    3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)

Picked this one and put to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From zhangyd6 at gmail.com  Mon Oct 18 00:00:46 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 18 Oct 2010 12:00:46 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <20101016131752.GA2676@pengutronix.de>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
Message-ID: <AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>

hi
   The 39VF*-B-Version flashes in the cfi_nopri_fixup_table don't work
well in the current code.  Because of the mistaken use of
command(0x30) in the 6th bus cycle, which should be 0x50. I think the
39VF*-B-Version flashes should be removed form the CFI probe mode. Or
maybe the erase operation should be changed for the Compatibility.

On Sat, Oct 16, 2010 at 9:17 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> On Sat, Oct 16, 2010 at 08:25:44PM +0800, yidong zhang wrote:
>> Hi
>> ? Thanks for your reply. In the cfi_nopri_fixup_table, i added the
>> below code as you did.
>> { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>
> OK, please just use C-style comments (I just sent another patch
> converting the others). Also, would be nice if you could check the
> datasheet for other IDs mentioned there and add them, too.
>
>> And the flash can get detected. But i still have one confusion.
>> According to the ?data sheets Table 6, in the 6th bus write cycle.
>> 39VF6401B uses 0x50 and 39VF6401 uses 0x30. If 39VF6401B uses 0x30 in
>
> Ouch! Is this true for the other 39VF*-non-B and B-versions, too?
>
> Adding Guillaume to CC...
>
> Regards,
>
> ? Wolfram
>
> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
>
> iEYEARECAAYFAky5pgAACgkQD27XaX1/VRuEjQCeNCz+zi5WcYZkPqs2e5qPHn2C
> 4dYAn20dlxN5m+SdRDqtaspFiEFR0KAY
> =q/e2
> -----END PGP SIGNATURE-----
>
>


From dedekind1 at gmail.com  Mon Oct 18 01:46:08 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 08:46:08 +0300
Subject: [PATCH 1/2] UBIFS: remove a bit of unneeded code
Message-ID: <1287380769-8250-1-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This is a clean-up patch which:

1. Removes explicite 'hrtimer_cancel()' after 'ubifs_wbuf_sync()' in
   'ubifs_remount_ro()', because the timers will be canceled by
   'ubifs_wbuf_sync()', no need to cancel them for the second time.
2. Remove "if (c->jheads)" check from 'ubifs_put_super()', because
   at journal heads must always be allocated there, since we checked
   earlier that we were mounted R/W, and the olny situation when
   journal heads are not allocated is when mounter or re-mounted R/O.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index bb6ed5d..6ff2f80 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1686,10 +1686,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
 
 	dbg_save_space_info(c);
 
-	for (i = 0; i < c->jhead_cnt; i++) {
+	for (i = 0; i < c->jhead_cnt; i++)
 		ubifs_wbuf_sync(&c->jheads[i].wbuf);
-		hrtimer_cancel(&c->jheads[i].wbuf.timer);
-	}
 
 	c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY);
 	c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS);
@@ -1754,9 +1752,8 @@ static void ubifs_put_super(struct super_block *sb)
 			int err;
 
 			/* Synchronize write-buffers */
-			if (c->jheads)
-				for (i = 0; i < c->jhead_cnt; i++)
-					ubifs_wbuf_sync(&c->jheads[i].wbuf);
+			for (i = 0; i < c->jhead_cnt; i++)
+				ubifs_wbuf_sync(&c->jheads[i].wbuf);
 
 			/*
 			 * We are being cleanly unmounted which means the
-- 
1.7.2.3



From dedekind1 at gmail.com  Mon Oct 18 01:46:09 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 08:46:09 +0300
Subject: [PATCH 2/2] UBIFS: do not forget to cancel timers
In-Reply-To: <1287380769-8250-1-git-send-email-dedekind1@gmail.com>
References: <1287380769-8250-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1287380769-8250-2-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This is a bug-fix: when we unmount, and we are currently in R/O
mode because of an error - we do not sync write-buffers, which
means we also do not cancel write-buffer timers we may possibly
have armed. This patch fixes the issue.

The issue can easily be reproduced by enabling UBIFS failure debug
mode (echo 4 > /sys/module/ubifs/parameters/debug_tsts) and
unmounting as soon as a failure happen. At some point the system
oopses because we have an armed hrtimer but UBIFS is unmounted
already.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 6ff2f80..98695f9 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1772,7 +1772,11 @@ static void ubifs_put_super(struct super_block *sb)
 				 */
 				ubifs_err("failed to write master node, "
 					  "error %d", err);
-		}
+		} else {
+			for (i = 0; i < c->jhead_cnt; i++)
+				/* Make sure write-buffer timers are canceled */
+				hrtimer_cancel(&c->jheads[i].wbuf.timer);
+ 		}
 	}
 
 	ubifs_umount(c);
-- 
1.7.2.3



From baruch at tkos.co.il  Mon Oct 18 03:23:25 2010
From: baruch at tkos.co.il (Baruch Siach)
Date: Mon, 18 Oct 2010 09:23:25 +0200
Subject: [PATCH] nanddump: warn when the start address is not page aligned
In-Reply-To: <1287256127.1781.32.camel@brekeke>
References: <1287256127.1781.32.camel@brekeke>
Message-ID: <1909cbad57553279212f156a0c7cb20178981909.1287386497.git.baruch@tkos.co.il>

nanddump should be consistent with nandwrite, which does not accept non page
aligned start addresses. Thus, non page aligned dumps are useless.

To ease migration only warn for now. Add the plan of making this an error to
feature-removal-schedule.txt.

Signed-off-by: Baruch Siach <baruch at tkos.co.il>
---
 feature-removal-schedule.txt |   12 +++++++++++-
 nanddump.c                   |    7 +++++++
 2 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 21bc8d4..f4ed2a3 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -27,5 +27,15 @@ So the plan is (to be done by Artem Bityutskiy):
 3.1 adding a warning to make users stop using them
 3.2 removing both options.
 ---------------------------
-2.
+2. nanddump: fail when the -s parameter is not page aligned
+
+nanddump should be consistent with nandwrite, and refuse accepting non page 
+aligned start addresses. These dumps are most likely useless, since nandwrite 
+won't write then at this location. Currently only a warning is issued to keep 
+backward compatibility during a transition period. This should become an error 
+after 1.5.0.
+
+To be done by Artem Bityutskiy.
+---------------------------
+3.
 ---------------------------
diff --git a/nanddump.c b/nanddump.c
index 15bf9c4..bb649da 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -360,6 +360,13 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Initialize start/end addresses and block size */
+	if (start_addr & (meminfo.writesize - 1)) {
+		fprintf(stderr, "WARNING: The start address is not page-aligned !\n"
+				"The pagesize of this NAND Flash is 0x%x.\n"
+				"nandwrite doesn't allow writes starting at this location.\n"
+				"Future versions of nanddump will fail here.\n",
+				meminfo.writesize);
+	}
 	if (length)
 		end_addr = start_addr + length;
 	if (!length || end_addr > meminfo.size)
-- 
1.7.1



From tie-fei.zang at freescale.com  Mon Oct 18 03:22:31 2010
From: tie-fei.zang at freescale.com (Roy Zang)
Date: Mon, 18 Oct 2010 15:22:31 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to elbc
	devices
Message-ID: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>

Move Freescale elbc interrupt from nand dirver to elbc driver.
Then all elbc devices can use the interrupt instead of ONLY nand.

For former nand driver, it had the two functions:

1. detecting nand flash partitions;
2. registering elbc interrupt.

Now, second function is removed to fsl_lbc.c.

Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
Cc: Wood Scott-B07421 <B07421 at freescale.com>
---

These two patches are based on the following commits:
1.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032112.html
2.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032110.html
3.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032111.html
According to Anton's comment, I merge 1 & 2 together and start a new thread.
Comparing the provided link:
1.	Merge 1 & 2 together.
2.	Some code style updates
3.	Add counter protect for elbc driver remove 
4.	Rebase to 2.6.36-rc7

Other histories from the links:
V2: Comparing with v1, according to the feedback, add some decorations.

V3: Comparing with v2:
1.	according to the feedback, add some decorations.
2.	change of_platform_driver to platform_driver
3.	rebase to 2.6.36-rc4

V4: Comparing with v3
1.	minor fix from type unsigned int to u32
2.	fix platform_driver issue.
3.	add mutex for nand probe

 arch/powerpc/Kconfig               |    7 +-
 arch/powerpc/include/asm/fsl_lbc.h |   33 +++-
 arch/powerpc/sysdev/fsl_lbc.c      |  229 ++++++++++++++---
 drivers/mtd/nand/Kconfig           |    1 +
 drivers/mtd/nand/fsl_elbc_nand.c   |  482 +++++++++++++++---------------------
 5 files changed, 425 insertions(+), 327 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 631e5a0..44df1ba 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -687,9 +687,12 @@ config 4xx_SOC
 	bool
 
 config FSL_LBC
-	bool
+	bool "Freescale Local Bus support"
+	depends on FSL_SOC
 	help
-	  Freescale Localbus support
+	  Enables reporting of errors from the Freescale local bus
+	  controller.  Also contains some common code used by
+	  drivers for specific local bus peripherals.
 
 config FSL_GTM
 	bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a210..0c40c05 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
 /* Freescale Local Bus Controller
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence at freescale.com>,
  *          Scott Wood <scottwood at freescale.com>
+ *          Jack Lan <jack.lan at freescale.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
@@ -26,6 +27,8 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/io.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
 
 struct fsl_lbc_bank {
 	__be32 br;             /**< Base Register  */
@@ -125,13 +128,23 @@ struct fsl_lbc_regs {
 #define LTESR_ATMW 0x00800000
 #define LTESR_ATMR 0x00400000
 #define LTESR_CS   0x00080000
+#define LTESR_UPM  0x00000002
 #define LTESR_CC   0x00000001
 #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
+#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
+			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
+			 | LTESR_CC)
+#define LTESR_CLEAR	0xFFFFFFFF
+#define LTECCR_CLEAR	0xFFFFFFFF
+#define LTESR_STATUS	LTESR_MASK
+#define LTEIR_ENABLE	LTESR_MASK
+#define LTEDR_ENABLE	0x00000000
 	__be32 ltedr;           /**< Transfer Error Disable Register */
 	__be32 lteir;           /**< Transfer Error Interrupt Register */
 	__be32 lteatr;          /**< Transfer Error Attributes Register */
 	__be32 ltear;           /**< Transfer Error Address Register */
-	u8 res6[0xC];
+	__be32 lteccr;          /**< Transfer Error ECC Register */
+	u8 res6[0x8];
 	__be32 lbcr;            /**< Configuration Register */
 #define LBCR_LDIS  0x80000000
 #define LBCR_LDIS_SHIFT    31
@@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
 		cpu_relax();
 }
 
+/* overview of the fsl lbc controller */
+
+struct fsl_lbc_ctrl {
+	/* device info */
+	struct device			*dev;
+	struct fsl_lbc_regs __iomem	*regs;
+	int				irq;
+	wait_queue_head_t		irq_wait;
+	spinlock_t			lock;
+	void				*nand;
+
+	/* status read from LTESR by irq handler */
+	unsigned int			irq_status;
+};
+
 extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
 			       u32 mar);
+extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 
 #endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1..4bb0336 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -2,8 +2,11 @@
  * Freescale LBC and UPM routines.
  *
  * Copyright (c) 2007-2008  MontaVista Software, Inc.
+ * Copyright (c) 2010 Freescale Semiconductor
  *
  * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
+ * Author: Jack Lan <Jack.Lan at freescale.com>
+ * Author: Roy Zang <tie-fei.zang at freescale.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
@@ -19,39 +22,16 @@
 #include <linux/types.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
 #include <asm/prom.h>
 #include <asm/fsl_lbc.h>
 
 static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
-static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
-
-static char __initdata *compat_lbc[] = {
-	"fsl,pq2-localbus",
-	"fsl,pq2pro-localbus",
-	"fsl,pq3-localbus",
-	"fsl,elbc",
-};
-
-static int __init fsl_lbc_init(void)
-{
-	struct device_node *lbus;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
-		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
-		if (lbus)
-			goto found;
-	}
-	return -ENODEV;
-
-found:
-	fsl_lbc_regs = of_iomap(lbus, 0);
-	of_node_put(lbus);
-	if (!fsl_lbc_regs)
-		return -ENOMEM;
-	return 0;
-}
-arch_initcall(fsl_lbc_init);
+struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
+EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
  * fsl_lbc_find - find Localbus bank
@@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
 int fsl_lbc_find(phys_addr_t addr_base)
 {
 	int i;
+	struct fsl_lbc_regs __iomem *lbc;
 
-	if (!fsl_lbc_regs)
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 
-	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
-		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
-		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
+	lbc = fsl_lbc_ctrl_dev->regs;
+	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
+		__be32 br = in_be32(&lbc->bank[i].br);
+		__be32 or = in_be32(&lbc->bank[i].or);
 
 		if (br & BR_V && (br & or & BR_BA) == addr_base)
 			return i;
@@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
 {
 	int bank;
 	__be32 br;
+	struct fsl_lbc_regs __iomem *lbc;
 
 	bank = fsl_lbc_find(addr_base);
 	if (bank < 0)
 		return bank;
 
-	br = in_be32(&fsl_lbc_regs->bank[bank].br);
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+
+	lbc = fsl_lbc_ctrl_dev->regs;
+	br = in_be32(&lbc->bank[bank].br);
 
 	switch (br & BR_MSEL) {
 	case BR_MS_UPMA:
-		upm->mxmr = &fsl_lbc_regs->mamr;
+		upm->mxmr = &lbc->mamr;
 		break;
 	case BR_MS_UPMB:
-		upm->mxmr = &fsl_lbc_regs->mbmr;
+		upm->mxmr = &lbc->mbmr;
 		break;
 	case BR_MS_UPMC:
-		upm->mxmr = &fsl_lbc_regs->mcmr;
+		upm->mxmr = &lbc->mcmr;
 		break;
 	default:
 		return -EINVAL;
@@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 	int ret = 0;
 	unsigned long flags;
 
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+
 	spin_lock_irqsave(&fsl_lbc_lock, flags);
 
-	out_be32(&fsl_lbc_regs->mar, mar);
+	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
 
 	switch (upm->width) {
 	case 8:
@@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
 	return ret;
 }
 EXPORT_SYMBOL(fsl_upm_run_pattern);
+
+static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
+{
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+
+	/* clear event registers */
+	setbits32(&lbc->ltesr, LTESR_CLEAR);
+	out_be32(&lbc->lteatr, 0);
+	out_be32(&lbc->ltear, 0);
+	out_be32(&lbc->lteccr, LTECCR_CLEAR);
+	out_be32(&lbc->ltedr, LTEDR_ENABLE);
+
+	/* Enable interrupts for any detected events */
+	out_be32(&lbc->lteir, LTEIR_ENABLE);
+
+	return 0;
+}
+
+/*
+ * NOTE: This interrupt is used to report localbus events of various kinds,
+ * such as transaction errors on the chipselects.
+ */
+
+static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
+{
+	struct fsl_lbc_ctrl *ctrl = data;
+	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	u32 status;
+
+	status = in_be32(&lbc->ltesr);
+	if (!status)
+		return IRQ_NONE;
+
+	out_be32(&lbc->ltesr, LTESR_CLEAR);
+	out_be32(&lbc->lteatr, 0);
+	out_be32(&lbc->ltear, 0);
+	ctrl->irq_status = status;
+
+	if (status & LTESR_BM)
+		dev_err(ctrl->dev, "Local bus monitor time-out: "
+			"LTESR 0x%08X\n", status);
+	if (status & LTESR_WP)
+		dev_err(ctrl->dev, "Write protect error: "
+			"LTESR 0x%08X\n", status);
+	if (status & LTESR_ATMW)
+		dev_err(ctrl->dev, "Atomic write error: "
+			"LTESR 0x%08X\n", status);
+	if (status & LTESR_ATMR)
+		dev_err(ctrl->dev, "Atomic read error: "
+			"LTESR 0x%08X\n", status);
+	if (status & LTESR_CS)
+		dev_err(ctrl->dev, "Chip select error: "
+			"LTESR 0x%08X\n", status);
+	if (status & LTESR_UPM)
+		;
+	if (status & LTESR_FCT) {
+		dev_err(ctrl->dev, "FCM command time-out: "
+			"LTESR 0x%08X\n", status);
+		smp_wmb();
+		wake_up(&ctrl->irq_wait);
+	}
+	if (status & LTESR_PAR) {
+		dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
+			"LTESR 0x%08X\n", status);
+		smp_wmb();
+		wake_up(&ctrl->irq_wait);
+	}
+	if (status & LTESR_CC) {
+		smp_wmb();
+		wake_up(&ctrl->irq_wait);
+	}
+	if (status & ~LTESR_MASK)
+		dev_err(ctrl->dev, "Unknown error: "
+			"LTESR 0x%08X\n", status);
+	return IRQ_HANDLED;
+}
+
+/*
+ * fsl_lbc_ctrl_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code allocates all of
+ * the resources needed for the controller only.  The
+ * resources for the NAND banks themselves are allocated
+ * in the chip probe function.
+*/
+
+static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
+{
+	int ret;
+
+	if (!dev->dev.of_node) {
+		dev_err(&dev->dev, "Device OF-Node is NULL");
+		return -EFAULT;
+	}
+
+	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
+	if (!fsl_lbc_ctrl_dev)
+		return -ENOMEM;
+
+	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
+
+	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
+	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
+
+	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
+	if (!fsl_lbc_ctrl_dev->regs) {
+		dev_err(&dev->dev, "failed to get memory region\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
+	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+		dev_err(&dev->dev, "failed to get irq resource\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	fsl_lbc_ctrl_dev->dev = &dev->dev;
+
+	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
+	if (ret < 0)
+		goto err;
+
+	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+				"fsl-lbc", fsl_lbc_ctrl_dev);
+	if (ret != 0) {
+		dev_err(&dev->dev, "failed to install irq (%d)\n",
+			fsl_lbc_ctrl_dev->irq);
+		ret = fsl_lbc_ctrl_dev->irq;
+		goto err;
+	}
+
+	return 0;
+
+err:
+	iounmap(fsl_lbc_ctrl_dev->regs);
+	kfree(fsl_lbc_ctrl_dev);
+	return ret;
+}
+
+static const struct of_device_id fsl_lbc_match[] = {
+	{ .compatible = "fsl,elbc", },
+	{ .compatible = "fsl,pq3-localbus", },
+	{ .compatible = "fsl,pq2-localbus", },
+	{ .compatible = "fsl,pq2pro-localbus", },
+	{},
+};
+
+static struct platform_driver fsl_lbc_ctrl_driver = {
+	.driver = {
+		.name = "fsl-lbc",
+		.of_match_table = fsl_lbc_match,
+	},
+	.probe = fsl_lbc_ctrl_probe,
+};
+
+static int __init fsl_lbc_init(void)
+{
+	return platform_driver_register(&fsl_lbc_ctrl_driver);
+}
+module_init(fsl_lbc_init);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 8b4b67c..4132c46 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -458,6 +458,7 @@ config MTD_NAND_ORION
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
 	depends on PPC_OF
+	select FSL_LBC
 	help
 	  Various Freescale chips, including the 8313, include a NAND Flash
 	  Controller Module with built-in hardware ECC capabilities.
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 80de0bf..400f01f 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -1,9 +1,11 @@
 /* Freescale Enhanced Local Bus Controller NAND driver
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor
+ * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
  *
  * Authors: Nick Spence <nick.spence at freescale.com>,
  *          Scott Wood <scottwood at freescale.com>
+ *          Jack Lan <jack.lan at freescale.com>
+ *          Roy Zang <tie-fei.zang at freescale.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
@@ -27,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/of_platform.h>
+#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 
@@ -42,14 +45,12 @@
 #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
 #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
 
-struct fsl_elbc_ctrl;
-
 /* mtd information per set */
 
 struct fsl_elbc_mtd {
 	struct mtd_info mtd;
 	struct nand_chip chip;
-	struct fsl_elbc_ctrl *ctrl;
+	struct fsl_lbc_ctrl *ctrl;
 
 	struct device *dev;
 	int bank;               /* Chip select bank number           */
@@ -58,18 +59,12 @@ struct fsl_elbc_mtd {
 	unsigned int fmr;       /* FCM Flash Mode Register value     */
 };
 
-/* overview of the fsl elbc controller */
+/* Freescale eLBC FCM controller infomation */
 
-struct fsl_elbc_ctrl {
+struct fsl_elbc_fcm_ctrl {
 	struct nand_hw_control controller;
 	struct fsl_elbc_mtd *chips[MAX_BANKS];
 
-	/* device info */
-	struct device *dev;
-	struct fsl_lbc_regs __iomem *regs;
-	int irq;
-	wait_queue_head_t irq_wait;
-	unsigned int irq_status; /* status read from LTESR by irq handler */
 	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
 	unsigned int page;       /* Last page written to / read from      */
 	unsigned int read_bytes; /* Number of bytes read during command   */
@@ -79,6 +74,7 @@ struct fsl_elbc_ctrl {
 	unsigned int mdr;        /* UPM/FCM Data Register value           */
 	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
 	unsigned int oob;        /* Non zero if operating on OOB data     */
+	unsigned int counter;	 /* counter for the initializations	  */
 	char *oob_poi;           /* Place to write ECC after read back    */
 };
 
@@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	int buf_num;
 
-	ctrl->page = page_addr;
+	elbc_fcm_ctrl->page = page_addr;
 
 	out_be32(&lbc->fbar,
 	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
@@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 		buf_num = page_addr & 7;
 	}
 
-	ctrl->addr = priv->vbase + buf_num * 1024;
-	ctrl->index = column;
+	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
+	elbc_fcm_ctrl->index = column;
 
 	/* for OOB data point to the second half of the buffer */
 	if (oob)
-		ctrl->index += priv->page_size ? 2048 : 512;
+		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
 
-	dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
+	dev_vdbg(priv->dev, "set_addr: bank=%d, "
+			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
 	                    "index %x, pes %d ps %d\n",
-	         buf_num, ctrl->addr, priv->vbase, ctrl->index,
+		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
+		 elbc_fcm_ctrl->index,
 	         chip->phys_erase_shift, chip->page_shift);
 }
 
@@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	/* Setup the FMR[OP] to execute without write protection */
 	out_be32(&lbc->fmr, priv->fmr | 3);
-	if (ctrl->use_mdr)
-		out_be32(&lbc->mdr, ctrl->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
 
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
 	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
-	dev_vdbg(ctrl->dev,
+	dev_vdbg(priv->dev,
 	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
 	         "fbcr=%08x bank=%d\n",
 	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
@@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 	/* wait for FCM complete flag or timeout */
 	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
 	                   FCM_TIMEOUT_MSECS * HZ/1000);
-	ctrl->status = ctrl->irq_status;
-
+	elbc_fcm_ctrl->status = ctrl->irq_status;
 	/* store mdr value in case it was needed */
-	if (ctrl->use_mdr)
-		ctrl->mdr = in_be32(&lbc->mdr);
+	if (elbc_fcm_ctrl->use_mdr)
+		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
-	if (ctrl->status != LTESR_CC) {
-		dev_info(ctrl->dev,
+	if (elbc_fcm_ctrl->status != LTESR_CC) {
+		dev_info(priv->dev,
 		         "command failed: fir %x fcr %x status %x mdr %x\n",
 		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
-		         ctrl->status, ctrl->mdr);
+			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
 		return -EIO;
 	}
 
@@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
 	if (priv->page_size) {
@@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 
-	ctrl->use_mdr = 0;
+	elbc_fcm_ctrl->use_mdr = 0;
 
 	/* clear the read buffer */
-	ctrl->read_bytes = 0;
+	elbc_fcm_ctrl->read_bytes = 0;
 	if (command != NAND_CMD_PAGEPROG)
-		ctrl->index = 0;
+		elbc_fcm_ctrl->index = 0;
 
 	switch (command) {
 	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
@@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* fall-through */
 	case NAND_CMD_READ0:
-		dev_dbg(ctrl->dev,
+		dev_dbg(priv->dev,
 		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
 		        " 0x%x, column: 0x%x.\n", page_addr, column);
 
@@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
 		set_addr(mtd, 0, page_addr, 0);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
-		ctrl->index += column;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->index += column;
 
 		fsl_elbc_do_read(chip, 0);
 		fsl_elbc_run_command(mtd);
@@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READOOB reads only the OOB because no ECC is performed. */
 	case NAND_CMD_READOOB:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
 			 " 0x%x, column: 0x%x.\n", page_addr, column);
 
 		out_be32(&lbc->fbcr, mtd->oobsize - column);
 		set_addr(mtd, column, page_addr, 1);
 
-		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
+		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
 
 		fsl_elbc_do_read(chip, 1);
 		fsl_elbc_run_command(mtd);
@@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* READID must read all 5 possible bytes while CEB is active */
 	case NAND_CMD_READID:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
 
 		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
@@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
 		/* 5 bytes for manuf, device and exts */
 		out_be32(&lbc->fbcr, 5);
-		ctrl->read_bytes = 5;
-		ctrl->use_mdr = 1;
-		ctrl->mdr = 0;
+		elbc_fcm_ctrl->read_bytes = 5;
+		elbc_fcm_ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->mdr = 0;
 
 		set_addr(mtd, 0, 0, 0);
 		fsl_elbc_run_command(mtd);
@@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE1 stores the block and page address */
 	case NAND_CMD_ERASE1:
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
 		         "page_addr: 0x%x.\n", page_addr);
 		set_addr(mtd, 0, page_addr, 0);
@@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 
 	/* ERASE2 uses the block and page address from ERASE1 */
 	case NAND_CMD_ERASE2:
-		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
+		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
 
 		out_be32(&lbc->fir,
 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
 
 		out_be32(&lbc->fbcr, 0);
-		ctrl->read_bytes = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->read_bytes = 0;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fsl_elbc_run_command(mtd);
 		return;
@@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 	/* SEQIN sets up the addr buffer and all registers except the length */
 	case NAND_CMD_SEQIN: {
 		__be32 fcr;
-		dev_vdbg(ctrl->dev,
-		         "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
+		dev_vdbg(priv->dev,
+			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
 		         "page_addr: 0x%x, column: 0x%x.\n",
 		         page_addr, column);
 
-		ctrl->column = column;
-		ctrl->oob = 0;
-		ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->use_mdr = 1;
 
 		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
 		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
@@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 				/* OOB area --> READOOB */
 				column -= mtd->writesize;
 				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
-				ctrl->oob = 1;
+				elbc_fcm_ctrl->oob = 1;
 			} else {
 				WARN_ON(column != 0);
 				/* First 256 bytes --> READ0 */
@@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		}
 
 		out_be32(&lbc->fcr, fcr);
-		set_addr(mtd, column, page_addr, ctrl->oob);
+		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
 		return;
 	}
 
 	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
 	case NAND_CMD_PAGEPROG: {
 		int full_page;
-		dev_vdbg(ctrl->dev,
+		dev_vdbg(priv->dev,
 		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
-		         "writing %d bytes.\n", ctrl->index);
+			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
 
 		/* if the write did not start at 0 or is not a full page
 		 * then set the exact length, otherwise use a full page
 		 * write so the HW generates the ECC.
 		 */
-		if (ctrl->oob || ctrl->column != 0 ||
-		    ctrl->index != mtd->writesize + mtd->oobsize) {
-			out_be32(&lbc->fbcr, ctrl->index);
+		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
+		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
+			out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
 			full_page = 0;
 		} else {
 			out_be32(&lbc->fbcr, 0);
@@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		/* Read back the page in order to fill in the ECC for the
 		 * caller.  Is this really needed?
 		 */
-		if (full_page && ctrl->oob_poi) {
+		if (full_page && elbc_fcm_ctrl->oob_poi) {
 			out_be32(&lbc->fbcr, 3);
 			set_addr(mtd, 6, page_addr, 1);
 
-			ctrl->read_bytes = mtd->writesize + 9;
+			elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
 
 			fsl_elbc_do_read(chip, 1);
 			fsl_elbc_run_command(mtd);
 
-			memcpy_fromio(ctrl->oob_poi + 6,
-			              &ctrl->addr[ctrl->index], 3);
-			ctrl->index += 3;
+			memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
+				&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
+			elbc_fcm_ctrl->index += 3;
 		}
 
-		ctrl->oob_poi = NULL;
+		elbc_fcm_ctrl->oob_poi = NULL;
 		return;
 	}
 
@@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
 		out_be32(&lbc->fbcr, 1);
 		set_addr(mtd, 0, 0, 0);
-		ctrl->read_bytes = 1;
+		elbc_fcm_ctrl->read_bytes = 1;
 
 		fsl_elbc_run_command(mtd);
 
 		/* The chip always seems to report that it is
 		 * write-protected, even when it is not.
 		 */
-		setbits8(ctrl->addr, NAND_STATUS_WP);
+		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
 		return;
 
 	/* RESET without waiting for the ready line */
 	case NAND_CMD_RESET:
-		dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
+		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
 		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
 		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
 		fsl_elbc_run_command(mtd);
 		return;
 
 	default:
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
 		        command);
 	}
@@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
 	if (len <= 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
-		ctrl->status = 0;
+		dev_err(priv->dev, "write_buf of %d bytes", len);
+		elbc_fcm_ctrl->status = 0;
 		return;
 	}
 
-	if ((unsigned int)len > bufsize - ctrl->index) {
-		dev_err(ctrl->dev,
+	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
 		        "write_buf beyond end of buffer "
 		        "(%d requested, %u available)\n",
-		        len, bufsize - ctrl->index);
-		len = bufsize - ctrl->index;
+			len, bufsize - elbc_fcm_ctrl->index);
+		len = bufsize - elbc_fcm_ctrl->index;
 	}
 
-	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
+	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
 	/*
 	 * This is workaround for the weird elbc hangs during nand write,
 	 * Scott Wood says: "...perhaps difference in how long it takes a
@@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 	 * is causing problems, and sync isn't helping for some reason."
 	 * Reading back the last byte helps though.
 	 */
-	in_8(&ctrl->addr[ctrl->index] + len - 1);
+	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
 
-	ctrl->index += len;
+	elbc_fcm_ctrl->index += len;
 }
 
 /*
@@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
 	/* If there are still bytes in the FCM, then use the next byte. */
-	if (ctrl->index < ctrl->read_bytes)
-		return in_8(&ctrl->addr[ctrl->index++]);
+	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
+		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
 
-	dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
+	dev_err(priv->dev, "read_byte beyond end of buffer\n");
 	return ERR_BYTE;
 }
 
@@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int avail;
 
 	if (len < 0)
 		return;
 
-	avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
-	memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
-	ctrl->index += avail;
+	avail = min((unsigned int)len,
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
+	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
+	elbc_fcm_ctrl->index += avail;
 
 	if (len > avail)
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "read_buf beyond end of buffer "
 		        "(%d requested, %d available)\n",
 		        len, avail);
@@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	int i;
 
 	if (len < 0) {
-		dev_err(ctrl->dev, "write_buf of %d bytes", len);
+		dev_err(priv->dev, "write_buf of %d bytes", len);
 		return -EINVAL;
 	}
 
-	if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
-		dev_err(ctrl->dev,
-		        "verify_buf beyond end of buffer "
-		        "(%d requested, %u available)\n",
-		        len, ctrl->read_bytes - ctrl->index);
+	if ((unsigned int)len >
+			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
+		dev_err(priv->dev,
+			"verify_buf beyond end of buffer "
+			"(%d requested, %u available)\n",
+			len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
 
-		ctrl->index = ctrl->read_bytes;
+		elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
 		return -EINVAL;
 	}
 
 	for (i = 0; i < len; i++)
-		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
+		if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
+				!= buf[i])
 			break;
 
-	ctrl->index += len;
-	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
+	elbc_fcm_ctrl->index += len;
+	return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
 }
 
 /* This function is called after Program and Erase Operations to
@@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
-	if (ctrl->status != LTESR_CC)
+	if (elbc_fcm_ctrl->status != LTESR_CC)
 		return NAND_STATUS_FAIL;
 
 	/* The chip always seems to report that it is
 	 * write-protected, even when it is not.
 	 */
-	return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
+	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
 static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	unsigned int al;
 
@@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
 	             (al << FMR_AL_SHIFT);
 
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
 	        chip->numchips);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
 	        chip->chipsize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
 	        chip->pagemask);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
 	        chip->chip_delay);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
 	        chip->badblockpos);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
 	        chip->chip_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
 	        chip->page_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
 	        chip->phys_erase_shift);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
 	        chip->ecclayout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
 	        chip->ecc.mode);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
 	        chip->ecc.steps);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
 	        chip->ecc.bytes);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
 	        chip->ecc.total);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
 	        chip->ecc.layout);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
 	        mtd->erasesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
 	        mtd->writesize);
-	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
+	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
 	        mtd->oobsize);
 
 	/* adjust Option Register and ECC to match Flash page size */
@@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 			chip->badblock_pattern = &largepage_memorybased;
 		}
 	} else {
-		dev_err(ctrl->dev,
+		dev_err(priv->dev,
 		        "fsl_elbc_init: page size %d is not supported\n",
 		        mtd->writesize);
 		return -1;
@@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
                                 const uint8_t *buf)
 {
 	struct fsl_elbc_mtd *priv = chip->priv;
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-	ctrl->oob_poi = chip->oob_poi;
+	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
 }
 
 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct nand_chip *chip = &priv->chip;
 
 	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
@@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
 			NAND_USE_FLASH_BBT;
 
-	chip->controller = &ctrl->controller;
+	chip->controller = &elbc_fcm_ctrl->controller;
 	chip->priv = priv;
 
 	chip->ecc.read_page = fsl_elbc_read_page;
@@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
 
 static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 {
-	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
 	nand_release(&priv->mtd);
 
 	kfree(priv->mtd.name);
@@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 	if (priv->vbase)
 		iounmap(priv->vbase);
 
-	ctrl->chips[priv->bank] = NULL;
+	elbc_fcm_ctrl->chips[priv->bank] = NULL;
 	kfree(priv);
-
+	kfree(elbc_fcm_ctrl);
 	return 0;
 }
 
-static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
-					 struct device_node *node)
+static DEFINE_MUTEX(fsl_elbc_nand_mutex);
+
+static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
+	struct fsl_lbc_regs __iomem *lbc;
 	struct fsl_elbc_mtd *priv;
 	struct resource res;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
+
 #ifdef CONFIG_MTD_PARTITIONS
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", NULL };
@@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 #endif
 	int ret;
 	int bank;
+	struct device *dev;
+	struct device_node *node = pdev->dev.of_node;
+
+	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
+		return -ENODEV;
+	lbc = fsl_lbc_ctrl_dev->regs;
+	dev = fsl_lbc_ctrl_dev->dev;
 
 	/* get, allocate and map the memory resource */
 	ret = of_address_to_resource(node, 0, &res);
 	if (ret) {
-		dev_err(ctrl->dev, "failed to get resource\n");
+		dev_err(dev, "failed to get resource\n");
 		return ret;
 	}
 
@@ -861,7 +872,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 			break;
 
 	if (bank >= MAX_BANKS) {
-		dev_err(ctrl->dev, "address did not match any chip selects\n");
+		dev_err(dev, "address did not match any chip selects\n");
 		return -ENODEV;
 	}
 
@@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 	if (!priv)
 		return -ENOMEM;
 
-	ctrl->chips[bank] = priv;
+	mutex_lock(&fsl_elbc_nand_mutex);
+	if (!fsl_lbc_ctrl_dev->nand) {
+		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
+		if (!elbc_fcm_ctrl) {
+			dev_err(dev, "failed to allocate memory\n");
+			mutex_unlock(&fsl_elbc_nand_mutex);
+			ret = -ENOMEM;
+			goto err;
+		}
+		elbc_fcm_ctrl->counter++;
+
+		spin_lock_init(&elbc_fcm_ctrl->controller.lock);
+		init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
+		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
+	} else {
+		elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
+	}
+	mutex_unlock(&fsl_elbc_nand_mutex);
+
+	elbc_fcm_ctrl->chips[bank] = priv;
 	priv->bank = bank;
-	priv->ctrl = ctrl;
-	priv->dev = ctrl->dev;
+	priv->ctrl = fsl_lbc_ctrl_dev;
+	priv->dev = dev;
 
 	priv->vbase = ioremap(res.start, resource_size(&res));
 	if (!priv->vbase) {
-		dev_err(ctrl->dev, "failed to map chip region\n");
+		dev_err(dev, "failed to map chip region\n");
 		ret = -ENOMEM;
 		goto err;
 	}
@@ -933,171 +963,53 @@ err:
 	return ret;
 }
 
-static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
+static int fsl_elbc_nand_remove(struct platform_device *pdev)
 {
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-
-	/*
-	 * NAND transactions can tie up the bus for a long time, so set the
-	 * bus timeout to max by clearing LBCR[BMT] (highest base counter
-	 * value) and setting LBCR[BMTPS] to the highest prescaler value.
-	 */
-	clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
-
-	/* clear event registers */
-	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
-	out_be32(&lbc->lteatr, 0);
-
-	/* Enable interrupts for any detected events */
-	out_be32(&lbc->lteir, LTESR_NAND_MASK);
-
-	ctrl->read_bytes = 0;
-	ctrl->index = 0;
-	ctrl->addr = NULL;
-
-	return 0;
-}
-
-static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
-{
-	struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
 	int i;
-
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
 	for (i = 0; i < MAX_BANKS; i++)
-		if (ctrl->chips[i])
-			fsl_elbc_chip_remove(ctrl->chips[i]);
-
-	if (ctrl->irq)
-		free_irq(ctrl->irq, ctrl);
-
-	if (ctrl->regs)
-		iounmap(ctrl->regs);
-
-	dev_set_drvdata(&ofdev->dev, NULL);
-	kfree(ctrl);
-	return 0;
-}
-
-/* NOTE: This interrupt is also used to report other localbus events,
- * such as transaction errors on other chipselects.  If we want to
- * capture those, we'll need to move the IRQ code into a shared
- * LBC driver.
- */
-
-static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
-{
-	struct fsl_elbc_ctrl *ctrl = data;
-	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
-	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
-
-	if (status) {
-		out_be32(&lbc->ltesr, status);
-		out_be32(&lbc->lteatr, 0);
-
-		ctrl->irq_status = status;
-		smp_wmb();
-		wake_up(&ctrl->irq_wait);
-
-		return IRQ_HANDLED;
+		if (elbc_fcm_ctrl->chips[i])
+			fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
+
+	mutex_lock(&fsl_elbc_nand_mutex);
+	elbc_fcm_ctrl->counter--;
+	if (!elbc_fcm_ctrl->counter) {
+		fsl_lbc_ctrl_dev->nand = NULL;
+		kfree(elbc_fcm_ctrl);
 	}
-
-	return IRQ_NONE;
-}
-
-/* fsl_elbc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only.  The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-
-static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
-                                         const struct of_device_id *match)
-{
-	struct device_node *child;
-	struct fsl_elbc_ctrl *ctrl;
-	int ret;
-
-	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
-	if (!ctrl)
-		return -ENOMEM;
-
-	dev_set_drvdata(&ofdev->dev, ctrl);
-
-	spin_lock_init(&ctrl->controller.lock);
-	init_waitqueue_head(&ctrl->controller.wq);
-	init_waitqueue_head(&ctrl->irq_wait);
-
-	ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
-	if (!ctrl->regs) {
-		dev_err(&ofdev->dev, "failed to get memory region\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
-	if (ctrl->irq == NO_IRQ) {
-		dev_err(&ofdev->dev, "failed to get irq resource\n");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	ctrl->dev = &ofdev->dev;
-
-	ret = fsl_elbc_ctrl_init(ctrl);
-	if (ret < 0)
-		goto err;
-
-	ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
-	if (ret != 0) {
-		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
-		        ctrl->irq);
-		ret = ctrl->irq;
-		goto err;
-	}
-
-	for_each_child_of_node(ofdev->dev.of_node, child)
-		if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
-			fsl_elbc_chip_probe(ctrl, child);
+	mutex_unlock(&fsl_elbc_nand_mutex);
 
 	return 0;
 
-err:
-	fsl_elbc_ctrl_remove(ofdev);
-	return ret;
 }
 
-static const struct of_device_id fsl_elbc_match[] = {
-	{
-		.compatible = "fsl,elbc",
-	},
+static const struct of_device_id fsl_elbc_nand_match[] = {
+	{ .compatible = "fsl,elbc-fcm-nand", },
 	{}
 };
 
-static struct of_platform_driver fsl_elbc_ctrl_driver = {
+static struct platform_driver fsl_elbc_nand_driver = {
 	.driver = {
-		.name = "fsl-elbc",
+		.name = "fsl,elbc-fcm-nand",
 		.owner = THIS_MODULE,
-		.of_match_table = fsl_elbc_match,
+		.of_match_table = fsl_elbc_nand_match,
 	},
-	.probe = fsl_elbc_ctrl_probe,
-	.remove = fsl_elbc_ctrl_remove,
+	.probe = fsl_elbc_nand_probe,
+	.remove = fsl_elbc_nand_remove,
 };
 
-static int __init fsl_elbc_init(void)
+static int __init fsl_elbc_nand_init(void)
 {
-	return of_register_platform_driver(&fsl_elbc_ctrl_driver);
+	return platform_driver_register(&fsl_elbc_nand_driver);
 }
 
-static void __exit fsl_elbc_exit(void)
+static void __exit fsl_elbc_nand_exit(void)
 {
-	of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
+	platform_driver_unregister(&fsl_elbc_nand_driver);
 }
 
-module_init(fsl_elbc_init);
-module_exit(fsl_elbc_exit);
+module_init(fsl_elbc_nand_init);
+module_exit(fsl_elbc_nand_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Freescale");
-- 
1.5.6.5




From tie-fei.zang at freescale.com  Mon Oct 18 03:22:32 2010
From: tie-fei.zang at freescale.com (Roy Zang)
Date: Mon, 18 Oct 2010 15:22:32 +0800
Subject: [PATCH 2/2] P4080/mtd: Fix the freescale lbc issue with 36bit mode
In-Reply-To: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
Message-ID: <1287386552-10647-2-git-send-email-tie-fei.zang@freescale.com>

From: Lan Chunhe-B25806 <b25806 at freescale.com>

When system uses 36bit physical address, res.start is 36bit
physical address. But the function of in_be32 returns 32bit
physical address. Then both of them compared each other is
wrong. So by converting the address of res.start into
the right format fixes this issue.

Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
---
 arch/powerpc/include/asm/fsl_lbc.h |    1 +
 arch/powerpc/sysdev/fsl_lbc.c      |   23 ++++++++++++++++++++++-
 drivers/mtd/nand/fsl_elbc_nand.c   |    2 +-
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 0c40c05..7639cbd 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -248,6 +248,7 @@ struct fsl_upm {
 	int width;
 };
 
+extern u32 fsl_lbc_addr(phys_addr_t addr_base);
 extern int fsl_lbc_find(phys_addr_t addr_base);
 extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
 
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index 4bb0336..29ba867 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -34,6 +34,27 @@ struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
 /**
+ * fsl_lbc_addr - convert the base address
+ * @addr_base:	base address of the memory bank
+ *
+ * This function converts a base address of lbc into the right format for the
+ * BR register. If the SOC has eLBC then it returns 32bit physical address
+ * else it convers a 34bit local bus physical address to correct format of
+ * 32bit address for BR register (Example: MPC8641).
+ */
+u32 fsl_lbc_addr(phys_addr_t addr_base)
+{
+	struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
+	u32 addr = addr_base & 0xffff8000;
+
+	if (of_device_is_compatible(np, "fsl,elbc"))
+		return addr;
+
+	return addr | ((addr_base & 0x300000000ull) >> 19);
+}
+EXPORT_SYMBOL(fsl_lbc_addr);
+
+/**
  * fsl_lbc_find - find Localbus bank
  * @addr_base:	base address of the memory bank
  *
@@ -55,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base)
 		__be32 br = in_be32(&lbc->bank[i].br);
 		__be32 or = in_be32(&lbc->bank[i].or);
 
-		if (br & BR_V && (br & or & BR_BA) == addr_base)
+		if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
 			return i;
 	}
 
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 400f01f..8785317 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -868,7 +868,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 		    (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
 		    (in_be32(&lbc->bank[bank].br) &
 		     in_be32(&lbc->bank[bank].or) & BR_BA)
-		     == res.start)
+		     == fsl_lbc_addr(res.start))
 			break;
 
 	if (bank >= MAX_BANKS) {
-- 
1.5.6.5




From s.hauer at pengutronix.de  Mon Oct 18 04:16:26 2010
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 18 Oct 2010 10:16:26 +0200
Subject: [PATCH for 2.6.36] mxc_nand: do not depend on disabling the irq in
	the interrupt handler
Message-ID: <20101018081626.GI28242@pengutronix.de>


This patch reverts the driver to enabling/disabling the NFC interrupt
mask rather than enabling/disabling the system interrupt. This cleans
up the driver so that it doesn't rely on interrupts being disabled
within the interrupt handler.
For i.MX21 we keep the current behaviour, that is calling
enable_irq/disable_irq_nosync to enable/disable interrupts.
This patch is based on earlier work by John Ogness.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Acked-by: John Ogness <john.ogness at linutronix.de>
Tested-by: John Ogness <john.ogness at linutronix.de>
Signed-off-by: David Woodhouse <dwmw2 at infradead.org>
---

Hi Linus,

I now it's late but please apply this patch for 2.6.36. It was sent some
times to the lists but got lost. Without it the i.MX NAND driver is
nonfuntional.

Sascha

 drivers/mtd/nand/mxc_nand.c |   92 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 83 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index b2828e8..214b03a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -30,6 +30,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/completion.h>
 
 #include <asm/mach/flash.h>
 #include <mach/mxc_nand.h>
@@ -151,7 +153,7 @@ struct mxc_nand_host {
 	int			irq;
 	int			eccsize;
 
-	wait_queue_head_t	irq_waitq;
+	struct completion	op_completion;
 
 	uint8_t			*data_buf;
 	unsigned int		buf_start;
@@ -164,6 +166,7 @@ struct mxc_nand_host {
 	void			(*send_read_id)(struct mxc_nand_host *);
 	uint16_t		(*get_dev_status)(struct mxc_nand_host *);
 	int			(*check_int)(struct mxc_nand_host *);
+	void			(*irq_control)(struct mxc_nand_host *, int);
 };
 
 /* OOB placement block for use with hardware ecc generation */
@@ -216,9 +219,12 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 {
 	struct mxc_nand_host *host = dev_id;
 
-	disable_irq_nosync(irq);
+	if (!host->check_int(host))
+		return IRQ_NONE;
 
-	wake_up(&host->irq_waitq);
+	host->irq_control(host, 0);
+
+	complete(&host->op_completion);
 
 	return IRQ_HANDLED;
 }
@@ -245,11 +251,54 @@ static int check_int_v1_v2(struct mxc_nand_host *host)
 	if (!(tmp & NFC_V1_V2_CONFIG2_INT))
 		return 0;
 
-	writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
+	if (!cpu_is_mx21())
+		writew(tmp & ~NFC_V1_V2_CONFIG2_INT, NFC_V1_V2_CONFIG2);
 
 	return 1;
 }
 
+/*
+ * It has been observed that the i.MX21 cannot read the CONFIG2:INT bit
+ * if interrupts are masked (CONFIG1:INT_MSK is set). To handle this, the
+ * driver can enable/disable the irq line rather than simply masking the
+ * interrupts.
+ */
+static void irq_control_mx21(struct mxc_nand_host *host, int activate)
+{
+	if (activate)
+		enable_irq(host->irq);
+	else
+		disable_irq_nosync(host->irq);
+}
+
+static void irq_control_v1_v2(struct mxc_nand_host *host, int activate)
+{
+	uint16_t tmp;
+
+	tmp = readw(NFC_V1_V2_CONFIG1);
+
+	if (activate)
+		tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK;
+	else
+		tmp |= NFC_V1_V2_CONFIG1_INT_MSK;
+
+	writew(tmp, NFC_V1_V2_CONFIG1);
+}
+
+static void irq_control_v3(struct mxc_nand_host *host, int activate)
+{
+	uint32_t tmp;
+
+	tmp = readl(NFC_V3_CONFIG2);
+
+	if (activate)
+		tmp &= ~NFC_V3_CONFIG2_INT_MSK;
+	else
+		tmp |= NFC_V3_CONFIG2_INT_MSK;
+
+	writel(tmp, NFC_V3_CONFIG2);
+}
+
 /* This function polls the NANDFC to wait for the basic operation to
  * complete by checking the INT bit of config2 register.
  */
@@ -259,10 +308,9 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq)
 
 	if (useirq) {
 		if (!host->check_int(host)) {
-
-			enable_irq(host->irq);
-
-			wait_event(host->irq_waitq, host->check_int(host));
+			INIT_COMPLETION(host->op_completion);
+			host->irq_control(host, 1);
+			wait_for_completion(&host->op_completion);
 		}
 	} else {
 		while (max_retries-- > 0) {
@@ -799,6 +847,7 @@ static void preset_v3(struct mtd_info *mtd)
 		NFC_V3_CONFIG2_2CMD_PHASES |
 		NFC_V3_CONFIG2_SPAS(mtd->oobsize >> 1) |
 		NFC_V3_CONFIG2_ST_CMD(0x70) |
+		NFC_V3_CONFIG2_INT_MSK |
 		NFC_V3_CONFIG2_NUM_ADDR_PHASE0;
 
 	if (chip->ecc.mode == NAND_ECC_HW)
@@ -1024,6 +1073,10 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		host->send_read_id = send_read_id_v1_v2;
 		host->get_dev_status = get_dev_status_v1_v2;
 		host->check_int = check_int_v1_v2;
+		if (cpu_is_mx21())
+			host->irq_control = irq_control_mx21;
+		else
+			host->irq_control = irq_control_v1_v2;
 	}
 
 	if (nfc_is_v21()) {
@@ -1062,6 +1115,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		host->send_read_id = send_read_id_v3;
 		host->check_int = check_int_v3;
 		host->get_dev_status = get_dev_status_v3;
+		host->irq_control = irq_control_v3;
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 	} else
@@ -1093,14 +1147,34 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 		this->options |= NAND_USE_FLASH_BBT;
 	}
 
-	init_waitqueue_head(&host->irq_waitq);
+	init_completion(&host->op_completion);
 
 	host->irq = platform_get_irq(pdev, 0);
 
+	/*
+	 * mask the interrupt. For i.MX21 explicitely call
+	 * irq_control_v1_v2 to use the mask bit. We can't call
+	 * disable_irq_nosync() for an interrupt we do not own yet.
+	 */
+	if (cpu_is_mx21())
+		irq_control_v1_v2(host, 0);
+	else
+		host->irq_control(host, 0);
+
 	err = request_irq(host->irq, mxc_nfc_irq, IRQF_DISABLED, DRIVER_NAME, host);
 	if (err)
 		goto eirq;
 
+	host->irq_control(host, 0);
+
+	/*
+	 * Now that the interrupt is disabled make sure the interrupt
+	 * mask bit is cleared on i.MX21. Otherwise we can't read
+	 * the interrupt status bit on this machine.
+	 */
+	if (cpu_is_mx21())
+		irq_control_v1_v2(host, 1);
+
 	/* first scan to find the device and get the page size */
 	if (nand_scan_ident(mtd, 1, NULL)) {
 		err = -ENXIO;
-- 
1.7.2.3

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


From tiejun.chen at windriver.com  Mon Oct 18 04:55:49 2010
From: tiejun.chen at windriver.com (tiejun.chen)
Date: Mon, 18 Oct 2010 16:55:49 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common
	to elbc	devices
In-Reply-To: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
Message-ID: <4CBC0B95.9010300@windriver.com>

Roy Zang wrote:
> Move Freescale elbc interrupt from nand dirver to elbc driver.
> Then all elbc devices can use the interrupt instead of ONLY nand.
> 
> For former nand driver, it had the two functions:
> 
> 1. detecting nand flash partitions;
> 2. registering elbc interrupt.
> 
> Now, second function is removed to fsl_lbc.c.
> 
> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
> Cc: Wood Scott-B07421 <B07421 at freescale.com>
> ---
> 
> These two patches are based on the following commits:
> 1.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032112.html
> 2.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032110.html
> 3.	http://lists.infradead.org/pipermail/linux-mtd/2010-September/032111.html
> According to Anton's comment, I merge 1 & 2 together and start a new thread.
> Comparing the provided link:
> 1.	Merge 1 & 2 together.
> 2.	Some code style updates
> 3.	Add counter protect for elbc driver remove 
> 4.	Rebase to 2.6.36-rc7
> 
> Other histories from the links:
> V2: Comparing with v1, according to the feedback, add some decorations.
> 
> V3: Comparing with v2:
> 1.	according to the feedback, add some decorations.
> 2.	change of_platform_driver to platform_driver
> 3.	rebase to 2.6.36-rc4
> 
> V4: Comparing with v3
> 1.	minor fix from type unsigned int to u32
> 2.	fix platform_driver issue.
> 3.	add mutex for nand probe
> 
>  arch/powerpc/Kconfig               |    7 +-
>  arch/powerpc/include/asm/fsl_lbc.h |   33 +++-
>  arch/powerpc/sysdev/fsl_lbc.c      |  229 ++++++++++++++---
>  drivers/mtd/nand/Kconfig           |    1 +
>  drivers/mtd/nand/fsl_elbc_nand.c   |  482 +++++++++++++++---------------------
>  5 files changed, 425 insertions(+), 327 deletions(-)
> 
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 631e5a0..44df1ba 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -687,9 +687,12 @@ config 4xx_SOC
>  	bool
>  
>  config FSL_LBC
> -	bool
> +	bool "Freescale Local Bus support"
> +	depends on FSL_SOC
>  	help
> -	  Freescale Localbus support
> +	  Enables reporting of errors from the Freescale local bus
> +	  controller.  Also contains some common code used by
> +	  drivers for specific local bus peripherals.
>  
>  config FSL_GTM
>  	bool
> diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
> index 1b5a210..0c40c05 100644
> --- a/arch/powerpc/include/asm/fsl_lbc.h
> +++ b/arch/powerpc/include/asm/fsl_lbc.h
> @@ -1,9 +1,10 @@
>  /* Freescale Local Bus Controller
>   *
> - * Copyright (c) 2006-2007 Freescale Semiconductor
> + * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
>   *
>   * Authors: Nick Spence <nick.spence at freescale.com>,
>   *          Scott Wood <scottwood at freescale.com>
> + *          Jack Lan <jack.lan at freescale.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
> @@ -26,6 +27,8 @@
>  #include <linux/compiler.h>
>  #include <linux/types.h>
>  #include <linux/io.h>
> +#include <linux/device.h>
> +#include <linux/spinlock.h>
>  
>  struct fsl_lbc_bank {
>  	__be32 br;             /**< Base Register  */
> @@ -125,13 +128,23 @@ struct fsl_lbc_regs {
>  #define LTESR_ATMW 0x00800000
>  #define LTESR_ATMR 0x00400000
>  #define LTESR_CS   0x00080000
> +#define LTESR_UPM  0x00000002
>  #define LTESR_CC   0x00000001
>  #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> +#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
> +			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
> +			 | LTESR_CC)
> +#define LTESR_CLEAR	0xFFFFFFFF
> +#define LTECCR_CLEAR	0xFFFFFFFF
> +#define LTESR_STATUS	LTESR_MASK
> +#define LTEIR_ENABLE	LTESR_MASK
> +#define LTEDR_ENABLE	0x00000000
>  	__be32 ltedr;           /**< Transfer Error Disable Register */
>  	__be32 lteir;           /**< Transfer Error Interrupt Register */
>  	__be32 lteatr;          /**< Transfer Error Attributes Register */
>  	__be32 ltear;           /**< Transfer Error Address Register */
> -	u8 res6[0xC];
> +	__be32 lteccr;          /**< Transfer Error ECC Register */
> +	u8 res6[0x8];
>  	__be32 lbcr;            /**< Configuration Register */
>  #define LBCR_LDIS  0x80000000
>  #define LBCR_LDIS_SHIFT    31
> @@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
>  		cpu_relax();
>  }
>  
> +/* overview of the fsl lbc controller */
> +
> +struct fsl_lbc_ctrl {
> +	/* device info */
> +	struct device			*dev;
> +	struct fsl_lbc_regs __iomem	*regs;
> +	int				irq;
> +	wait_queue_head_t		irq_wait;
> +	spinlock_t			lock;
> +	void				*nand;
> +
> +	/* status read from LTESR by irq handler */
> +	unsigned int			irq_status;
> +};
> +
>  extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
>  			       u32 mar);
> +extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
>  
>  #endif /* __ASM_FSL_LBC_H */
> diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
> index dceb8d1..4bb0336 100644
> --- a/arch/powerpc/sysdev/fsl_lbc.c
> +++ b/arch/powerpc/sysdev/fsl_lbc.c
> @@ -2,8 +2,11 @@
>   * Freescale LBC and UPM routines.
>   *
>   * Copyright (c) 2007-2008  MontaVista Software, Inc.
> + * Copyright (c) 2010 Freescale Semiconductor
>   *
>   * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> + * Author: Jack Lan <Jack.Lan at freescale.com>
> + * Author: Roy Zang <tie-fei.zang at freescale.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
> @@ -19,39 +22,16 @@
>  #include <linux/types.h>
>  #include <linux/io.h>
>  #include <linux/of.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/mod_devicetable.h>
>  #include <asm/prom.h>
>  #include <asm/fsl_lbc.h>
>  
>  static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
> -static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
> -
> -static char __initdata *compat_lbc[] = {
> -	"fsl,pq2-localbus",
> -	"fsl,pq2pro-localbus",
> -	"fsl,pq3-localbus",
> -	"fsl,elbc",
> -};
> -
> -static int __init fsl_lbc_init(void)
> -{
> -	struct device_node *lbus;
> -	int i;
> -
> -	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
> -		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
> -		if (lbus)
> -			goto found;
> -	}
> -	return -ENODEV;
> -
> -found:
> -	fsl_lbc_regs = of_iomap(lbus, 0);
> -	of_node_put(lbus);
> -	if (!fsl_lbc_regs)
> -		return -ENOMEM;
> -	return 0;
> -}
> -arch_initcall(fsl_lbc_init);
> +struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
> +EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
>  
>  /**
>   * fsl_lbc_find - find Localbus bank
> @@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
>  int fsl_lbc_find(phys_addr_t addr_base)
>  {
>  	int i;
> +	struct fsl_lbc_regs __iomem *lbc;
>  
> -	if (!fsl_lbc_regs)
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>  		return -ENODEV;
>  
> -	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
> -		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
> -		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
> +	lbc = fsl_lbc_ctrl_dev->regs;
> +	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
> +		__be32 br = in_be32(&lbc->bank[i].br);
> +		__be32 or = in_be32(&lbc->bank[i].or);
>  
>  		if (br & BR_V && (br & or & BR_BA) == addr_base)
>  			return i;
> @@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
>  {
>  	int bank;
>  	__be32 br;
> +	struct fsl_lbc_regs __iomem *lbc;
>  
>  	bank = fsl_lbc_find(addr_base);
>  	if (bank < 0)
>  		return bank;
>  
> -	br = in_be32(&fsl_lbc_regs->bank[bank].br);
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;
> +
> +	lbc = fsl_lbc_ctrl_dev->regs;
> +	br = in_be32(&lbc->bank[bank].br);
>  
>  	switch (br & BR_MSEL) {
>  	case BR_MS_UPMA:
> -		upm->mxmr = &fsl_lbc_regs->mamr;
> +		upm->mxmr = &lbc->mamr;
>  		break;
>  	case BR_MS_UPMB:
> -		upm->mxmr = &fsl_lbc_regs->mbmr;
> +		upm->mxmr = &lbc->mbmr;
>  		break;
>  	case BR_MS_UPMC:
> -		upm->mxmr = &fsl_lbc_regs->mcmr;
> +		upm->mxmr = &lbc->mcmr;
>  		break;
>  	default:
>  		return -EINVAL;
> @@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
>  	int ret = 0;
>  	unsigned long flags;
>  
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;
> +
>  	spin_lock_irqsave(&fsl_lbc_lock, flags);
>  
> -	out_be32(&fsl_lbc_regs->mar, mar);
> +	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
>  
>  	switch (upm->width) {
>  	case 8:
> @@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
>  	return ret;
>  }
>  EXPORT_SYMBOL(fsl_upm_run_pattern);
> +
> +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
> +{
> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +
> +	/* clear event registers */
> +	setbits32(&lbc->ltesr, LTESR_CLEAR);
> +	out_be32(&lbc->lteatr, 0);
> +	out_be32(&lbc->ltear, 0);
> +	out_be32(&lbc->lteccr, LTECCR_CLEAR);
> +	out_be32(&lbc->ltedr, LTEDR_ENABLE);
> +
> +	/* Enable interrupts for any detected events */
> +	out_be32(&lbc->lteir, LTEIR_ENABLE);
> +
> +	return 0;
> +}
> +
> +/*
> + * NOTE: This interrupt is used to report localbus events of various kinds,
> + * such as transaction errors on the chipselects.
> + */
> +
> +static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
> +{
> +	struct fsl_lbc_ctrl *ctrl = data;
> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	u32 status;
> +
> +	status = in_be32(&lbc->ltesr);
> +	if (!status)
> +		return IRQ_NONE;
> +
> +	out_be32(&lbc->ltesr, LTESR_CLEAR);
> +	out_be32(&lbc->lteatr, 0);
> +	out_be32(&lbc->ltear, 0);
> +	ctrl->irq_status = status;
> +
> +	if (status & LTESR_BM)
> +		dev_err(ctrl->dev, "Local bus monitor time-out: "
> +			"LTESR 0x%08X\n", status);
> +	if (status & LTESR_WP)
> +		dev_err(ctrl->dev, "Write protect error: "
> +			"LTESR 0x%08X\n", status);
> +	if (status & LTESR_ATMW)
> +		dev_err(ctrl->dev, "Atomic write error: "
> +			"LTESR 0x%08X\n", status);
> +	if (status & LTESR_ATMR)
> +		dev_err(ctrl->dev, "Atomic read error: "
> +			"LTESR 0x%08X\n", status);
> +	if (status & LTESR_CS)
> +		dev_err(ctrl->dev, "Chip select error: "
> +			"LTESR 0x%08X\n", status);
> +	if (status & LTESR_UPM)
> +		;
> +	if (status & LTESR_FCT) {
> +		dev_err(ctrl->dev, "FCM command time-out: "
> +			"LTESR 0x%08X\n", status);
> +		smp_wmb();
> +		wake_up(&ctrl->irq_wait);
> +	}
> +	if (status & LTESR_PAR) {
> +		dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
> +			"LTESR 0x%08X\n", status);
> +		smp_wmb();
> +		wake_up(&ctrl->irq_wait);
> +	}
> +	if (status & LTESR_CC) {
> +		smp_wmb();
> +		wake_up(&ctrl->irq_wait);
> +	}
> +	if (status & ~LTESR_MASK)
> +		dev_err(ctrl->dev, "Unknown error: "
> +			"LTESR 0x%08X\n", status);
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * fsl_lbc_ctrl_probe
> + *
> + * called by device layer when it finds a device matching
> + * one our driver can handled. This code allocates all of
> + * the resources needed for the controller only.  The
> + * resources for the NAND banks themselves are allocated
> + * in the chip probe function.
> +*/
> +
> +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
> +{
> +	int ret;
> +
> +	if (!dev->dev.of_node) {
> +		dev_err(&dev->dev, "Device OF-Node is NULL");
> +		return -EFAULT;
> +	}
> +
> +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
> +	if (!fsl_lbc_ctrl_dev)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
> +
> +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
> +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
> +
> +	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
> +	if (!fsl_lbc_ctrl_dev->regs) {
> +		dev_err(&dev->dev, "failed to get memory region\n");
> +		ret = -ENODEV;
> +		goto err;

Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
again. So you should improve that as the following on 'err', or layout 'err' in
gain.
------
	if(fsl_lbc_ctrl_dev->regs)
		iounmap(fsl_lbc_ctrl_dev->regs);

Tiejun

> +	}
> +
> +	fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
> +	if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
> +		dev_err(&dev->dev, "failed to get irq resource\n");
> +		ret = -ENODEV;
> +		goto err;
> +	}
> +
> +	fsl_lbc_ctrl_dev->dev = &dev->dev;
> +
> +	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
> +	if (ret < 0)
> +		goto err;
> +
> +	ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
> +				"fsl-lbc", fsl_lbc_ctrl_dev);
> +	if (ret != 0) {
> +		dev_err(&dev->dev, "failed to install irq (%d)\n",
> +			fsl_lbc_ctrl_dev->irq);
> +		ret = fsl_lbc_ctrl_dev->irq;
> +		goto err;
> +	}
> +
> +	return 0;
> +
> +err:
> +	iounmap(fsl_lbc_ctrl_dev->regs);
> +	kfree(fsl_lbc_ctrl_dev);
> +	return ret;
> +}
> +
> +static const struct of_device_id fsl_lbc_match[] = {
> +	{ .compatible = "fsl,elbc", },
> +	{ .compatible = "fsl,pq3-localbus", },
> +	{ .compatible = "fsl,pq2-localbus", },
> +	{ .compatible = "fsl,pq2pro-localbus", },
> +	{},
> +};
> +
> +static struct platform_driver fsl_lbc_ctrl_driver = {
> +	.driver = {
> +		.name = "fsl-lbc",
> +		.of_match_table = fsl_lbc_match,
> +	},
> +	.probe = fsl_lbc_ctrl_probe,
> +};
> +
> +static int __init fsl_lbc_init(void)
> +{
> +	return platform_driver_register(&fsl_lbc_ctrl_driver);
> +}
> +module_init(fsl_lbc_init);
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 8b4b67c..4132c46 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -458,6 +458,7 @@ config MTD_NAND_ORION
>  config MTD_NAND_FSL_ELBC
>  	tristate "NAND support for Freescale eLBC controllers"
>  	depends on PPC_OF
> +	select FSL_LBC
>  	help
>  	  Various Freescale chips, including the 8313, include a NAND Flash
>  	  Controller Module with built-in hardware ECC capabilities.
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> index 80de0bf..400f01f 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -1,9 +1,11 @@
>  /* Freescale Enhanced Local Bus Controller NAND driver
>   *
> - * Copyright (c) 2006-2007 Freescale Semiconductor
> + * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
>   *
>   * Authors: Nick Spence <nick.spence at freescale.com>,
>   *          Scott Wood <scottwood at freescale.com>
> + *          Jack Lan <jack.lan at freescale.com>
> + *          Roy Zang <tie-fei.zang at freescale.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
> @@ -27,6 +29,7 @@
>  #include <linux/string.h>
>  #include <linux/ioport.h>
>  #include <linux/of_platform.h>
> +#include <linux/platform_device.h>
>  #include <linux/slab.h>
>  #include <linux/interrupt.h>
>  
> @@ -42,14 +45,12 @@
>  #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
>  #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
>  
> -struct fsl_elbc_ctrl;
> -
>  /* mtd information per set */
>  
>  struct fsl_elbc_mtd {
>  	struct mtd_info mtd;
>  	struct nand_chip chip;
> -	struct fsl_elbc_ctrl *ctrl;
> +	struct fsl_lbc_ctrl *ctrl;
>  
>  	struct device *dev;
>  	int bank;               /* Chip select bank number           */
> @@ -58,18 +59,12 @@ struct fsl_elbc_mtd {
>  	unsigned int fmr;       /* FCM Flash Mode Register value     */
>  };
>  
> -/* overview of the fsl elbc controller */
> +/* Freescale eLBC FCM controller infomation */
>  
> -struct fsl_elbc_ctrl {
> +struct fsl_elbc_fcm_ctrl {
>  	struct nand_hw_control controller;
>  	struct fsl_elbc_mtd *chips[MAX_BANKS];
>  
> -	/* device info */
> -	struct device *dev;
> -	struct fsl_lbc_regs __iomem *regs;
> -	int irq;
> -	wait_queue_head_t irq_wait;
> -	unsigned int irq_status; /* status read from LTESR by irq handler */
>  	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
>  	unsigned int page;       /* Last page written to / read from      */
>  	unsigned int read_bytes; /* Number of bytes read during command   */
> @@ -79,6 +74,7 @@ struct fsl_elbc_ctrl {
>  	unsigned int mdr;        /* UPM/FCM Data Register value           */
>  	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
>  	unsigned int oob;        /* Non zero if operating on OOB data     */
> +	unsigned int counter;	 /* counter for the initializations	  */
>  	char *oob_poi;           /* Place to write ECC after read back    */
>  };
>  
> @@ -164,11 +160,12 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
>  	int buf_num;
>  
> -	ctrl->page = page_addr;
> +	elbc_fcm_ctrl->page = page_addr;
>  
>  	out_be32(&lbc->fbar,
>  	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
> @@ -185,16 +182,18 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
>  		buf_num = page_addr & 7;
>  	}
>  
> -	ctrl->addr = priv->vbase + buf_num * 1024;
> -	ctrl->index = column;
> +	elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
> +	elbc_fcm_ctrl->index = column;
>  
>  	/* for OOB data point to the second half of the buffer */
>  	if (oob)
> -		ctrl->index += priv->page_size ? 2048 : 512;
> +		elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
>  
> -	dev_vdbg(ctrl->dev, "set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
> +	dev_vdbg(priv->dev, "set_addr: bank=%d, "
> +			    "elbc_fcm_ctrl->addr=0x%p (0x%p), "
>  	                    "index %x, pes %d ps %d\n",
> -	         buf_num, ctrl->addr, priv->vbase, ctrl->index,
> +		 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
> +		 elbc_fcm_ctrl->index,
>  	         chip->phys_erase_shift, chip->page_shift);
>  }
>  
> @@ -205,18 +204,19 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>  
>  	/* Setup the FMR[OP] to execute without write protection */
>  	out_be32(&lbc->fmr, priv->fmr | 3);
> -	if (ctrl->use_mdr)
> -		out_be32(&lbc->mdr, ctrl->mdr);
> +	if (elbc_fcm_ctrl->use_mdr)
> +		out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
>  
> -	dev_vdbg(ctrl->dev,
> +	dev_vdbg(priv->dev,
>  	         "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
>  	         in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
> -	dev_vdbg(ctrl->dev,
> +	dev_vdbg(priv->dev,
>  	         "fsl_elbc_run_command: fbar=%08x fpar=%08x "
>  	         "fbcr=%08x bank=%d\n",
>  	         in_be32(&lbc->fbar), in_be32(&lbc->fpar),
> @@ -229,19 +229,18 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
>  	/* wait for FCM complete flag or timeout */
>  	wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
>  	                   FCM_TIMEOUT_MSECS * HZ/1000);
> -	ctrl->status = ctrl->irq_status;
> -
> +	elbc_fcm_ctrl->status = ctrl->irq_status;
>  	/* store mdr value in case it was needed */
> -	if (ctrl->use_mdr)
> -		ctrl->mdr = in_be32(&lbc->mdr);
> +	if (elbc_fcm_ctrl->use_mdr)
> +		elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
>  
> -	ctrl->use_mdr = 0;
> +	elbc_fcm_ctrl->use_mdr = 0;
>  
> -	if (ctrl->status != LTESR_CC) {
> -		dev_info(ctrl->dev,
> +	if (elbc_fcm_ctrl->status != LTESR_CC) {
> +		dev_info(priv->dev,
>  		         "command failed: fir %x fcr %x status %x mdr %x\n",
>  		         in_be32(&lbc->fir), in_be32(&lbc->fcr),
> -		         ctrl->status, ctrl->mdr);
> +			 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
>  		return -EIO;
>  	}
>  
> @@ -251,7 +250,7 @@ static int fsl_elbc_run_command(struct mtd_info *mtd)
>  static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
>  {
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>  
>  	if (priv->page_size) {
> @@ -284,15 +283,16 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>  
> -	ctrl->use_mdr = 0;
> +	elbc_fcm_ctrl->use_mdr = 0;
>  
>  	/* clear the read buffer */
> -	ctrl->read_bytes = 0;
> +	elbc_fcm_ctrl->read_bytes = 0;
>  	if (command != NAND_CMD_PAGEPROG)
> -		ctrl->index = 0;
> +		elbc_fcm_ctrl->index = 0;
>  
>  	switch (command) {
>  	/* READ0 and READ1 read the entire buffer to use hardware ECC. */
> @@ -301,7 +301,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  
>  	/* fall-through */
>  	case NAND_CMD_READ0:
> -		dev_dbg(ctrl->dev,
> +		dev_dbg(priv->dev,
>  		        "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
>  		        " 0x%x, column: 0x%x.\n", page_addr, column);
>  
> @@ -309,8 +309,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
>  		set_addr(mtd, 0, page_addr, 0);
>  
> -		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
> -		ctrl->index += column;
> +		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
> +		elbc_fcm_ctrl->index += column;
>  
>  		fsl_elbc_do_read(chip, 0);
>  		fsl_elbc_run_command(mtd);
> @@ -318,14 +318,14 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  
>  	/* READOOB reads only the OOB because no ECC is performed. */
>  	case NAND_CMD_READOOB:
> -		dev_vdbg(ctrl->dev,
> +		dev_vdbg(priv->dev,
>  		         "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
>  			 " 0x%x, column: 0x%x.\n", page_addr, column);
>  
>  		out_be32(&lbc->fbcr, mtd->oobsize - column);
>  		set_addr(mtd, column, page_addr, 1);
>  
> -		ctrl->read_bytes = mtd->writesize + mtd->oobsize;
> +		elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
>  
>  		fsl_elbc_do_read(chip, 1);
>  		fsl_elbc_run_command(mtd);
> @@ -333,7 +333,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  
>  	/* READID must read all 5 possible bytes while CEB is active */
>  	case NAND_CMD_READID:
> -		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
> +		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_READID.\n");
>  
>  		out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
>  		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
> @@ -341,9 +341,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
>  		/* 5 bytes for manuf, device and exts */
>  		out_be32(&lbc->fbcr, 5);
> -		ctrl->read_bytes = 5;
> -		ctrl->use_mdr = 1;
> -		ctrl->mdr = 0;
> +		elbc_fcm_ctrl->read_bytes = 5;
> +		elbc_fcm_ctrl->use_mdr = 1;
> +		elbc_fcm_ctrl->mdr = 0;
>  
>  		set_addr(mtd, 0, 0, 0);
>  		fsl_elbc_run_command(mtd);
> @@ -351,7 +351,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  
>  	/* ERASE1 stores the block and page address */
>  	case NAND_CMD_ERASE1:
> -		dev_vdbg(ctrl->dev,
> +		dev_vdbg(priv->dev,
>  		         "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
>  		         "page_addr: 0x%x.\n", page_addr);
>  		set_addr(mtd, 0, page_addr, 0);
> @@ -359,7 +359,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  
>  	/* ERASE2 uses the block and page address from ERASE1 */
>  	case NAND_CMD_ERASE2:
> -		dev_vdbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
> +		dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
>  
>  		out_be32(&lbc->fir,
>  		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
> @@ -374,8 +374,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		         (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
>  
>  		out_be32(&lbc->fbcr, 0);
> -		ctrl->read_bytes = 0;
> -		ctrl->use_mdr = 1;
> +		elbc_fcm_ctrl->read_bytes = 0;
> +		elbc_fcm_ctrl->use_mdr = 1;
>  
>  		fsl_elbc_run_command(mtd);
>  		return;
> @@ -383,14 +383,12 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  	/* SEQIN sets up the addr buffer and all registers except the length */
>  	case NAND_CMD_SEQIN: {
>  		__be32 fcr;
> -		dev_vdbg(ctrl->dev,
> -		         "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
> +		dev_vdbg(priv->dev,
> +			 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
>  		         "page_addr: 0x%x, column: 0x%x.\n",
>  		         page_addr, column);
>  
> -		ctrl->column = column;
> -		ctrl->oob = 0;
> -		ctrl->use_mdr = 1;
> +		elbc_fcm_ctrl->use_mdr = 1;
>  
>  		fcr = (NAND_CMD_STATUS   << FCR_CMD1_SHIFT) |
>  		      (NAND_CMD_SEQIN    << FCR_CMD2_SHIFT) |
> @@ -420,7 +418,7 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  				/* OOB area --> READOOB */
>  				column -= mtd->writesize;
>  				fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
> -				ctrl->oob = 1;
> +				elbc_fcm_ctrl->oob = 1;
>  			} else {
>  				WARN_ON(column != 0);
>  				/* First 256 bytes --> READ0 */
> @@ -429,24 +427,24 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		}
>  
>  		out_be32(&lbc->fcr, fcr);
> -		set_addr(mtd, column, page_addr, ctrl->oob);
> +		set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
>  		return;
>  	}
>  
>  	/* PAGEPROG reuses all of the setup from SEQIN and adds the length */
>  	case NAND_CMD_PAGEPROG: {
>  		int full_page;
> -		dev_vdbg(ctrl->dev,
> +		dev_vdbg(priv->dev,
>  		         "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
> -		         "writing %d bytes.\n", ctrl->index);
> +			 "writing %d bytes.\n", elbc_fcm_ctrl->index);
>  
>  		/* if the write did not start at 0 or is not a full page
>  		 * then set the exact length, otherwise use a full page
>  		 * write so the HW generates the ECC.
>  		 */
> -		if (ctrl->oob || ctrl->column != 0 ||
> -		    ctrl->index != mtd->writesize + mtd->oobsize) {
> -			out_be32(&lbc->fbcr, ctrl->index);
> +		if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
> +		    elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) {
> +			out_be32(&lbc->fbcr, elbc_fcm_ctrl->index);
>  			full_page = 0;
>  		} else {
>  			out_be32(&lbc->fbcr, 0);
> @@ -458,21 +456,21 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		/* Read back the page in order to fill in the ECC for the
>  		 * caller.  Is this really needed?
>  		 */
> -		if (full_page && ctrl->oob_poi) {
> +		if (full_page && elbc_fcm_ctrl->oob_poi) {
>  			out_be32(&lbc->fbcr, 3);
>  			set_addr(mtd, 6, page_addr, 1);
>  
> -			ctrl->read_bytes = mtd->writesize + 9;
> +			elbc_fcm_ctrl->read_bytes = mtd->writesize + 9;
>  
>  			fsl_elbc_do_read(chip, 1);
>  			fsl_elbc_run_command(mtd);
>  
> -			memcpy_fromio(ctrl->oob_poi + 6,
> -			              &ctrl->addr[ctrl->index], 3);
> -			ctrl->index += 3;
> +			memcpy_fromio(elbc_fcm_ctrl->oob_poi + 6,
> +				&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], 3);
> +			elbc_fcm_ctrl->index += 3;
>  		}
>  
> -		ctrl->oob_poi = NULL;
> +		elbc_fcm_ctrl->oob_poi = NULL;
>  		return;
>  	}
>  
> @@ -485,26 +483,26 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
>  		out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
>  		out_be32(&lbc->fbcr, 1);
>  		set_addr(mtd, 0, 0, 0);
> -		ctrl->read_bytes = 1;
> +		elbc_fcm_ctrl->read_bytes = 1;
>  
>  		fsl_elbc_run_command(mtd);
>  
>  		/* The chip always seems to report that it is
>  		 * write-protected, even when it is not.
>  		 */
> -		setbits8(ctrl->addr, NAND_STATUS_WP);
> +		setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
>  		return;
>  
>  	/* RESET without waiting for the ready line */
>  	case NAND_CMD_RESET:
> -		dev_dbg(ctrl->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
> +		dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
>  		out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
>  		out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
>  		fsl_elbc_run_command(mtd);
>  		return;
>  
>  	default:
> -		dev_err(ctrl->dev,
> +		dev_err(priv->dev,
>  		        "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
>  		        command);
>  	}
> @@ -524,24 +522,24 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	unsigned int bufsize = mtd->writesize + mtd->oobsize;
>  
>  	if (len <= 0) {
> -		dev_err(ctrl->dev, "write_buf of %d bytes", len);
> -		ctrl->status = 0;
> +		dev_err(priv->dev, "write_buf of %d bytes", len);
> +		elbc_fcm_ctrl->status = 0;
>  		return;
>  	}
>  
> -	if ((unsigned int)len > bufsize - ctrl->index) {
> -		dev_err(ctrl->dev,
> +	if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
> +		dev_err(priv->dev,
>  		        "write_buf beyond end of buffer "
>  		        "(%d requested, %u available)\n",
> -		        len, bufsize - ctrl->index);
> -		len = bufsize - ctrl->index;
> +			len, bufsize - elbc_fcm_ctrl->index);
> +		len = bufsize - elbc_fcm_ctrl->index;
>  	}
>  
> -	memcpy_toio(&ctrl->addr[ctrl->index], buf, len);
> +	memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
>  	/*
>  	 * This is workaround for the weird elbc hangs during nand write,
>  	 * Scott Wood says: "...perhaps difference in how long it takes a
> @@ -549,9 +547,9 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
>  	 * is causing problems, and sync isn't helping for some reason."
>  	 * Reading back the last byte helps though.
>  	 */
> -	in_8(&ctrl->addr[ctrl->index] + len - 1);
> +	in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
>  
> -	ctrl->index += len;
> +	elbc_fcm_ctrl->index += len;
>  }
>  
>  /*
> @@ -562,13 +560,13 @@ static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  
>  	/* If there are still bytes in the FCM, then use the next byte. */
> -	if (ctrl->index < ctrl->read_bytes)
> -		return in_8(&ctrl->addr[ctrl->index++]);
> +	if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
> +		return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
>  
> -	dev_err(ctrl->dev, "read_byte beyond end of buffer\n");
> +	dev_err(priv->dev, "read_byte beyond end of buffer\n");
>  	return ERR_BYTE;
>  }
>  
> @@ -579,18 +577,19 @@ static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	int avail;
>  
>  	if (len < 0)
>  		return;
>  
> -	avail = min((unsigned int)len, ctrl->read_bytes - ctrl->index);
> -	memcpy_fromio(buf, &ctrl->addr[ctrl->index], avail);
> -	ctrl->index += avail;
> +	avail = min((unsigned int)len,
> +			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
> +	memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
> +	elbc_fcm_ctrl->index += avail;
>  
>  	if (len > avail)
> -		dev_err(ctrl->dev,
> +		dev_err(priv->dev,
>  		        "read_buf beyond end of buffer "
>  		        "(%d requested, %d available)\n",
>  		        len, avail);
> @@ -603,30 +602,32 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	int i;
>  
>  	if (len < 0) {
> -		dev_err(ctrl->dev, "write_buf of %d bytes", len);
> +		dev_err(priv->dev, "write_buf of %d bytes", len);
>  		return -EINVAL;
>  	}
>  
> -	if ((unsigned int)len > ctrl->read_bytes - ctrl->index) {
> -		dev_err(ctrl->dev,
> -		        "verify_buf beyond end of buffer "
> -		        "(%d requested, %u available)\n",
> -		        len, ctrl->read_bytes - ctrl->index);
> +	if ((unsigned int)len >
> +			elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index) {
> +		dev_err(priv->dev,
> +			"verify_buf beyond end of buffer "
> +			"(%d requested, %u available)\n",
> +			len, elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
>  
> -		ctrl->index = ctrl->read_bytes;
> +		elbc_fcm_ctrl->index = elbc_fcm_ctrl->read_bytes;
>  		return -EINVAL;
>  	}
>  
>  	for (i = 0; i < len; i++)
> -		if (in_8(&ctrl->addr[ctrl->index + i]) != buf[i])
> +		if (in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index + i])
> +				!= buf[i])
>  			break;
>  
> -	ctrl->index += len;
> -	return i == len && ctrl->status == LTESR_CC ? 0 : -EIO;
> +	elbc_fcm_ctrl->index += len;
> +	return i == len && elbc_fcm_ctrl->status == LTESR_CC ? 0 : -EIO;
>  }
>  
>  /* This function is called after Program and Erase Operations to
> @@ -635,22 +636,22 @@ static int fsl_elbc_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
>  static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  {
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  
> -	if (ctrl->status != LTESR_CC)
> +	if (elbc_fcm_ctrl->status != LTESR_CC)
>  		return NAND_STATUS_FAIL;
>  
>  	/* The chip always seems to report that it is
>  	 * write-protected, even when it is not.
>  	 */
> -	return (ctrl->mdr & 0xff) | NAND_STATUS_WP;
> +	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
>  }
>  
>  static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd->priv;
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>  	unsigned int al;
>  
> @@ -665,41 +666,41 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
>  	priv->fmr |= (12 << FMR_CWTO_SHIFT) |  /* Timeout > 12 ms */
>  	             (al << FMR_AL_SHIFT);
>  
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
>  	        chip->numchips);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
>  	        chip->chipsize);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
>  	        chip->pagemask);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n",
>  	        chip->chip_delay);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
>  	        chip->badblockpos);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
>  	        chip->chip_shift);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->page_shift = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
>  	        chip->page_shift);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
>  	        chip->phys_erase_shift);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n",
>  	        chip->ecclayout);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
>  	        chip->ecc.mode);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
>  	        chip->ecc.steps);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
>  	        chip->ecc.bytes);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
>  	        chip->ecc.total);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
>  	        chip->ecc.layout);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
> +	dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
> +	dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
>  	        mtd->erasesize);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
>  	        mtd->writesize);
> -	dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
> +	dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
>  	        mtd->oobsize);
>  
>  	/* adjust Option Register and ECC to match Flash page size */
> @@ -719,7 +720,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
>  			chip->badblock_pattern = &largepage_memorybased;
>  		}
>  	} else {
> -		dev_err(ctrl->dev,
> +		dev_err(priv->dev,
>  		        "fsl_elbc_init: page size %d is not supported\n",
>  		        mtd->writesize);
>  		return -1;
> @@ -750,18 +751,19 @@ static void fsl_elbc_write_page(struct mtd_info *mtd,
>                                  const uint8_t *buf)
>  {
>  	struct fsl_elbc_mtd *priv = chip->priv;
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  
>  	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
>  	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
>  
> -	ctrl->oob_poi = chip->oob_poi;
> +	elbc_fcm_ctrl->oob_poi = chip->oob_poi;
>  }
>  
>  static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  {
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> +	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
>  	struct nand_chip *chip = &priv->chip;
>  
>  	dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
> @@ -790,7 +792,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  	chip->options = NAND_NO_READRDY | NAND_NO_AUTOINCR |
>  			NAND_USE_FLASH_BBT;
>  
> -	chip->controller = &ctrl->controller;
> +	chip->controller = &elbc_fcm_ctrl->controller;
>  	chip->priv = priv;
>  
>  	chip->ecc.read_page = fsl_elbc_read_page;
> @@ -815,8 +817,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
>  
>  static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
>  {
> -	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
> -
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
>  	nand_release(&priv->mtd);
>  
>  	kfree(priv->mtd.name);
> @@ -824,18 +825,21 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
>  	if (priv->vbase)
>  		iounmap(priv->vbase);
>  
> -	ctrl->chips[priv->bank] = NULL;
> +	elbc_fcm_ctrl->chips[priv->bank] = NULL;
>  	kfree(priv);
> -
> +	kfree(elbc_fcm_ctrl);
>  	return 0;
>  }
>  
> -static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
> -					 struct device_node *node)
> +static DEFINE_MUTEX(fsl_elbc_nand_mutex);
> +
> +static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
>  {
> -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> +	struct fsl_lbc_regs __iomem *lbc;
>  	struct fsl_elbc_mtd *priv;
>  	struct resource res;
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
> +
>  #ifdef CONFIG_MTD_PARTITIONS
>  	static const char *part_probe_types[]
>  		= { "cmdlinepart", "RedBoot", NULL };
> @@ -843,11 +847,18 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  #endif
>  	int ret;
>  	int bank;
> +	struct device *dev;
> +	struct device_node *node = pdev->dev.of_node;
> +
> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> +		return -ENODEV;
> +	lbc = fsl_lbc_ctrl_dev->regs;
> +	dev = fsl_lbc_ctrl_dev->dev;
>  
>  	/* get, allocate and map the memory resource */
>  	ret = of_address_to_resource(node, 0, &res);
>  	if (ret) {
> -		dev_err(ctrl->dev, "failed to get resource\n");
> +		dev_err(dev, "failed to get resource\n");
>  		return ret;
>  	}
>  
> @@ -861,7 +872,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  			break;
>  
>  	if (bank >= MAX_BANKS) {
> -		dev_err(ctrl->dev, "address did not match any chip selects\n");
> +		dev_err(dev, "address did not match any chip selects\n");
>  		return -ENODEV;
>  	}
>  
> @@ -869,14 +880,33 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
>  	if (!priv)
>  		return -ENOMEM;
>  
> -	ctrl->chips[bank] = priv;
> +	mutex_lock(&fsl_elbc_nand_mutex);
> +	if (!fsl_lbc_ctrl_dev->nand) {
> +		elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
> +		if (!elbc_fcm_ctrl) {
> +			dev_err(dev, "failed to allocate memory\n");
> +			mutex_unlock(&fsl_elbc_nand_mutex);
> +			ret = -ENOMEM;
> +			goto err;
> +		}
> +		elbc_fcm_ctrl->counter++;
> +
> +		spin_lock_init(&elbc_fcm_ctrl->controller.lock);
> +		init_waitqueue_head(&elbc_fcm_ctrl->controller.wq);
> +		fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
> +	} else {
> +		elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
> +	}
> +	mutex_unlock(&fsl_elbc_nand_mutex);
> +
> +	elbc_fcm_ctrl->chips[bank] = priv;
>  	priv->bank = bank;
> -	priv->ctrl = ctrl;
> -	priv->dev = ctrl->dev;
> +	priv->ctrl = fsl_lbc_ctrl_dev;
> +	priv->dev = dev;
>  
>  	priv->vbase = ioremap(res.start, resource_size(&res));
>  	if (!priv->vbase) {
> -		dev_err(ctrl->dev, "failed to map chip region\n");
> +		dev_err(dev, "failed to map chip region\n");
>  		ret = -ENOMEM;
>  		goto err;
>  	}
> @@ -933,171 +963,53 @@ err:
>  	return ret;
>  }
>  
> -static int __devinit fsl_elbc_ctrl_init(struct fsl_elbc_ctrl *ctrl)
> +static int fsl_elbc_nand_remove(struct platform_device *pdev)
>  {
> -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> -
> -	/*
> -	 * NAND transactions can tie up the bus for a long time, so set the
> -	 * bus timeout to max by clearing LBCR[BMT] (highest base counter
> -	 * value) and setting LBCR[BMTPS] to the highest prescaler value.
> -	 */
> -	clrsetbits_be32(&lbc->lbcr, LBCR_BMT, 15);
> -
> -	/* clear event registers */
> -	setbits32(&lbc->ltesr, LTESR_NAND_MASK);
> -	out_be32(&lbc->lteatr, 0);
> -
> -	/* Enable interrupts for any detected events */
> -	out_be32(&lbc->lteir, LTESR_NAND_MASK);
> -
> -	ctrl->read_bytes = 0;
> -	ctrl->index = 0;
> -	ctrl->addr = NULL;
> -
> -	return 0;
> -}
> -
> -static int fsl_elbc_ctrl_remove(struct platform_device *ofdev)
> -{
> -	struct fsl_elbc_ctrl *ctrl = dev_get_drvdata(&ofdev->dev);
>  	int i;
> -
> +	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
>  	for (i = 0; i < MAX_BANKS; i++)
> -		if (ctrl->chips[i])
> -			fsl_elbc_chip_remove(ctrl->chips[i]);
> -
> -	if (ctrl->irq)
> -		free_irq(ctrl->irq, ctrl);
> -
> -	if (ctrl->regs)
> -		iounmap(ctrl->regs);
> -
> -	dev_set_drvdata(&ofdev->dev, NULL);
> -	kfree(ctrl);
> -	return 0;
> -}
> -
> -/* NOTE: This interrupt is also used to report other localbus events,
> - * such as transaction errors on other chipselects.  If we want to
> - * capture those, we'll need to move the IRQ code into a shared
> - * LBC driver.
> - */
> -
> -static irqreturn_t fsl_elbc_ctrl_irq(int irqno, void *data)
> -{
> -	struct fsl_elbc_ctrl *ctrl = data;
> -	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> -	__be32 status = in_be32(&lbc->ltesr) & LTESR_NAND_MASK;
> -
> -	if (status) {
> -		out_be32(&lbc->ltesr, status);
> -		out_be32(&lbc->lteatr, 0);
> -
> -		ctrl->irq_status = status;
> -		smp_wmb();
> -		wake_up(&ctrl->irq_wait);
> -
> -		return IRQ_HANDLED;
> +		if (elbc_fcm_ctrl->chips[i])
> +			fsl_elbc_chip_remove(elbc_fcm_ctrl->chips[i]);
> +
> +	mutex_lock(&fsl_elbc_nand_mutex);
> +	elbc_fcm_ctrl->counter--;
> +	if (!elbc_fcm_ctrl->counter) {
> +		fsl_lbc_ctrl_dev->nand = NULL;
> +		kfree(elbc_fcm_ctrl);
>  	}
> -
> -	return IRQ_NONE;
> -}
> -
> -/* fsl_elbc_ctrl_probe
> - *
> - * called by device layer when it finds a device matching
> - * one our driver can handled. This code allocates all of
> - * the resources needed for the controller only.  The
> - * resources for the NAND banks themselves are allocated
> - * in the chip probe function.
> -*/
> -
> -static int __devinit fsl_elbc_ctrl_probe(struct platform_device *ofdev,
> -                                         const struct of_device_id *match)
> -{
> -	struct device_node *child;
> -	struct fsl_elbc_ctrl *ctrl;
> -	int ret;
> -
> -	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
> -	if (!ctrl)
> -		return -ENOMEM;
> -
> -	dev_set_drvdata(&ofdev->dev, ctrl);
> -
> -	spin_lock_init(&ctrl->controller.lock);
> -	init_waitqueue_head(&ctrl->controller.wq);
> -	init_waitqueue_head(&ctrl->irq_wait);
> -
> -	ctrl->regs = of_iomap(ofdev->dev.of_node, 0);
> -	if (!ctrl->regs) {
> -		dev_err(&ofdev->dev, "failed to get memory region\n");
> -		ret = -ENODEV;
> -		goto err;
> -	}
> -
> -	ctrl->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL);
> -	if (ctrl->irq == NO_IRQ) {
> -		dev_err(&ofdev->dev, "failed to get irq resource\n");
> -		ret = -ENODEV;
> -		goto err;
> -	}
> -
> -	ctrl->dev = &ofdev->dev;
> -
> -	ret = fsl_elbc_ctrl_init(ctrl);
> -	if (ret < 0)
> -		goto err;
> -
> -	ret = request_irq(ctrl->irq, fsl_elbc_ctrl_irq, 0, "fsl-elbc", ctrl);
> -	if (ret != 0) {
> -		dev_err(&ofdev->dev, "failed to install irq (%d)\n",
> -		        ctrl->irq);
> -		ret = ctrl->irq;
> -		goto err;
> -	}
> -
> -	for_each_child_of_node(ofdev->dev.of_node, child)
> -		if (of_device_is_compatible(child, "fsl,elbc-fcm-nand"))
> -			fsl_elbc_chip_probe(ctrl, child);
> +	mutex_unlock(&fsl_elbc_nand_mutex);
>  
>  	return 0;
>  
> -err:
> -	fsl_elbc_ctrl_remove(ofdev);
> -	return ret;
>  }
>  
> -static const struct of_device_id fsl_elbc_match[] = {
> -	{
> -		.compatible = "fsl,elbc",
> -	},
> +static const struct of_device_id fsl_elbc_nand_match[] = {
> +	{ .compatible = "fsl,elbc-fcm-nand", },
>  	{}
>  };
>  
> -static struct of_platform_driver fsl_elbc_ctrl_driver = {
> +static struct platform_driver fsl_elbc_nand_driver = {
>  	.driver = {
> -		.name = "fsl-elbc",
> +		.name = "fsl,elbc-fcm-nand",
>  		.owner = THIS_MODULE,
> -		.of_match_table = fsl_elbc_match,
> +		.of_match_table = fsl_elbc_nand_match,
>  	},
> -	.probe = fsl_elbc_ctrl_probe,
> -	.remove = fsl_elbc_ctrl_remove,
> +	.probe = fsl_elbc_nand_probe,
> +	.remove = fsl_elbc_nand_remove,
>  };
>  
> -static int __init fsl_elbc_init(void)
> +static int __init fsl_elbc_nand_init(void)
>  {
> -	return of_register_platform_driver(&fsl_elbc_ctrl_driver);
> +	return platform_driver_register(&fsl_elbc_nand_driver);
>  }
>  
> -static void __exit fsl_elbc_exit(void)
> +static void __exit fsl_elbc_nand_exit(void)
>  {
> -	of_unregister_platform_driver(&fsl_elbc_ctrl_driver);
> +	platform_driver_unregister(&fsl_elbc_nand_driver);
>  }
>  
> -module_init(fsl_elbc_init);
> -module_exit(fsl_elbc_exit);
> +module_init(fsl_elbc_nand_init);
> +module_exit(fsl_elbc_nand_exit);
>  
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Freescale");



From r61911 at freescale.com  Mon Oct 18 05:30:41 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Mon, 18 Oct 2010 17:30:41 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc	devices
In-Reply-To: <4CBC0B95.9010300@windriver.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<4CBC0B95.9010300@windriver.com>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B0708@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: tiejun.chen [mailto:tiejun.chen at windriver.com]
> Sent: Monday, October 18, 2010 16:56 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421; dedekind1 at gmail.com; Lan
> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
> dwmw2 at infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
> elbc devices
> 
> Roy Zang wrote:
> > Move Freescale elbc interrupt from nand dirver to elbc driver.
> > Then all elbc devices can use the interrupt instead of ONLY nand.
> >
> > For former nand driver, it had the two functions:
> >
> > 1. detecting nand flash partitions;
> > 2. registering elbc interrupt.
> >
> > Now, second function is removed to fsl_lbc.c.
> >
> > Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
> > Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
> > Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
> > Cc: Wood Scott-B07421 <B07421 at freescale.com>
> > ---
> >
> > These two patches are based on the following commits:
> > 1.	http://lists.infradead.org/pipermail/linux-mtd/2010-
> September/032112.html
> > 2.	http://lists.infradead.org/pipermail/linux-mtd/2010-
> September/032110.html
> > 3.	http://lists.infradead.org/pipermail/linux-mtd/2010-
> September/032111.html
> > According to Anton's comment, I merge 1 & 2 together and start a new thread.
> > Comparing the provided link:
> > 1.	Merge 1 & 2 together.
> > 2.	Some code style updates
> > 3.	Add counter protect for elbc driver remove
> > 4.	Rebase to 2.6.36-rc7
> >
> > Other histories from the links:
> > V2: Comparing with v1, according to the feedback, add some decorations.
> >
> > V3: Comparing with v2:
> > 1.	according to the feedback, add some decorations.
> > 2.	change of_platform_driver to platform_driver
> > 3.	rebase to 2.6.36-rc4
> >
> > V4: Comparing with v3
> > 1.	minor fix from type unsigned int to u32
> > 2.	fix platform_driver issue.
> > 3.	add mutex for nand probe
> >
> >  arch/powerpc/Kconfig               |    7 +-
> >  arch/powerpc/include/asm/fsl_lbc.h |   33 +++-
> >  arch/powerpc/sysdev/fsl_lbc.c      |  229 ++++++++++++++---
> >  drivers/mtd/nand/Kconfig           |    1 +
> >  drivers/mtd/nand/fsl_elbc_nand.c   |  482 +++++++++++++++------------------
> ---
> >  5 files changed, 425 insertions(+), 327 deletions(-)
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index 631e5a0..44df1ba 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -687,9 +687,12 @@ config 4xx_SOC
> >  	bool
> >
> >  config FSL_LBC
> > -	bool
> > +	bool "Freescale Local Bus support"
> > +	depends on FSL_SOC
> >  	help
> > -	  Freescale Localbus support
> > +	  Enables reporting of errors from the Freescale local bus
> > +	  controller.  Also contains some common code used by
> > +	  drivers for specific local bus peripherals.
> >
> >  config FSL_GTM
> >  	bool
> > diff --git a/arch/powerpc/include/asm/fsl_lbc.h
> b/arch/powerpc/include/asm/fsl_lbc.h
> > index 1b5a210..0c40c05 100644
> > --- a/arch/powerpc/include/asm/fsl_lbc.h
> > +++ b/arch/powerpc/include/asm/fsl_lbc.h
> > @@ -1,9 +1,10 @@
> >  /* Freescale Local Bus Controller
> >   *
> > - * Copyright (c) 2006-2007 Freescale Semiconductor
> > + * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
> >   *
> >   * Authors: Nick Spence <nick.spence at freescale.com>,
> >   *          Scott Wood <scottwood at freescale.com>
> > + *          Jack Lan <jack.lan at freescale.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
> > @@ -26,6 +27,8 @@
> >  #include <linux/compiler.h>
> >  #include <linux/types.h>
> >  #include <linux/io.h>
> > +#include <linux/device.h>
> > +#include <linux/spinlock.h>
> >
> >  struct fsl_lbc_bank {
> >  	__be32 br;             /**< Base Register  */
> > @@ -125,13 +128,23 @@ struct fsl_lbc_regs {
> >  #define LTESR_ATMW 0x00800000
> >  #define LTESR_ATMR 0x00400000
> >  #define LTESR_CS   0x00080000
> > +#define LTESR_UPM  0x00000002
> >  #define LTESR_CC   0x00000001
> >  #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
> > +#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
> > +			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
> > +			 | LTESR_CC)
> > +#define LTESR_CLEAR	0xFFFFFFFF
> > +#define LTECCR_CLEAR	0xFFFFFFFF
> > +#define LTESR_STATUS	LTESR_MASK
> > +#define LTEIR_ENABLE	LTESR_MASK
> > +#define LTEDR_ENABLE	0x00000000
> >  	__be32 ltedr;           /**< Transfer Error Disable Register */
> >  	__be32 lteir;           /**< Transfer Error Interrupt Register */
> >  	__be32 lteatr;          /**< Transfer Error Attributes Register */
> >  	__be32 ltear;           /**< Transfer Error Address Register */
> > -	u8 res6[0xC];
> > +	__be32 lteccr;          /**< Transfer Error ECC Register */
> > +	u8 res6[0x8];
> >  	__be32 lbcr;            /**< Configuration Register */
> >  #define LBCR_LDIS  0x80000000
> >  #define LBCR_LDIS_SHIFT    31
> > @@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm
> *upm)
> >  		cpu_relax();
> >  }
> >
> > +/* overview of the fsl lbc controller */
> > +
> > +struct fsl_lbc_ctrl {
> > +	/* device info */
> > +	struct device			*dev;
> > +	struct fsl_lbc_regs __iomem	*regs;
> > +	int				irq;
> > +	wait_queue_head_t		irq_wait;
> > +	spinlock_t			lock;
> > +	void				*nand;
> > +
> > +	/* status read from LTESR by irq handler */
> > +	unsigned int			irq_status;
> > +};
> > +
> >  extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
> >  			       u32 mar);
> > +extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
> >
> >  #endif /* __ASM_FSL_LBC_H */
> > diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
> > index dceb8d1..4bb0336 100644
> > --- a/arch/powerpc/sysdev/fsl_lbc.c
> > +++ b/arch/powerpc/sysdev/fsl_lbc.c
> > @@ -2,8 +2,11 @@
> >   * Freescale LBC and UPM routines.
> >   *
> >   * Copyright (c) 2007-2008  MontaVista Software, Inc.
> > + * Copyright (c) 2010 Freescale Semiconductor
> >   *
> >   * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
> > + * Author: Jack Lan <Jack.Lan at freescale.com>
> > + * Author: Roy Zang <tie-fei.zang at freescale.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
> > @@ -19,39 +22,16 @@
> >  #include <linux/types.h>
> >  #include <linux/io.h>
> >  #include <linux/of.h>
> > +#include <linux/slab.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/mod_devicetable.h>
> >  #include <asm/prom.h>
> >  #include <asm/fsl_lbc.h>
> >
> >  static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
> > -static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
> > -
> > -static char __initdata *compat_lbc[] = {
> > -	"fsl,pq2-localbus",
> > -	"fsl,pq2pro-localbus",
> > -	"fsl,pq3-localbus",
> > -	"fsl,elbc",
> > -};
> > -
> > -static int __init fsl_lbc_init(void)
> > -{
> > -	struct device_node *lbus;
> > -	int i;
> > -
> > -	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
> > -		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
> > -		if (lbus)
> > -			goto found;
> > -	}
> > -	return -ENODEV;
> > -
> > -found:
> > -	fsl_lbc_regs = of_iomap(lbus, 0);
> > -	of_node_put(lbus);
> > -	if (!fsl_lbc_regs)
> > -		return -ENOMEM;
> > -	return 0;
> > -}
> > -arch_initcall(fsl_lbc_init);
> > +struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
> > +EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
> >
> >  /**
> >   * fsl_lbc_find - find Localbus bank
> > @@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
> >  int fsl_lbc_find(phys_addr_t addr_base)
> >  {
> >  	int i;
> > +	struct fsl_lbc_regs __iomem *lbc;
> >
> > -	if (!fsl_lbc_regs)
> > +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> >  		return -ENODEV;
> >
> > -	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
> > -		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
> > -		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
> > +	lbc = fsl_lbc_ctrl_dev->regs;
> > +	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
> > +		__be32 br = in_be32(&lbc->bank[i].br);
> > +		__be32 or = in_be32(&lbc->bank[i].or);
> >
> >  		if (br & BR_V && (br & or & BR_BA) == addr_base)
> >  			return i;
> > @@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm
> *upm)
> >  {
> >  	int bank;
> >  	__be32 br;
> > +	struct fsl_lbc_regs __iomem *lbc;
> >
> >  	bank = fsl_lbc_find(addr_base);
> >  	if (bank < 0)
> >  		return bank;
> >
> > -	br = in_be32(&fsl_lbc_regs->bank[bank].br);
> > +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> > +		return -ENODEV;
> > +
> > +	lbc = fsl_lbc_ctrl_dev->regs;
> > +	br = in_be32(&lbc->bank[bank].br);
> >
> >  	switch (br & BR_MSEL) {
> >  	case BR_MS_UPMA:
> > -		upm->mxmr = &fsl_lbc_regs->mamr;
> > +		upm->mxmr = &lbc->mamr;
> >  		break;
> >  	case BR_MS_UPMB:
> > -		upm->mxmr = &fsl_lbc_regs->mbmr;
> > +		upm->mxmr = &lbc->mbmr;
> >  		break;
> >  	case BR_MS_UPMC:
> > -		upm->mxmr = &fsl_lbc_regs->mcmr;
> > +		upm->mxmr = &lbc->mcmr;
> >  		break;
> >  	default:
> >  		return -EINVAL;
> > @@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
> __iomem *io_base, u32 mar)
> >  	int ret = 0;
> >  	unsigned long flags;
> >
> > +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
> > +		return -ENODEV;
> > +
> >  	spin_lock_irqsave(&fsl_lbc_lock, flags);
> >
> > -	out_be32(&fsl_lbc_regs->mar, mar);
> > +	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
> >
> >  	switch (upm->width) {
> >  	case 8:
> > @@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
> __iomem *io_base, u32 mar)
> >  	return ret;
> >  }
> >  EXPORT_SYMBOL(fsl_upm_run_pattern);
> > +
> > +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
> > +{
> > +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > +
> > +	/* clear event registers */
> > +	setbits32(&lbc->ltesr, LTESR_CLEAR);
> > +	out_be32(&lbc->lteatr, 0);
> > +	out_be32(&lbc->ltear, 0);
> > +	out_be32(&lbc->lteccr, LTECCR_CLEAR);
> > +	out_be32(&lbc->ltedr, LTEDR_ENABLE);
> > +
> > +	/* Enable interrupts for any detected events */
> > +	out_be32(&lbc->lteir, LTEIR_ENABLE);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * NOTE: This interrupt is used to report localbus events of various kinds,
> > + * such as transaction errors on the chipselects.
> > + */
> > +
> > +static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
> > +{
> > +	struct fsl_lbc_ctrl *ctrl = data;
> > +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> > +	u32 status;
> > +
> > +	status = in_be32(&lbc->ltesr);
> > +	if (!status)
> > +		return IRQ_NONE;
> > +
> > +	out_be32(&lbc->ltesr, LTESR_CLEAR);
> > +	out_be32(&lbc->lteatr, 0);
> > +	out_be32(&lbc->ltear, 0);
> > +	ctrl->irq_status = status;
> > +
> > +	if (status & LTESR_BM)
> > +		dev_err(ctrl->dev, "Local bus monitor time-out: "
> > +			"LTESR 0x%08X\n", status);
> > +	if (status & LTESR_WP)
> > +		dev_err(ctrl->dev, "Write protect error: "
> > +			"LTESR 0x%08X\n", status);
> > +	if (status & LTESR_ATMW)
> > +		dev_err(ctrl->dev, "Atomic write error: "
> > +			"LTESR 0x%08X\n", status);
> > +	if (status & LTESR_ATMR)
> > +		dev_err(ctrl->dev, "Atomic read error: "
> > +			"LTESR 0x%08X\n", status);
> > +	if (status & LTESR_CS)
> > +		dev_err(ctrl->dev, "Chip select error: "
> > +			"LTESR 0x%08X\n", status);
> > +	if (status & LTESR_UPM)
> > +		;
> > +	if (status & LTESR_FCT) {
> > +		dev_err(ctrl->dev, "FCM command time-out: "
> > +			"LTESR 0x%08X\n", status);
> > +		smp_wmb();
> > +		wake_up(&ctrl->irq_wait);
> > +	}
> > +	if (status & LTESR_PAR) {
> > +		dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
> > +			"LTESR 0x%08X\n", status);
> > +		smp_wmb();
> > +		wake_up(&ctrl->irq_wait);
> > +	}
> > +	if (status & LTESR_CC) {
> > +		smp_wmb();
> > +		wake_up(&ctrl->irq_wait);
> > +	}
> > +	if (status & ~LTESR_MASK)
> > +		dev_err(ctrl->dev, "Unknown error: "
> > +			"LTESR 0x%08X\n", status);
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +/*
> > + * fsl_lbc_ctrl_probe
> > + *
> > + * called by device layer when it finds a device matching
> > + * one our driver can handled. This code allocates all of
> > + * the resources needed for the controller only.  The
> > + * resources for the NAND banks themselves are allocated
> > + * in the chip probe function.
> > +*/
> > +
> > +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
> > +{
> > +	int ret;
> > +
> > +	if (!dev->dev.of_node) {
> > +		dev_err(&dev->dev, "Device OF-Node is NULL");
> > +		return -EFAULT;
> > +	}
> > +
> > +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
> > +	if (!fsl_lbc_ctrl_dev)
> > +		return -ENOMEM;
> > +
> > +	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
> > +
> > +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
> > +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
> > +
> > +	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
> > +	if (!fsl_lbc_ctrl_dev->regs) {
> > +		dev_err(&dev->dev, "failed to get memory region\n");
> > +		ret = -ENODEV;
> > +		goto err;
> 
> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
> again. So you should improve that as the following on 'err', or layout 'err'
> in
> gain.
> ------
> 	if(fsl_lbc_ctrl_dev->regs)
> 		iounmap(fsl_lbc_ctrl_dev->regs);
> 
> Tiejun

You are right!
How about
 
        if (!fsl_lbc_ctrl_dev->regs) {
                dev_err(&dev->dev, "failed to get memory region\n");
                kfree(fsl_lbc_ctrl_dev);
                return -ENOMEM;
        }

...

Thanks.
Roy

From tiejun.chen at windriver.com  Mon Oct 18 05:44:29 2010
From: tiejun.chen at windriver.com (tiejun.chen)
Date: Mon, 18 Oct 2010 17:44:29 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common
	to	elbc	devices
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A2B0708@zch01exm23.fsl.freescale.net>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>	<4CBC0B95.9010300@windriver.com>
	<3850A844E6A3854C827AC5C0BEC7B60A2B0708@zch01exm23.fsl.freescale.net>
Message-ID: <4CBC16FD.6030507@windriver.com>

Zang Roy-R61911 wrote:
> 
>> -----Original Message-----
>> From: tiejun.chen [mailto:tiejun.chen at windriver.com]
>> Sent: Monday, October 18, 2010 16:56 PM
>> To: Zang Roy-R61911
>> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421; dedekind1 at gmail.com; Lan
>> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
>> dwmw2 at infradead.org; Gala Kumar-B11780
>> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
>> elbc devices
>>
>> Roy Zang wrote:
>>> Move Freescale elbc interrupt from nand dirver to elbc driver.
>>> Then all elbc devices can use the interrupt instead of ONLY nand.
>>>
>>> For former nand driver, it had the two functions:
>>>
>>> 1. detecting nand flash partitions;
>>> 2. registering elbc interrupt.
>>>
>>> Now, second function is removed to fsl_lbc.c.
>>>
>>> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
>>> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
>>> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
>>> Cc: Wood Scott-B07421 <B07421 at freescale.com>
>>> ---
>>>
>>> These two patches are based on the following commits:
>>> 1.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>> September/032112.html
>>> 2.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>> September/032110.html
>>> 3.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>> September/032111.html
>>> According to Anton's comment, I merge 1 & 2 together and start a new thread.
>>> Comparing the provided link:
>>> 1.	Merge 1 & 2 together.
>>> 2.	Some code style updates
>>> 3.	Add counter protect for elbc driver remove
>>> 4.	Rebase to 2.6.36-rc7
>>>
>>> Other histories from the links:
>>> V2: Comparing with v1, according to the feedback, add some decorations.
>>>
>>> V3: Comparing with v2:
>>> 1.	according to the feedback, add some decorations.
>>> 2.	change of_platform_driver to platform_driver
>>> 3.	rebase to 2.6.36-rc4
>>>
>>> V4: Comparing with v3
>>> 1.	minor fix from type unsigned int to u32
>>> 2.	fix platform_driver issue.
>>> 3.	add mutex for nand probe
>>>
>>>  arch/powerpc/Kconfig               |    7 +-
>>>  arch/powerpc/include/asm/fsl_lbc.h |   33 +++-
>>>  arch/powerpc/sysdev/fsl_lbc.c      |  229 ++++++++++++++---
>>>  drivers/mtd/nand/Kconfig           |    1 +
>>>  drivers/mtd/nand/fsl_elbc_nand.c   |  482 +++++++++++++++------------------
>> ---
>>>  5 files changed, 425 insertions(+), 327 deletions(-)
>>>
>>> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>>> index 631e5a0..44df1ba 100644
>>> --- a/arch/powerpc/Kconfig
>>> +++ b/arch/powerpc/Kconfig
>>> @@ -687,9 +687,12 @@ config 4xx_SOC
>>>  	bool
>>>
>>>  config FSL_LBC
>>> -	bool
>>> +	bool "Freescale Local Bus support"
>>> +	depends on FSL_SOC
>>>  	help
>>> -	  Freescale Localbus support
>>> +	  Enables reporting of errors from the Freescale local bus
>>> +	  controller.  Also contains some common code used by
>>> +	  drivers for specific local bus peripherals.
>>>
>>>  config FSL_GTM
>>>  	bool
>>> diff --git a/arch/powerpc/include/asm/fsl_lbc.h
>> b/arch/powerpc/include/asm/fsl_lbc.h
>>> index 1b5a210..0c40c05 100644
>>> --- a/arch/powerpc/include/asm/fsl_lbc.h
>>> +++ b/arch/powerpc/include/asm/fsl_lbc.h
>>> @@ -1,9 +1,10 @@
>>>  /* Freescale Local Bus Controller
>>>   *
>>> - * Copyright (c) 2006-2007 Freescale Semiconductor
>>> + * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
>>>   *
>>>   * Authors: Nick Spence <nick.spence at freescale.com>,
>>>   *          Scott Wood <scottwood at freescale.com>
>>> + *          Jack Lan <jack.lan at freescale.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
>>> @@ -26,6 +27,8 @@
>>>  #include <linux/compiler.h>
>>>  #include <linux/types.h>
>>>  #include <linux/io.h>
>>> +#include <linux/device.h>
>>> +#include <linux/spinlock.h>
>>>
>>>  struct fsl_lbc_bank {
>>>  	__be32 br;             /**< Base Register  */
>>> @@ -125,13 +128,23 @@ struct fsl_lbc_regs {
>>>  #define LTESR_ATMW 0x00800000
>>>  #define LTESR_ATMR 0x00400000
>>>  #define LTESR_CS   0x00080000
>>> +#define LTESR_UPM  0x00000002
>>>  #define LTESR_CC   0x00000001
>>>  #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
>>> +#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
>>> +			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
>>> +			 | LTESR_CC)
>>> +#define LTESR_CLEAR	0xFFFFFFFF
>>> +#define LTECCR_CLEAR	0xFFFFFFFF
>>> +#define LTESR_STATUS	LTESR_MASK
>>> +#define LTEIR_ENABLE	LTESR_MASK
>>> +#define LTEDR_ENABLE	0x00000000
>>>  	__be32 ltedr;           /**< Transfer Error Disable Register */
>>>  	__be32 lteir;           /**< Transfer Error Interrupt Register */
>>>  	__be32 lteatr;          /**< Transfer Error Attributes Register */
>>>  	__be32 ltear;           /**< Transfer Error Address Register */
>>> -	u8 res6[0xC];
>>> +	__be32 lteccr;          /**< Transfer Error ECC Register */
>>> +	u8 res6[0x8];
>>>  	__be32 lbcr;            /**< Configuration Register */
>>>  #define LBCR_LDIS  0x80000000
>>>  #define LBCR_LDIS_SHIFT    31
>>> @@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm
>> *upm)
>>>  		cpu_relax();
>>>  }
>>>
>>> +/* overview of the fsl lbc controller */
>>> +
>>> +struct fsl_lbc_ctrl {
>>> +	/* device info */
>>> +	struct device			*dev;
>>> +	struct fsl_lbc_regs __iomem	*regs;
>>> +	int				irq;
>>> +	wait_queue_head_t		irq_wait;
>>> +	spinlock_t			lock;
>>> +	void				*nand;
>>> +
>>> +	/* status read from LTESR by irq handler */
>>> +	unsigned int			irq_status;
>>> +};
>>> +
>>>  extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
>>>  			       u32 mar);
>>> +extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
>>>
>>>  #endif /* __ASM_FSL_LBC_H */
>>> diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
>>> index dceb8d1..4bb0336 100644
>>> --- a/arch/powerpc/sysdev/fsl_lbc.c
>>> +++ b/arch/powerpc/sysdev/fsl_lbc.c
>>> @@ -2,8 +2,11 @@
>>>   * Freescale LBC and UPM routines.
>>>   *
>>>   * Copyright (c) 2007-2008  MontaVista Software, Inc.
>>> + * Copyright (c) 2010 Freescale Semiconductor
>>>   *
>>>   * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
>>> + * Author: Jack Lan <Jack.Lan at freescale.com>
>>> + * Author: Roy Zang <tie-fei.zang at freescale.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
>>> @@ -19,39 +22,16 @@
>>>  #include <linux/types.h>
>>>  #include <linux/io.h>
>>>  #include <linux/of.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/interrupt.h>
>>> +#include <linux/mod_devicetable.h>
>>>  #include <asm/prom.h>
>>>  #include <asm/fsl_lbc.h>
>>>
>>>  static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
>>> -static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
>>> -
>>> -static char __initdata *compat_lbc[] = {
>>> -	"fsl,pq2-localbus",
>>> -	"fsl,pq2pro-localbus",
>>> -	"fsl,pq3-localbus",
>>> -	"fsl,elbc",
>>> -};
>>> -
>>> -static int __init fsl_lbc_init(void)
>>> -{
>>> -	struct device_node *lbus;
>>> -	int i;
>>> -
>>> -	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
>>> -		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
>>> -		if (lbus)
>>> -			goto found;
>>> -	}
>>> -	return -ENODEV;
>>> -
>>> -found:
>>> -	fsl_lbc_regs = of_iomap(lbus, 0);
>>> -	of_node_put(lbus);
>>> -	if (!fsl_lbc_regs)
>>> -		return -ENOMEM;
>>> -	return 0;
>>> -}
>>> -arch_initcall(fsl_lbc_init);
>>> +struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
>>> +EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
>>>
>>>  /**
>>>   * fsl_lbc_find - find Localbus bank
>>> @@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
>>>  int fsl_lbc_find(phys_addr_t addr_base)
>>>  {
>>>  	int i;
>>> +	struct fsl_lbc_regs __iomem *lbc;
>>>
>>> -	if (!fsl_lbc_regs)
>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>>  		return -ENODEV;
>>>
>>> -	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
>>> -		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
>>> -		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
>>> +	lbc = fsl_lbc_ctrl_dev->regs;
>>> +	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
>>> +		__be32 br = in_be32(&lbc->bank[i].br);
>>> +		__be32 or = in_be32(&lbc->bank[i].or);
>>>
>>>  		if (br & BR_V && (br & or & BR_BA) == addr_base)
>>>  			return i;
>>> @@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm
>> *upm)
>>>  {
>>>  	int bank;
>>>  	__be32 br;
>>> +	struct fsl_lbc_regs __iomem *lbc;
>>>
>>>  	bank = fsl_lbc_find(addr_base);
>>>  	if (bank < 0)
>>>  		return bank;
>>>
>>> -	br = in_be32(&fsl_lbc_regs->bank[bank].br);
>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>> +		return -ENODEV;
>>> +
>>> +	lbc = fsl_lbc_ctrl_dev->regs;
>>> +	br = in_be32(&lbc->bank[bank].br);
>>>
>>>  	switch (br & BR_MSEL) {
>>>  	case BR_MS_UPMA:
>>> -		upm->mxmr = &fsl_lbc_regs->mamr;
>>> +		upm->mxmr = &lbc->mamr;
>>>  		break;
>>>  	case BR_MS_UPMB:
>>> -		upm->mxmr = &fsl_lbc_regs->mbmr;
>>> +		upm->mxmr = &lbc->mbmr;
>>>  		break;
>>>  	case BR_MS_UPMC:
>>> -		upm->mxmr = &fsl_lbc_regs->mcmr;
>>> +		upm->mxmr = &lbc->mcmr;
>>>  		break;
>>>  	default:
>>>  		return -EINVAL;
>>> @@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
>> __iomem *io_base, u32 mar)
>>>  	int ret = 0;
>>>  	unsigned long flags;
>>>
>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>> +		return -ENODEV;
>>> +
>>>  	spin_lock_irqsave(&fsl_lbc_lock, flags);
>>>
>>> -	out_be32(&fsl_lbc_regs->mar, mar);
>>> +	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
>>>
>>>  	switch (upm->width) {
>>>  	case 8:
>>> @@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
>> __iomem *io_base, u32 mar)
>>>  	return ret;
>>>  }
>>>  EXPORT_SYMBOL(fsl_upm_run_pattern);
>>> +
>>> +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
>>> +{
>>> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>>> +
>>> +	/* clear event registers */
>>> +	setbits32(&lbc->ltesr, LTESR_CLEAR);
>>> +	out_be32(&lbc->lteatr, 0);
>>> +	out_be32(&lbc->ltear, 0);
>>> +	out_be32(&lbc->lteccr, LTECCR_CLEAR);
>>> +	out_be32(&lbc->ltedr, LTEDR_ENABLE);
>>> +
>>> +	/* Enable interrupts for any detected events */
>>> +	out_be32(&lbc->lteir, LTEIR_ENABLE);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +/*
>>> + * NOTE: This interrupt is used to report localbus events of various kinds,
>>> + * such as transaction errors on the chipselects.
>>> + */
>>> +
>>> +static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
>>> +{
>>> +	struct fsl_lbc_ctrl *ctrl = data;
>>> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>>> +	u32 status;
>>> +
>>> +	status = in_be32(&lbc->ltesr);
>>> +	if (!status)
>>> +		return IRQ_NONE;
>>> +
>>> +	out_be32(&lbc->ltesr, LTESR_CLEAR);
>>> +	out_be32(&lbc->lteatr, 0);
>>> +	out_be32(&lbc->ltear, 0);
>>> +	ctrl->irq_status = status;
>>> +
>>> +	if (status & LTESR_BM)
>>> +		dev_err(ctrl->dev, "Local bus monitor time-out: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	if (status & LTESR_WP)
>>> +		dev_err(ctrl->dev, "Write protect error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	if (status & LTESR_ATMW)
>>> +		dev_err(ctrl->dev, "Atomic write error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	if (status & LTESR_ATMR)
>>> +		dev_err(ctrl->dev, "Atomic read error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	if (status & LTESR_CS)
>>> +		dev_err(ctrl->dev, "Chip select error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	if (status & LTESR_UPM)
>>> +		;
>>> +	if (status & LTESR_FCT) {
>>> +		dev_err(ctrl->dev, "FCM command time-out: "
>>> +			"LTESR 0x%08X\n", status);
>>> +		smp_wmb();
>>> +		wake_up(&ctrl->irq_wait);
>>> +	}
>>> +	if (status & LTESR_PAR) {
>>> +		dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +		smp_wmb();
>>> +		wake_up(&ctrl->irq_wait);
>>> +	}
>>> +	if (status & LTESR_CC) {
>>> +		smp_wmb();
>>> +		wake_up(&ctrl->irq_wait);
>>> +	}
>>> +	if (status & ~LTESR_MASK)
>>> +		dev_err(ctrl->dev, "Unknown error: "
>>> +			"LTESR 0x%08X\n", status);
>>> +	return IRQ_HANDLED;
>>> +}
>>> +
>>> +/*
>>> + * fsl_lbc_ctrl_probe
>>> + *
>>> + * called by device layer when it finds a device matching
>>> + * one our driver can handled. This code allocates all of
>>> + * the resources needed for the controller only.  The
>>> + * resources for the NAND banks themselves are allocated
>>> + * in the chip probe function.
>>> +*/
>>> +
>>> +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
>>> +{
>>> +	int ret;
>>> +
>>> +	if (!dev->dev.of_node) {
>>> +		dev_err(&dev->dev, "Device OF-Node is NULL");
>>> +		return -EFAULT;
>>> +	}
>>> +
>>> +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
>>> +	if (!fsl_lbc_ctrl_dev)
>>> +		return -ENOMEM;
>>> +
>>> +	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
>>> +
>>> +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
>>> +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
>>> +
>>> +	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
>>> +	if (!fsl_lbc_ctrl_dev->regs) {
>>> +		dev_err(&dev->dev, "failed to get memory region\n");
>>> +		ret = -ENODEV;
>>> +		goto err;
>> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
>> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
>> again. So you should improve that as the following on 'err', or layout 'err'
>> in
>> gain.
>> ------
>> 	if(fsl_lbc_ctrl_dev->regs)
>> 		iounmap(fsl_lbc_ctrl_dev->regs);
>>
>> Tiejun
> 
> You are right!
> How about
>  
>         if (!fsl_lbc_ctrl_dev->regs) {
>                 dev_err(&dev->dev, "failed to get memory region\n");
>                 kfree(fsl_lbc_ctrl_dev);
>                 return -ENOMEM;
>         }

Although this is a big problem, I prefer to return 'ENXIO' :)

Others are fine to me.

Tiejun

> 
> ...
> 
> Thanks.
> Roy



From tiejun.chen at windriver.com  Mon Oct 18 05:46:29 2010
From: tiejun.chen at windriver.com (tiejun.chen)
Date: Mon, 18 Oct 2010 17:46:29 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common
	to	elbc	devices
In-Reply-To: <4CBC16FD.6030507@windriver.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>	<4CBC0B95.9010300@windriver.com>	<3850A844E6A3854C827AC5C0BEC7B60A2B0708@zch01exm23.fsl.freescale.net>
	<4CBC16FD.6030507@windriver.com>
Message-ID: <4CBC1775.6000706@windriver.com>

tiejun.chen wrote:
> Zang Roy-R61911 wrote:
>>> -----Original Message-----
>>> From: tiejun.chen [mailto:tiejun.chen at windriver.com]
>>> Sent: Monday, October 18, 2010 16:56 PM
>>> To: Zang Roy-R61911
>>> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421; dedekind1 at gmail.com; Lan
>>> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
>>> dwmw2 at infradead.org; Gala Kumar-B11780
>>> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
>>> elbc devices
>>>
>>> Roy Zang wrote:
>>>> Move Freescale elbc interrupt from nand dirver to elbc driver.
>>>> Then all elbc devices can use the interrupt instead of ONLY nand.
>>>>
>>>> For former nand driver, it had the two functions:
>>>>
>>>> 1. detecting nand flash partitions;
>>>> 2. registering elbc interrupt.
>>>>
>>>> Now, second function is removed to fsl_lbc.c.
>>>>
>>>> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
>>>> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
>>>> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
>>>> Cc: Wood Scott-B07421 <B07421 at freescale.com>
>>>> ---
>>>>
>>>> These two patches are based on the following commits:
>>>> 1.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>>> September/032112.html
>>>> 2.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>>> September/032110.html
>>>> 3.	http://lists.infradead.org/pipermail/linux-mtd/2010-
>>> September/032111.html
>>>> According to Anton's comment, I merge 1 & 2 together and start a new thread.
>>>> Comparing the provided link:
>>>> 1.	Merge 1 & 2 together.
>>>> 2.	Some code style updates
>>>> 3.	Add counter protect for elbc driver remove
>>>> 4.	Rebase to 2.6.36-rc7
>>>>
>>>> Other histories from the links:
>>>> V2: Comparing with v1, according to the feedback, add some decorations.
>>>>
>>>> V3: Comparing with v2:
>>>> 1.	according to the feedback, add some decorations.
>>>> 2.	change of_platform_driver to platform_driver
>>>> 3.	rebase to 2.6.36-rc4
>>>>
>>>> V4: Comparing with v3
>>>> 1.	minor fix from type unsigned int to u32
>>>> 2.	fix platform_driver issue.
>>>> 3.	add mutex for nand probe
>>>>
>>>>  arch/powerpc/Kconfig               |    7 +-
>>>>  arch/powerpc/include/asm/fsl_lbc.h |   33 +++-
>>>>  arch/powerpc/sysdev/fsl_lbc.c      |  229 ++++++++++++++---
>>>>  drivers/mtd/nand/Kconfig           |    1 +
>>>>  drivers/mtd/nand/fsl_elbc_nand.c   |  482 +++++++++++++++------------------
>>> ---
>>>>  5 files changed, 425 insertions(+), 327 deletions(-)
>>>>
>>>> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>>>> index 631e5a0..44df1ba 100644
>>>> --- a/arch/powerpc/Kconfig
>>>> +++ b/arch/powerpc/Kconfig
>>>> @@ -687,9 +687,12 @@ config 4xx_SOC
>>>>  	bool
>>>>
>>>>  config FSL_LBC
>>>> -	bool
>>>> +	bool "Freescale Local Bus support"
>>>> +	depends on FSL_SOC
>>>>  	help
>>>> -	  Freescale Localbus support
>>>> +	  Enables reporting of errors from the Freescale local bus
>>>> +	  controller.  Also contains some common code used by
>>>> +	  drivers for specific local bus peripherals.
>>>>
>>>>  config FSL_GTM
>>>>  	bool
>>>> diff --git a/arch/powerpc/include/asm/fsl_lbc.h
>>> b/arch/powerpc/include/asm/fsl_lbc.h
>>>> index 1b5a210..0c40c05 100644
>>>> --- a/arch/powerpc/include/asm/fsl_lbc.h
>>>> +++ b/arch/powerpc/include/asm/fsl_lbc.h
>>>> @@ -1,9 +1,10 @@
>>>>  /* Freescale Local Bus Controller
>>>>   *
>>>> - * Copyright (c) 2006-2007 Freescale Semiconductor
>>>> + * Copyright (c) 2006-2007, 2010 Freescale Semiconductor
>>>>   *
>>>>   * Authors: Nick Spence <nick.spence at freescale.com>,
>>>>   *          Scott Wood <scottwood at freescale.com>
>>>> + *          Jack Lan <jack.lan at freescale.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
>>>> @@ -26,6 +27,8 @@
>>>>  #include <linux/compiler.h>
>>>>  #include <linux/types.h>
>>>>  #include <linux/io.h>
>>>> +#include <linux/device.h>
>>>> +#include <linux/spinlock.h>
>>>>
>>>>  struct fsl_lbc_bank {
>>>>  	__be32 br;             /**< Base Register  */
>>>> @@ -125,13 +128,23 @@ struct fsl_lbc_regs {
>>>>  #define LTESR_ATMW 0x00800000
>>>>  #define LTESR_ATMR 0x00400000
>>>>  #define LTESR_CS   0x00080000
>>>> +#define LTESR_UPM  0x00000002
>>>>  #define LTESR_CC   0x00000001
>>>>  #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
>>>> +#define LTESR_MASK      (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
>>>> +			 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
>>>> +			 | LTESR_CC)
>>>> +#define LTESR_CLEAR	0xFFFFFFFF
>>>> +#define LTECCR_CLEAR	0xFFFFFFFF
>>>> +#define LTESR_STATUS	LTESR_MASK
>>>> +#define LTEIR_ENABLE	LTESR_MASK
>>>> +#define LTEDR_ENABLE	0x00000000
>>>>  	__be32 ltedr;           /**< Transfer Error Disable Register */
>>>>  	__be32 lteir;           /**< Transfer Error Interrupt Register */
>>>>  	__be32 lteatr;          /**< Transfer Error Attributes Register */
>>>>  	__be32 ltear;           /**< Transfer Error Address Register */
>>>> -	u8 res6[0xC];
>>>> +	__be32 lteccr;          /**< Transfer Error ECC Register */
>>>> +	u8 res6[0x8];
>>>>  	__be32 lbcr;            /**< Configuration Register */
>>>>  #define LBCR_LDIS  0x80000000
>>>>  #define LBCR_LDIS_SHIFT    31
>>>> @@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm
>>> *upm)
>>>>  		cpu_relax();
>>>>  }
>>>>
>>>> +/* overview of the fsl lbc controller */
>>>> +
>>>> +struct fsl_lbc_ctrl {
>>>> +	/* device info */
>>>> +	struct device			*dev;
>>>> +	struct fsl_lbc_regs __iomem	*regs;
>>>> +	int				irq;
>>>> +	wait_queue_head_t		irq_wait;
>>>> +	spinlock_t			lock;
>>>> +	void				*nand;
>>>> +
>>>> +	/* status read from LTESR by irq handler */
>>>> +	unsigned int			irq_status;
>>>> +};
>>>> +
>>>>  extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
>>>>  			       u32 mar);
>>>> +extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
>>>>
>>>>  #endif /* __ASM_FSL_LBC_H */
>>>> diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
>>>> index dceb8d1..4bb0336 100644
>>>> --- a/arch/powerpc/sysdev/fsl_lbc.c
>>>> +++ b/arch/powerpc/sysdev/fsl_lbc.c
>>>> @@ -2,8 +2,11 @@
>>>>   * Freescale LBC and UPM routines.
>>>>   *
>>>>   * Copyright (c) 2007-2008  MontaVista Software, Inc.
>>>> + * Copyright (c) 2010 Freescale Semiconductor
>>>>   *
>>>>   * Author: Anton Vorontsov <avorontsov at ru.mvista.com>
>>>> + * Author: Jack Lan <Jack.Lan at freescale.com>
>>>> + * Author: Roy Zang <tie-fei.zang at freescale.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
>>>> @@ -19,39 +22,16 @@
>>>>  #include <linux/types.h>
>>>>  #include <linux/io.h>
>>>>  #include <linux/of.h>
>>>> +#include <linux/slab.h>
>>>> +#include <linux/platform_device.h>
>>>> +#include <linux/interrupt.h>
>>>> +#include <linux/mod_devicetable.h>
>>>>  #include <asm/prom.h>
>>>>  #include <asm/fsl_lbc.h>
>>>>
>>>>  static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
>>>> -static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
>>>> -
>>>> -static char __initdata *compat_lbc[] = {
>>>> -	"fsl,pq2-localbus",
>>>> -	"fsl,pq2pro-localbus",
>>>> -	"fsl,pq3-localbus",
>>>> -	"fsl,elbc",
>>>> -};
>>>> -
>>>> -static int __init fsl_lbc_init(void)
>>>> -{
>>>> -	struct device_node *lbus;
>>>> -	int i;
>>>> -
>>>> -	for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
>>>> -		lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
>>>> -		if (lbus)
>>>> -			goto found;
>>>> -	}
>>>> -	return -ENODEV;
>>>> -
>>>> -found:
>>>> -	fsl_lbc_regs = of_iomap(lbus, 0);
>>>> -	of_node_put(lbus);
>>>> -	if (!fsl_lbc_regs)
>>>> -		return -ENOMEM;
>>>> -	return 0;
>>>> -}
>>>> -arch_initcall(fsl_lbc_init);
>>>> +struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
>>>> +EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
>>>>
>>>>  /**
>>>>   * fsl_lbc_find - find Localbus bank
>>>> @@ -65,13 +45,15 @@ arch_initcall(fsl_lbc_init);
>>>>  int fsl_lbc_find(phys_addr_t addr_base)
>>>>  {
>>>>  	int i;
>>>> +	struct fsl_lbc_regs __iomem *lbc;
>>>>
>>>> -	if (!fsl_lbc_regs)
>>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>>>  		return -ENODEV;
>>>>
>>>> -	for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
>>>> -		__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
>>>> -		__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
>>>> +	lbc = fsl_lbc_ctrl_dev->regs;
>>>> +	for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
>>>> +		__be32 br = in_be32(&lbc->bank[i].br);
>>>> +		__be32 or = in_be32(&lbc->bank[i].or);
>>>>
>>>>  		if (br & BR_V && (br & or & BR_BA) == addr_base)
>>>>  			return i;
>>>> @@ -94,22 +76,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm
>>> *upm)
>>>>  {
>>>>  	int bank;
>>>>  	__be32 br;
>>>> +	struct fsl_lbc_regs __iomem *lbc;
>>>>
>>>>  	bank = fsl_lbc_find(addr_base);
>>>>  	if (bank < 0)
>>>>  		return bank;
>>>>
>>>> -	br = in_be32(&fsl_lbc_regs->bank[bank].br);
>>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>>> +		return -ENODEV;
>>>> +
>>>> +	lbc = fsl_lbc_ctrl_dev->regs;
>>>> +	br = in_be32(&lbc->bank[bank].br);
>>>>
>>>>  	switch (br & BR_MSEL) {
>>>>  	case BR_MS_UPMA:
>>>> -		upm->mxmr = &fsl_lbc_regs->mamr;
>>>> +		upm->mxmr = &lbc->mamr;
>>>>  		break;
>>>>  	case BR_MS_UPMB:
>>>> -		upm->mxmr = &fsl_lbc_regs->mbmr;
>>>> +		upm->mxmr = &lbc->mbmr;
>>>>  		break;
>>>>  	case BR_MS_UPMC:
>>>> -		upm->mxmr = &fsl_lbc_regs->mcmr;
>>>> +		upm->mxmr = &lbc->mcmr;
>>>>  		break;
>>>>  	default:
>>>>  		return -EINVAL;
>>>> @@ -148,9 +135,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
>>> __iomem *io_base, u32 mar)
>>>>  	int ret = 0;
>>>>  	unsigned long flags;
>>>>
>>>> +	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
>>>> +		return -ENODEV;
>>>> +
>>>>  	spin_lock_irqsave(&fsl_lbc_lock, flags);
>>>>
>>>> -	out_be32(&fsl_lbc_regs->mar, mar);
>>>> +	out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
>>>>
>>>>  	switch (upm->width) {
>>>>  	case 8:
>>>> @@ -172,3 +162,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void
>>> __iomem *io_base, u32 mar)
>>>>  	return ret;
>>>>  }
>>>>  EXPORT_SYMBOL(fsl_upm_run_pattern);
>>>> +
>>>> +static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
>>>> +{
>>>> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>>>> +
>>>> +	/* clear event registers */
>>>> +	setbits32(&lbc->ltesr, LTESR_CLEAR);
>>>> +	out_be32(&lbc->lteatr, 0);
>>>> +	out_be32(&lbc->ltear, 0);
>>>> +	out_be32(&lbc->lteccr, LTECCR_CLEAR);
>>>> +	out_be32(&lbc->ltedr, LTEDR_ENABLE);
>>>> +
>>>> +	/* Enable interrupts for any detected events */
>>>> +	out_be32(&lbc->lteir, LTEIR_ENABLE);
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>> +/*
>>>> + * NOTE: This interrupt is used to report localbus events of various kinds,
>>>> + * such as transaction errors on the chipselects.
>>>> + */
>>>> +
>>>> +static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
>>>> +{
>>>> +	struct fsl_lbc_ctrl *ctrl = data;
>>>> +	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
>>>> +	u32 status;
>>>> +
>>>> +	status = in_be32(&lbc->ltesr);
>>>> +	if (!status)
>>>> +		return IRQ_NONE;
>>>> +
>>>> +	out_be32(&lbc->ltesr, LTESR_CLEAR);
>>>> +	out_be32(&lbc->lteatr, 0);
>>>> +	out_be32(&lbc->ltear, 0);
>>>> +	ctrl->irq_status = status;
>>>> +
>>>> +	if (status & LTESR_BM)
>>>> +		dev_err(ctrl->dev, "Local bus monitor time-out: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	if (status & LTESR_WP)
>>>> +		dev_err(ctrl->dev, "Write protect error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	if (status & LTESR_ATMW)
>>>> +		dev_err(ctrl->dev, "Atomic write error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	if (status & LTESR_ATMR)
>>>> +		dev_err(ctrl->dev, "Atomic read error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	if (status & LTESR_CS)
>>>> +		dev_err(ctrl->dev, "Chip select error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	if (status & LTESR_UPM)
>>>> +		;
>>>> +	if (status & LTESR_FCT) {
>>>> +		dev_err(ctrl->dev, "FCM command time-out: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +		smp_wmb();
>>>> +		wake_up(&ctrl->irq_wait);
>>>> +	}
>>>> +	if (status & LTESR_PAR) {
>>>> +		dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +		smp_wmb();
>>>> +		wake_up(&ctrl->irq_wait);
>>>> +	}
>>>> +	if (status & LTESR_CC) {
>>>> +		smp_wmb();
>>>> +		wake_up(&ctrl->irq_wait);
>>>> +	}
>>>> +	if (status & ~LTESR_MASK)
>>>> +		dev_err(ctrl->dev, "Unknown error: "
>>>> +			"LTESR 0x%08X\n", status);
>>>> +	return IRQ_HANDLED;
>>>> +}
>>>> +
>>>> +/*
>>>> + * fsl_lbc_ctrl_probe
>>>> + *
>>>> + * called by device layer when it finds a device matching
>>>> + * one our driver can handled. This code allocates all of
>>>> + * the resources needed for the controller only.  The
>>>> + * resources for the NAND banks themselves are allocated
>>>> + * in the chip probe function.
>>>> +*/
>>>> +
>>>> +static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
>>>> +{
>>>> +	int ret;
>>>> +
>>>> +	if (!dev->dev.of_node) {
>>>> +		dev_err(&dev->dev, "Device OF-Node is NULL");
>>>> +		return -EFAULT;
>>>> +	}
>>>> +
>>>> +	fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
>>>> +	if (!fsl_lbc_ctrl_dev)
>>>> +		return -ENOMEM;
>>>> +
>>>> +	dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
>>>> +
>>>> +	spin_lock_init(&fsl_lbc_ctrl_dev->lock);
>>>> +	init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
>>>> +
>>>> +	fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
>>>> +	if (!fsl_lbc_ctrl_dev->regs) {
>>>> +		dev_err(&dev->dev, "failed to get memory region\n");
>>>> +		ret = -ENODEV;
>>>> +		goto err;
>>> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
>>> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
>>> again. So you should improve that as the following on 'err', or layout 'err'
>>> in
>>> gain.
>>> ------
>>> 	if(fsl_lbc_ctrl_dev->regs)
>>> 		iounmap(fsl_lbc_ctrl_dev->regs);
>>>
>>> Tiejun
>> You are right!
>> How about
>>  
>>         if (!fsl_lbc_ctrl_dev->regs) {
>>                 dev_err(&dev->dev, "failed to get memory region\n");
>>                 kfree(fsl_lbc_ctrl_dev);
>>                 return -ENOMEM;
>>         }
> 
> Although this is a big problem, I prefer to return 'ENXIO' :)
		^
		Typo: is not a ......

Tiejun

> 
> Others are fine to me.
> 
> Tiejun
> 
>> ...
>>
>> Thanks.
>> Roy
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 



From dedekind1 at gmail.com  Mon Oct 18 06:01:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 13:01:15 +0300
Subject: [PATCH 1/2] UBIFS: do not allocate unneeded scan buffer
Message-ID: <1287396075-1840-1-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

In 'ubifs_replay_journal()' we allocate 'sbuf' for scanning the log.
However, we already have 'c->sbuf' for these purposes, so do not
allocate yet another one. This reduces UBIFS memory consumption while
recovering.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/replay.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 7df04ba..eed0fcf 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -1013,7 +1013,6 @@ out:
 int ubifs_replay_journal(struct ubifs_info *c)
 {
 	int err, i, lnum, offs, free;
-	void *sbuf = NULL;
 
 	BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1028,10 +1027,6 @@ int ubifs_replay_journal(struct ubifs_info *c)
 		return -EINVAL;
 	}
 
-	sbuf = vmalloc(c->leb_size);
-	if (!sbuf)
-		return -ENOMEM;
-
 	dbg_mnt("start replaying the journal");
 	c->replaying = 1;
 	lnum = c->ltail_lnum = c->lhead_lnum;
@@ -1046,7 +1041,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
 			lnum = UBIFS_LOG_LNUM;
 			offs = 0;
 		}
-		err = replay_log_leb(c, lnum, offs, sbuf);
+		err = replay_log_leb(c, lnum, offs, c->sbuf);
 		if (err == 1)
 			/* We hit the end of the log */
 			break;
@@ -1079,7 +1074,6 @@ int ubifs_replay_journal(struct ubifs_info *c)
 out:
 	destroy_replay_tree(c);
 	destroy_bud_list(c);
-	vfree(sbuf);
 	c->replaying = 0;
 	return err;
 }
-- 
1.7.2.3



From dedekind1 at gmail.com  Mon Oct 18 06:02:05 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 13:02:05 +0300
Subject: [PATCH 2/2] UBIFS: add unstable pages problem description
Message-ID: <1287396125-1890-1-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Describe a problem reported by Matthieu CASTET which is currently
not handled by UBIFS.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/replay.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index eed0fcf..e04d74a 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -32,6 +32,28 @@
  * larger is the journal, the more memory its index may consume.
  */
 
+/*
+ * Problem description: unstable pages after unclean power cut on NAND flashes.
+ *
+ * If a power cut happens when we have ongoing NAND page program, this page
+ * becomes unstable. The following situations are possible when we mount this
+ * flash next time and UBIFS reads the page.
+ *   o The page may look like it is empty, i.e., it contains only 0xFFs, but
+ *     we write data there, the data becomes corrupted. I.e., when the data are
+ *     read, we may get a ECC errors. Moreover, the page may be read with no
+ *     errors sometimes, with an ECC error next time, with a bit-flip next
+ *     time, etc.
+ *   o The page may have bit-flip, but when it is read next time, it may have
+ *     ECC errors or no errors at all.
+ *   o An UBIFS	node may have correct CRC, but when it is read next time, it
+ *     may have CRC error.
+ *
+ * IOW, these unstable pages are disaster. UBIFS has to handle them correctly:
+ * never write to them and never rely on their contents.
+ *
+ * TODO: handle this for buds, log, orphan area, and master area.
+ */
+
 #include "ubifs.h"
 
 /*
-- 
1.7.2.3



From dedekind1 at gmail.com  Mon Oct 18 06:21:13 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 13:21:13 +0300
Subject: UBI/UBIFS interrupted write page handling
In-Reply-To: <4CA9D2A0.6010508@parrot.com>
References: <4C88DDD5.4060507@parrot.com>
	<1284054669.11335.21.camel@brekeke> <1285006478.1762.1.camel@brekeke>
	<4C9B7CD8.4070806@parrot.com>,<1285266914.1766.1.camel@brekeke>
	<F5C24FC168F95048BB6B9E0B13EB33152BA6F5304E@DIAMANT.xi-lite.lan>
	<1285523911.1776.9.camel@brekeke> <1285657088.2437.23.camel@localhost>
	<4CA19DAE.7030402@parrot.com> <1285660934.2437.44.camel@localhost>
	<4CA9D2A0.6010508@parrot.com>
Message-ID: <1287397273.1972.37.camel@localhost>

On Mon, 2010-10-04 at 15:12 +0200, Matthieu CASTET wrote:
> Artem Bityutskiy a ?crit :
> > On Tue, 2010-09-28 at 09:47 +0200, Matthieu CASTET wrote:
> >> Artem Bityutskiy a ?crit :
> >>> On Sun, 2010-09-26 at 20:58 +0300, Artem Bityutskiy wrote:
> >>>
> >> That's better : interrupt erased page are not put anymore in corrupted list.
> >> But I have problem with interrupt write :
> >> this night the test crashed [1].
> > 
> > Yeah, this should be fixed by forcing LEB refresh for the last LEBs of
> > journal heads. This problem exists long time. I'll work on this and send
> > you patches.
> UBI will need also some patch.
> For example in case of wear leveling, ubi could move a leb from a peb to 
> another and the write can be interrupted.

Hmm, yeah, we have CRC in this case and we rely on CRC. However, if the
write to the last page was interrupted, it can be unstable and can
sometimes be read correctly, but sometimes incorrectly. So UBI should
refresh such PEBs.

I guess it is easier to start with UBI first.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Oct 18 06:31:29 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 18 Oct 2010 13:31:29 +0300
Subject: [PATCH] nanddump: warn when the start address is not page aligned
In-Reply-To: <1909cbad57553279212f156a0c7cb20178981909.1287386497.git.baruch@tkos.co.il>
References: <1287256127.1781.32.camel@brekeke>
	<1909cbad57553279212f156a0c7cb20178981909.1287386497.git.baruch@tkos.co.il>
Message-ID: <1287397889.1972.46.camel@localhost>

On Mon, 2010-10-18 at 09:23 +0200, Baruch Siach wrote:
> nanddump should be consistent with nandwrite, which does not accept non page
> aligned start addresses. Thus, non page aligned dumps are useless.
> 
> To ease migration only warn for now. Add the plan of making this an error to
> feature-removal-schedule.txt.
> 
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
>  feature-removal-schedule.txt |   12 +++++++++++-
>  nanddump.c                   |    7 +++++++
>  2 files changed, 18 insertions(+), 1 deletions(-)
> 
> diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
> index 21bc8d4..f4ed2a3 100644
> --- a/feature-removal-schedule.txt
> +++ b/feature-removal-schedule.txt
> @@ -27,5 +27,15 @@ So the plan is (to be done by Artem Bityutskiy):
>  3.1 adding a warning to make users stop using them
>  3.2 removing both options.
>  ---------------------------
> -2.
> +2. nanddump: fail when the -s parameter is not page aligned
> +
> +nanddump should be consistent with nandwrite, and refuse accepting non page 
> +aligned start addresses. These dumps are most likely useless, since nandwrite 
> +won't write then at this location. Currently only a warning is issued to keep 
> +backward compatibility during a transition period. This should become an error 
> +after 1.5.0.

I tweaked this and removed 1.5.0 - it is better to not specify exact
version. Also, fixed the following trailing white-spaces issue for the
feature-removal-schedule.txt part:

Applying: nanddump: warn when the start address is not page aligned
/home/dedekind/git/mtd-utils/.git/rebase-apply/patch:17: trailing whitespace.
nanddump should be consistent with nandwrite, and refuse accepting non page 
/home/dedekind/git/mtd-utils/.git/rebase-apply/patch:18: trailing whitespace.
aligned start addresses. These dumps are most likely useless, since nandwrite 
/home/dedekind/git/mtd-utils/.git/rebase-apply/patch:19: trailing whitespace.
won't write then at this location. Currently only a warning is issued to keep 
/home/dedekind/git/mtd-utils/.git/rebase-apply/patch:20: trailing whitespace.
backward compatibility during a transition period. This should become an error 
warning: 4 lines add whitespace errors.

And pushed, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From w.sang at pengutronix.de  Mon Oct 18 07:41:04 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Mon, 18 Oct 2010 13:41:04 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
Message-ID: <20101018114104.GC15440@pengutronix.de>

On Mon, Oct 18, 2010 at 12:00:46PM +0800, yidong zhang wrote:
> hi
>    The 39VF*-B-Version flashes in the cfi_nopri_fixup_table don't work
> well in the current code.  Because of the mistaken use of
> command(0x30) in the 6th bus cycle, which should be 0x50. I think the
> 39VF*-B-Version flashes should be removed form the CFI probe mode. Or
> maybe the erase operation should be changed for the Compatibility.

Or we put in a variable like the unlock-address?

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101018/717575df/attachment.sig>

From zhangyd6 at gmail.com  Mon Oct 18 09:05:12 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 18 Oct 2010 21:05:12 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <20101018114104.GC15440@pengutronix.de>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
Message-ID: <AANLkTikHy9OCYWuZJUKnEyK=9uvwg6LRZvkW_YhL5esm@mail.gmail.com>

On Mon, Oct 18, 2010 at 7:41 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> On Mon, Oct 18, 2010 at 12:00:46PM +0800, yidong zhang wrote:
>> hi
>> ? ?The 39VF*-B-Version flashes in the cfi_nopri_fixup_table don't work
>> well in the current code. ?Because of the mistaken use of
>> command(0x30) in the 6th bus cycle, which should be 0x50. I think the
>> 39VF*-B-Version flashes should be removed form the CFI probe mode. Or
>> maybe the erase operation should be changed for the Compatibility.
>
> Or we put in a variable like the unlock-address?

Maybe that's a better solution. I have no other methods.


>
> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAky8Mk8ACgkQD27XaX1/VRtD1QCgvhKREHwzceC1STdpZXJ2qrum
> Wg4An0JXJSQTkr5eShXUdykOn6lhlvbt
> =3BkZ
> -----END PGP SIGNATURE-----
>
>


From glecerf at gmail.com  Mon Oct 18 09:41:34 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Mon, 18 Oct 2010 15:41:34 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <20101018114104.GC15440@pengutronix.de>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
Message-ID: <AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>

2010/10/18 Wolfram Sang <w.sang at pengutronix.de>:
>> ? ?The 39VF*-B-Version flashes in the cfi_nopri_fixup_table don't work
>> well in the current code. ?Because of the mistaken use of
>> command(0x30) in the 6th bus cycle, which should be 0x50. I think the
>> 39VF*-B-Version flashes should be removed form the CFI probe mode. Or
>> maybe the erase operation should be changed for the Compatibility.
>
> Or we put in a variable like the unlock-address?

I'm OK with solution, that's what I try to implement atm, but I'm
still looking for the right place to put this variable.


-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From zhangyd6 at gmail.com  Mon Oct 18 22:06:50 2010
From: zhangyd6 at gmail.com (zhangyd)
Date: Mon, 18 Oct 2010 22:06:50 -0400
Subject: [PATCH] mtd: chips: Add SST38VF640x NOR-flashes
Message-ID: <1287454010-2718-1-git-send-email-zhangyd6@gmail.com>

Du to the wrong sector size description(The actual sector size is
8KBytes/sector, but the reporting size is 64KBytes/sector),you can get
the wrong size of the memory. So they should be moved to the jedec_probe.

Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
---
 drivers/mtd/chips/jedec_probe.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index d72a5fb..0e8df3b 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -163,6 +163,7 @@
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
 #define SST49LF080A	0x005B
+#define SST38VF6401	0x536B
 #define SST36VF3203	0x7354
 
 /* Toshiba */
@@ -1568,6 +1569,16 @@ static const struct amd_flash_info jedec_table[] = {
 			ERASEINFO(0x10000,64),
 		}
 	}, {
+		.mfr_id		= CFI_MFR_SST,
+		.dev_id		= SST38VF6401,
+		.name		= "SST 38VF6401",
+		.devtypes	= CFI_DEVICETYPE_X16,
+		.cmd_set	= P_ID_AMD_STD,
+		.nr_regions	= 1,
+		.regions	= {
+			ERASEINFO(0x10000,128),
+		}
+	}, {
 		.mfr_id		= CFI_MFR_ST,
 		.dev_id		= M29F800AB,
 		.name		= "ST M29F800AB",
-- 
1.7.2.3



From w.sang at pengutronix.de  Mon Oct 18 10:56:20 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Mon, 18 Oct 2010 16:56:20 +0200
Subject: [PATCH] mtd: chips: Add SST38VF640x NOR-flashes
In-Reply-To: <1287454010-2718-1-git-send-email-zhangyd6@gmail.com>
References: <1287454010-2718-1-git-send-email-zhangyd6@gmail.com>
Message-ID: <20101018145620.GA22538@pengutronix.de>

On Mon, Oct 18, 2010 at 10:06:50PM -0400, zhangyd wrote:
> Du to the wrong sector size description(The actual sector size is
> 8KBytes/sector, but the reporting size is 64KBytes/sector),you can get
> the wrong size of the memory. So they should be moved to the jedec_probe.
> 
> Signed-off-by: yidong zhang<zhangyd6 at gmail.com>

NACK as long as Guillaume has not finished updating the SST-support for CFI. He
said he is working on this at the moment, let's give him a chance to finish :)

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101018/dab49a0a/attachment.sig>

From zhangyd6 at gmail.com  Mon Oct 18 11:00:25 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 18 Oct 2010 23:00:25 +0800
Subject: [PATCH] mtd: chips: Add SST38VF640x NOR-flashes
In-Reply-To: <20101018145620.GA22538@pengutronix.de>
References: <1287454010-2718-1-git-send-email-zhangyd6@gmail.com>
	<20101018145620.GA22538@pengutronix.de>
Message-ID: <AANLkTink3zhFQSswA0XFvuZu=AUDmGxMWWbqWsF=qyB+@mail.gmail.com>

On Mon, Oct 18, 2010 at 10:56 PM, Wolfram Sang <w.sang at pengutronix.de> wrote:
> On Mon, Oct 18, 2010 at 10:06:50PM -0400, zhangyd wrote:
>> Du to the wrong sector size description(The actual sector size is
>> 8KBytes/sector, but the reporting size is 64KBytes/sector),you can get
>> the wrong size of the memory. So they should be moved to the jedec_probe.
>>
>> Signed-off-by: yidong zhang<zhangyd6 at gmail.com>
>
> NACK as long as Guillaume has not finished updating the SST-support for CFI. He
> said he is working on this at the moment, let's give him a chance to finish :)

OK , Thanks!

> --
> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | Wolfram Sang ? ? ? ? ? ? ? ?|
> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAky8YBQACgkQD27XaX1/VRtz6ACeMLJleCWrFki71rpj+0ELYala
> A8sAnA6Frg62shANhZn7xEW1196rHBxr
> =P1xd
> -----END PGP SIGNATURE-----
>
>


From scottwood at freescale.com  Mon Oct 18 12:06:31 2010
From: scottwood at freescale.com (Scott Wood)
Date: Mon, 18 Oct 2010 11:06:31 -0500
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc	devices
In-Reply-To: <4CBC0B95.9010300@windriver.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<4CBC0B95.9010300@windriver.com>
Message-ID: <20101018110631.22d6f081@udp111988uds.am.freescale.net>

On Mon, 18 Oct 2010 16:55:49 +0800
"tiejun.chen" <tiejun.chen at windriver.com> wrote:

> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
> again. So you should improve that as the following on 'err', or layout 'err' in
> gain.
> ------
> 	if(fsl_lbc_ctrl_dev->regs)
> 		iounmap(fsl_lbc_ctrl_dev->regs);
> 

It looks like iounmap(NULL) is a no-op, just like kfree(NULL).

-Scott



From jacmet at sunsite.dk  Mon Oct 18 16:51:48 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Mon, 18 Oct 2010 22:51:48 +0200
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <1287244167.1781.2.camel@brekeke> (Artem Bityutskiy's message of
	"Sat, 16 Oct 2010 18:49:27 +0300")
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
	<87lj5zet2y.fsf@macbook.be.48ers.dk> <1287244167.1781.2.camel@brekeke>
Message-ID: <871v7n442j.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

 Artem> On Fri, 2010-10-15 at 10:52 +0200, Peter Korsgaard wrote:
 >> >>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:
 >> 
 >> >> Artem: Time for a v1.4.1 release?
 >> 
 Artem> Thanks. If it works, I'll back-port Mike's patch to 1.4.0 and tag it as
 Artem> 1.4.1. So 1.4.1 won't include tons of irrelevant commits.
 >> 
 >> Great. An easy way to test:

 Artem> Done. You can find v1.4.1 tag, tarball, and announcement in the "news"
 Artem> section of the web site.

Thanks, but the 1.4.1 tarball is screwed - It contains a bunch of build
files which breaks the build if they aren't removed first.

diff -urpN mtd-utils-1.4.?|diffstat
 compr_zlib.c                       |    2 
 cscope.out                         |314340 +++++++++++++++++++++++++++++++++++++
 jffs2reader.c                      |    1 
 mkfs.jffs2.c                       |   49 
 mkfs.ubifs/compr.c                 |    1 
 tests/fs-tests/lib/tests.o         |binary
 tests/ubi-tests/.common.c.dep      |   38 
 tests/ubi-tests/.integ.c.dep       |   38 
 tests/ubi-tests/.io_basic.c.dep    |   33 
 tests/ubi-tests/.io_paral.c.dep    |   32 
 tests/ubi-tests/.io_read.c.dep     |   33 
 tests/ubi-tests/.io_update.c.dep   |   33 
 tests/ubi-tests/.mkvol_bad.c.dep   |   24 
 tests/ubi-tests/.mkvol_basic.c.dep |   24 
 tests/ubi-tests/.mkvol_paral.c.dep |   27 
 tests/ubi-tests/.rsvol.c.dep       |   33 
 tests/ubi-tests/.volrefcnt.c.dep   |   31 
 tests/ubi-tests/common.o           |binary
 tests/ubi-tests/integ              |binary
 tests/ubi-tests/io_basic           |binary
 tests/ubi-tests/io_paral           |binary
 tests/ubi-tests/io_read            |binary
 tests/ubi-tests/io_update          |binary
 tests/ubi-tests/libubi.a           |binary
 tests/ubi-tests/libubi.o           |binary
 tests/ubi-tests/mkvol_bad          |binary
 tests/ubi-tests/mkvol_basic        |binary
 tests/ubi-tests/mkvol_paral        |binary
 tests/ubi-tests/rsvol              |binary
 tests/ubi-tests/volrefcnt          |binary
 ubi-utils/cscope.out               |164861 +++++++++++++++++++
 ubi-utils/libmtd.a                 |binary
 32 files changed, 479573 insertions(+), 27 deletions(-)

Care to fix that?

-- 
Bye, Peter Korsgaard


From karsten at jeppesens.com  Mon Oct 18 17:22:37 2010
From: karsten at jeppesens.com (Karsten Jeppesen)
Date: Mon, 18 Oct 2010 23:22:37 +0200
Subject: Expanding UBI fs to maxavailable size
Message-ID: <4CBCBA9D.4040202@jeppesens.com>

Hi there,
....I think I found an error :-)

I have an ARM platform with either 32 or 64MB FLASH, and I want to make 
an image that I can burn more or less directly (ie: not tar) into the 
flash regardless if its the 32 or the 64MB edition.
So I assumed that is what the autoresize flag is about, but maybe I am 
wrong here.
I can get ubiformat to burn the image to the flash, but subsequently the 
filesystem doesn't expand to occupy the max available area.
What am I doing wrong - and how is it supposed to be achieved? Or is 
this an error or a missing feature?

Content of ubinize.cfg is>
---
[kjp_ubi]
mode=ubi
image=kjp.img
vol_id=0
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize
---

and my generation script looks like this:
---
#!/bin/sh
rm -rf work *.img 2>/dev/null
mkdir work
tar xzf armroot-stripped.tar.gz --directory work
mkfs.ubifs --root=work --min-io-size=1 --leb-size=130944 
--max-leb-cnt=232 -o kjp.img -x zlib
ubinize -o ubi.img --min-io-size=1 --peb-size=131072 ubinize.cfg
---

Burning the image to flash using:
ubiformat /dev/mtd4 -e 0 --yes -f ubi.img

The resulting filesystem will in the 64 MB edition be about 470 leb's. 
But the stupid thing wont expand. Sigh.

Enlightenment will be greatly appreciated

Sincerely,
Karsten Jeppesen



From tiejun.chen at windriver.com  Mon Oct 18 21:35:05 2010
From: tiejun.chen at windriver.com (tiejun.chen)
Date: Tue, 19 Oct 2010 09:35:05 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common
	to	elbc	devices
In-Reply-To: <20101018110631.22d6f081@udp111988uds.am.freescale.net>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>	<4CBC0B95.9010300@windriver.com>
	<20101018110631.22d6f081@udp111988uds.am.freescale.net>
Message-ID: <4CBCF5C9.5070209@windriver.com>

Scott Wood wrote:
> On Mon, 18 Oct 2010 16:55:49 +0800
> "tiejun.chen" <tiejun.chen at windriver.com> wrote:
> 
>> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
>> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
>> again. So you should improve that as the following on 'err', or layout 'err' in
>> gain.
>> ------
>> 	if(fsl_lbc_ctrl_dev->regs)
>> 		iounmap(fsl_lbc_ctrl_dev->regs);
>>
> 
> It looks like iounmap(NULL) is a no-op, just like kfree(NULL).
> 

Absolutely, I know what you mean :)

But I think we should take care of every line as one normal progress/rule. That
will make us understand easily, and maybe we also would benefit a little good
performance from those codes.

Tiejun

> -Scott
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 



From dedekind1 at gmail.com  Tue Oct 19 00:49:14 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 19 Oct 2010 07:49:14 +0300
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <871v7n442j.fsf@macbook.be.48ers.dk>
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
	<87lj5zet2y.fsf@macbook.be.48ers.dk>
	<1287244167.1781.2.camel@brekeke> <871v7n442j.fsf@macbook.be.48ers.dk>
Message-ID: <1287463754.1911.0.camel@brekeke>

On Mon, 2010-10-18 at 22:51 +0200, Peter Korsgaard wrote:
> Care to fix that?

Re-uploaded fixed tarball.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)




From dedekind1 at gmail.com  Tue Oct 19 01:12:34 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 19 Oct 2010 08:12:34 +0300
Subject: Expanding UBI fs to maxavailable size
In-Reply-To: <4CBCBA9D.4040202@jeppesens.com>
References: <4CBCBA9D.4040202@jeppesens.com>
Message-ID: <1287465154.1911.2.camel@brekeke>

On Mon, 2010-10-18 at 23:22 +0200, Karsten Jeppesen wrote:
> Hi there,
> ....I think I found an error :-)
> 
> I have an ARM platform with either 32 or 64MB FLASH, and I want to make 
> an image that I can burn more or less directly (ie: not tar) into the 
> flash regardless if its the 32 or the 64MB edition.
> So I assumed that is what the autoresize flag is about, but maybe I am 
> wrong here.
> I can get ubiformat to burn the image to the flash, but subsequently the 
> filesystem doesn't expand to occupy the max available area.
> What am I doing wrong - and how is it supposed to be achieved? Or is 
> this an error or a missing feature?

What do you see in dmesg from UBI/UBIFS?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From viresh.kumar at st.com  Tue Oct 19 01:55:55 2010
From: viresh.kumar at st.com (viresh kumar)
Date: Tue, 19 Oct 2010 11:25:55 +0530
Subject: [PATCH V2 25/69] ST SPEAr: Add smi driver for serial NOR flash
In-Reply-To: <238bd0ff57f8530c597157bc07f6c46dc362e1bc.1285933331.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<238bd0ff57f8530c597157bc07f6c46dc362e1bc.1285933331.git.viresh.kumar@st.com>
Message-ID: <4CBD32EB.5050409@st.com>

On 10/01/2010 05:25 PM, Viresh KUMAR wrote:
> From: Shiraz Hashim <shiraz.hashim at st.com>
> 
> SPEAr platforms(spear3xx/spear6xx/spear13xx) provide SMI(Serial Memory
> Interface) controller to access serial NOR flash. SMI provides a simple
> interface for SPI/serial NOR flashes and has certain inbuilt commands
> and features to support these flashes easily. It also makes it possible
> to map an address range in order to directly access (read/write) the SNOR
> over address bus. This patch intends to provide serial nor driver support
> for spear platforms which are accessed through SMI.
> 
> Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
> Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
> ---
>  arch/arm/plat-spear/include/plat/smi.h |   68 ++
>  drivers/mtd/devices/Kconfig            |    7 +
>  drivers/mtd/devices/Makefile           |    1 +
>  drivers/mtd/devices/spear_smi.c        | 1122 ++++++++++++++++++++++++++++++++
>  4 files changed, 1198 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/plat-spear/include/plat/smi.h
>  create mode 100644 drivers/mtd/devices/spear_smi.c

David,

Any review comments on this patch??

-- 
viresh


From r61911 at freescale.com  Tue Oct 19 02:37:56 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Tue, 19 Oct 2010 14:37:56 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc	devices
In-Reply-To: <20101018110631.22d6f081@udp111988uds.am.freescale.net>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com><4CBC0B95.9010300@windriver.com>
	<20101018110631.22d6f081@udp111988uds.am.freescale.net>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B07BC@zch01exm23.fsl.freescale.net>


> -----Original Message-----
> From: Wood Scott-B07421
> Sent: Tuesday, October 19, 2010 0:07 AM
> To: tiejun.chen
> Cc: Zang Roy-R61911; linux-mtd at lists.infradead.org; Wood Scott-B07421;
> dedekind1 at gmail.com; Lan Chunhe-B25806; linuxppc-dev at ozlabs.org;
akpm at linux-
> foundation.org; dwmw2 at infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
common to
> elbc devices
> 
> On Mon, 18 Oct 2010 16:55:49 +0800
> "tiejun.chen" <tiejun.chen at windriver.com> wrote:
> 
> > Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err'
but here
> > of_iomap() is already failed you should skip iounmap()
fsl_lbc_ctrl_dev-
> >regs
> > again. So you should improve that as the following on 'err', or
layout 'err'
> in
> > gain.
> > ------
> > 	if(fsl_lbc_ctrl_dev->regs)
> > 		iounmap(fsl_lbc_ctrl_dev->regs);
> >
> 
> It looks like iounmap(NULL) is a no-op, just like kfree(NULL).
Thanks for the reminder. I will keep original post, if there is no more
comment.
Roy



From dedekind1 at gmail.com  Tue Oct 19 03:57:48 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 19 Oct 2010 10:57:48 +0300
Subject: [PATCH 2/2] UBIFS: add unstable pages problem description
In-Reply-To: <1287396125-1890-1-git-send-email-dedekind1@gmail.com>
References: <1287396125-1890-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1287475068.9272.8.camel@localhost>

On Mon, 2010-10-18 at 13:02 +0300, Artem Bityutskiy wrote:
> From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> 
> Describe a problem reported by Matthieu CASTET which is currently
> not handled by UBIFS.
> 
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Matthiew, are you happy with this description? Does it properly reflect
your findings? Could you please correct, if not?

I'm starting working on your problem. Since I do not have much time,
I'll do a little everyday, but hope to come up with some patches this
week already. The thing is that it is a lot of work. We need to go
through a lot of UBI/UBIFS subsystems and analyze them.

Why a lot of work? Because we assumed everywhere we can rely on CRC - if
it is correct, we are safe. However, according to you this is not
reliable for unstable pages - you do not have guarantee that next time
you read it you will get correct data.

Also, I do not have HW to test this, so I expect you to help by testing,
are your testing set-ups kept ready? :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From arm9263 at yahoo.com  Tue Oct 19 04:17:51 2010
From: arm9263 at yahoo.com (Karsten Jeppesen)
Date: Tue, 19 Oct 2010 01:17:51 -0700 (PDT)
Subject: Expanding UBI fs to maxavailable size
In-Reply-To: <1287465154.1911.2.camel@brekeke>
References: <4CBCBA9D.4040202@jeppesens.com> <1287465154.1911.2.camel@brekeke>
Message-ID: <968604.60195.qm@web120213.mail.ne1.yahoo.com>

Hi Artem,

This is Karsten Jeppesen, just using an out-of-the-house account,
and thanks for your very quick reply.

The short answer to your question about dmesg is: no messages at any point from 
UBI whatsoever.

Here is a more detailed answer:
This part is executed on the development machine which is a Fedora running on an 
x86:
[root at vserver09 ubifs]# rm -rf work *.img 2>/dev/null
[root at vserver09 ubifs]# mkdir work
[root at vserver09 ubifs]# tar xzf /tftpboot/SKOV/armroot-stripped.tar.gz 
--directory work
[root at vserver09 ubifs]# mkfs.ubifs --root=work --min-io-size=1 --leb-size=130944 
--max-leb-cnt=232 -o kjp.img -x zlib
[root at vserver09 ubifs]# ubinize -o ubi.img --min-io-size=1 --peb-size=131072 
ubinize.cfg
ubinize: volume size was not specified in section "kjp_ubi", assume minimum to 
fit image "kjp.img"14272896 bytes (13.6 MiB)

Content of ubinize.cfg is:
[kjp_ubi]
mode=ubi
image=kjp.img
vol_id=0
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

Next part is executed on the target ARM 9263 with the 64MB FLASH fitted, running 
my distribution (Fedora based) via NFS (so the FLASH is not used)
Logging rerouted to console so it intermixes commands:
ubiformat: mtd4 (nor), size 63700992 bytes (60.8 MiB), 486 eraseblocks of 131072 
bytes (128.0 KiB), min. I/O size 1 bytes
libscan: scanning eraseblock 485 -- 100 % complete
ubiformat: 485 eraseblocks have valid erase counter, mean value is 0
ubiformat: 1 eraseblocks are supposedly empty
ubiformat: use erase counter 0 for all eraseblocks
ubiformat: flashing eraseblock 110 -- 100 % complete
ubiformat: formatting eraseblock 485 -- 100 % complete
# ubiattach /dev/ubi_ctrl -m 4
UBI device number 0, total 486 LEBs (63638784 bytes, 60.7 MiB), available 0 LEBs 
(0 bytes), LEB size 130944 bytes (127.9 KiB)
# mkdir -p /skov/mnt/ubi
# mount -t ubifs ubi0:rootfs /skov/mnt/ubi

As of this point no messages has been received via syslog from the UBI system

Here comes what I don't like. Meaning that I can see the rationale, but its not 
what I hoped for:
Ubinfo shows that ubiformat correctly

# ubinfo -a
UBI version:                    1
Count of UBI devices:           1
UBI control device major/minor: 10:63
Present UBI devices:            ubi0

ubi0
Volumes count:                           1
Logical eraseblock size:                 130944 bytes, 127.9 KiB
Total amount of logical eraseblocks:     486 (63638784 bytes, 60.7 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes                 128
Count of bad physical eraseblocks:       0
Count of reserved physical eraseblocks:  0
Current maximum erase counter value:     1
Minimum input/output unit size:          1 byte
Character device major/minor:            251:0
Present volumes:                         0

Volume ID:   0 (on ubi0)
Type:        dynamic
Alignment:   1
Size:        482 LEBs (63115008 bytes, 60.2 MiB)
State:       OK
Name:        rootfs
Character device major/minor: 251:1

But df reveils that the rootfs partition still is only 25MB where I had surely 
hoped for near 64MB
# df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root               120.9G     43.8G     75.9G  37% /
none                     61.3M         0     61.3M   0% /dev
none                     61.3M    116.0K     61.2M   0% /var/run
/skov/dev/sdcard1         1.8G     34.9M      1.7G   2% /skov/mnt/data
ubi0:rootfs              25.0M     11.7M     13.3M  47% /skov/mnt/ubi

It seems like the autoresize flag says: OK - you made a 25MB partition and I 
packed this down at 13MB and now I will autoresize it to 25MB again. O - so you 
have 64MB - Cool then you have additional useless empty space.

I am looking for: Ok - so I packed your partition to 13MB and format now shows 
me full 64 MB. I will autoresize to the 64MB.









----- Original Message ----
From: Artem Bityutskiy <dedekind1 at gmail.com>
To: Karsten Jeppesen <karsten at jeppesens.com>
Cc: linux-mtd at lists.infradead.org
Sent: Tue, October 19, 2010 7:12:34 AM
Subject: Re: Expanding UBI fs to maxavailable size

On Mon, 2010-10-18 at 23:22 +0200, Karsten Jeppesen wrote:
> Hi there,
> ....I think I found an error :-)
> 
> I have an ARM platform with either 32 or 64MB FLASH, and I want to make 
> an image that I can burn more or less directly (ie: not tar) into the 
> flash regardless if its the 32 or the 64MB edition.
> So I assumed that is what the autoresize flag is about, but maybe I am 
> wrong here.
> I can get ubiformat to burn the image to the flash, but subsequently the 
> filesystem doesn't expand to occupy the max available area.
> What am I doing wrong - and how is it supposed to be achieved? Or is 
> this an error or a missing feature?

What do you see in dmesg from UBI/UBIFS?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



      


From jacmet at sunsite.dk  Tue Oct 19 04:38:22 2010
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Tue, 19 Oct 2010 10:38:22 +0200
Subject: Latest mkfs.jffs2 is broken.
In-Reply-To: <1287463754.1911.0.camel@brekeke> (Artem Bityutskiy's message of
	"Tue, 19 Oct 2010 07:49:14 +0300")
References: <0D753D10438DA54287A00B02708426976450C42B27@AUSP01VMBX24.collaborationhost.net>
	<1287123245.18576.2.camel@localhost>
	<87pqvbetux.fsf@macbook.be.48ers.dk>
	<1287132218.18576.12.camel@localhost>
	<87lj5zet2y.fsf@macbook.be.48ers.dk> <1287244167.1781.2.camel@brekeke>
	<871v7n442j.fsf@macbook.be.48ers.dk> <1287463754.1911.0.camel@brekeke>
Message-ID: <87tykia875.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

 Artem> On Mon, 2010-10-18 at 22:51 +0200, Peter Korsgaard wrote:
 >> Care to fix that?

 Artem> Re-uploaded fixed tarball.

Thanks!

-- 
Bye, Peter Korsgaard


From galak at kernel.crashing.org  Tue Oct 19 09:18:30 2010
From: galak at kernel.crashing.org (Kumar Gala)
Date: Tue, 19 Oct 2010 08:18:30 -0500
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc devices
In-Reply-To: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
Message-ID: <2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>


On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:

> Move Freescale elbc interrupt from nand dirver to elbc driver.
> Then all elbc devices can use the interrupt instead of ONLY nand.
> 
> For former nand driver, it had the two functions:
> 
> 1. detecting nand flash partitions;
> 2. registering elbc interrupt.
> 
> Now, second function is removed to fsl_lbc.c.
> 
> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
> Cc: Wood Scott-B07421 <B07421 at freescale.com>
> ---

Roy, this is a nit, but are these really p4080 specific?  just wondering why the subject is P4080/eLBC:...

- k

From phdm at macqel.be  Tue Oct 19 10:24:23 2010
From: phdm at macqel.be (Philippe De Muyter)
Date: Tue, 19 Oct 2010 16:24:23 +0200
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for Lock/Unlock
	bug.
Message-ID: <1287498263-5561-1-git-send-email-phdm@macqel.be>

    Some flash chips have a small but annoying bug, documented in
    "Numonyx Axcell P33/P30 256-Mbit Specification Update"

    It states :
    When customer uses [...] block unlock, the block lock status might
    be altered inadvertently. Lock status might be set to either 01h
    or 03h unexpectedly (00h as expected data), which leads to
    program/erase failure on certain blocks.

    A workaround is given, (summary : issue a "Read Lock Status" before
    the "Lock" or "Unlock" command) which I have applied and tested
    with success.

Signed-off-by: Philippe De Muyter <phdm at macqel.be>
---
 drivers/mtd/chips/cfi_cmdset_0001.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 9e2b7e9..0d0ae41 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -2047,6 +2047,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_intelext *extp = cfi->cmdset_priv;
+	int ofs_factor = cfi->interleave * cfi->device_type;
 	int udelay;
 	int ret;
 
@@ -2062,6 +2063,14 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
 	ENABLE_VPP(map);
 	xip_disable(map, chip, adr);
 
+	/*
+	 * Issue a "Read Lock Status" before the "Lock" or "Unlock" :
+	 * see errata "Numonyx Axcell P33/P30 Specification Update" :)
+	 */
+	map_write(map, CMD(0x90), adr+(2*ofs_factor));
+	chip->state = FL_JEDEC_QUERY;
+	cfi_read_query(map, adr+(2*ofs_factor));
+
 	map_write(map, CMD(0x60), adr);
 	if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
 		map_write(map, CMD(0x01), adr);
-- 
1.7.1



From akpm at linux-foundation.org  Tue Oct 19 17:47:25 2010
From: akpm at linux-foundation.org (Andrew Morton)
Date: Tue, 19 Oct 2010 14:47:25 -0700
Subject: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
In-Reply-To: <c91308e26397dbe49f384c7d3cf168593e1fe8b0.1285933332.git.viresh.kumar@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<c91308e26397dbe49f384c7d3cf168593e1fe8b0.1285933332.git.viresh.kumar@st.com>
Message-ID: <20101019144725.977297f5.akpm@linux-foundation.org>

On Fri,  1 Oct 2010 17:26:05 +0530
Viresh KUMAR <viresh.kumar at st.com> wrote:

> From: Pratyush Anand <pratyush.anand at st.com>
> 
> This is a configurable gadget. can be configured by sysfs interface. Any
> IP available at PCIE bus can be programmed to be used by host
> controller.It supoorts both INTX and MSI.
> By default, gadget is configured for INTX and SYSRAM1 is mapped to BAR0
> with size 0x1000
> 
>
> ...
>
> +static void enable_dbi_access(struct pcie_app_reg *app_reg)

app_reg should have the __iomem tag.

> +{
> +	/* Enable DBI access */
> +	writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
> +			&app_reg->slv_armisc);
> +	writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
> +			&app_reg->slv_awmisc);
> +
> +}
> +
> +static void disable_dbi_access(struct pcie_app_reg *app_reg)

ditto

> +{
> +	/* disable DBI access */
> +	writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
> +			&app_reg->slv_armisc);
> +	writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
> +			&app_reg->slv_awmisc);
> +
> +}
> +
> +static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
> +		int where, int size, u32 *val)
> +{
> +	struct pcie_app_reg *app_reg
> +		= (struct pcie_app_reg *) config->va_app_base;

ditto

> +	u32 va_address;
> +
> +	/* Enable DBI access */
> +	enable_dbi_access(app_reg);
> +
> +	va_address = (u32)config->va_dbi_base + (where & ~0x3);
> +
> +	*val = readl(va_address);
> +
> +	if (size == 1)
> +		*val = (*val >> (8 * (where & 3))) & 0xff;
> +	else if (size == 2)
> +		*val = (*val >> (8 * (where & 3))) & 0xffff;
> +
> +	/* Disable DBI access */
> +	disable_dbi_access(app_reg);
> +}
> +
> +static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
> +		int where, int size, u32 val)
> +{
> +	struct pcie_app_reg *app_reg
> +		= (struct pcie_app_reg *) config->va_app_base;

etc.

> +	u32 va_address;
> +
> +	/* Enable DBI access */
> +	enable_dbi_access(app_reg);
> +
> +	va_address = (u32)config->va_dbi_base + (where & ~0x3);
> +
> +	if (size == 4)
> +		writel(val, va_address);
> +	else if (size == 2)
> +		writew(val, va_address + (where & 2));
> +	else if (size == 1)
> +		writeb(val, va_address + (where & 3));
> +
> +	/* Disable DBI access */
> +	disable_dbi_access(app_reg);
> +}
> +
>
> ...
>
> +/**

This token is specifically used to introduce a kerneldoc comment, but
this wasn't a kerneldoc comment.

> + * Tell if a device supports a given PCI capability.
> + * Returns the address of the requested capability structure within the
> + * device's PCI configuration space or 0 in case the device does not
> + * support it. Possible values for @cap:
> + *
> + * %PCI_CAP_ID_PM	Power Management
> + * %PCI_CAP_ID_AGP	Accelerated Graphics Port
> + * %PCI_CAP_ID_VPD	Vital Product Data
> + * %PCI_CAP_ID_SLOTID	Slot Identification
> + * %PCI_CAP_ID_MSI	Message Signalled Interrupts
> + * %PCI_CAP_ID_CHSWP	CompactPCI HotSwap
> + * %PCI_CAP_ID_PCIX	PCI-X
> + * %PCI_CAP_ID_EXP	PCI Express
> + */
>
> ...
>
> +
> +static ssize_t pcie_gadget_show_link(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;

Check all the __iomems;

> +	if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
> +		return sprintf(buf, "UP");
> +	else
> +		return sprintf(buf, "DOWN");
> +}
> +
> +static ssize_t pcie_gadget_store_link(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;
> +	char link[10];
> +
> +	if (sscanf(buf, "%s", link) != 1)

What happens if strlen(buf) >= 10?

> +		return -EINVAL;
> +
> +	if (!strcmp(link, "UP"))
> +		writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
> +			&app_reg->app_ctrl_0);
> +	else
> +		writel(readl(&app_reg->app_ctrl_0)
> +				& ~(1 << APP_LTSSM_ENABLE_ID),
> +				&app_reg->app_ctrl_0);
> +	return count;
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_store_int_type(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	char int_type[10];
> +	u32 cap, vector, vec, flags;
> +
> +	if (sscanf(buf, "%s", int_type) != 1)

ditto

> +		return -EINVAL;
> +
> +	if (!strcmp(int_type, "INTA"))
> +		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
> +
> +	else if (!strcmp(int_type, "MSI")) {
> +		vector = config->requested_msi;
> +		vec = 0;
> +		while (vector > 1) {
> +			vector /= 2;
> +			vec++;
> +		}
> +		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
> +		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
> +		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
> +		flags &= ~PCI_MSI_FLAGS_QMASK;
> +		flags |= vec << 1;
> +		spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
> +	}

No checking for unrecognised input?

> +	strcpy(config->int_type, int_type);
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR(int_type, S_IWUSR | S_IRUGO, pcie_gadget_show_int_type,
> +		pcie_gadget_store_int_type);
> +
> +static ssize_t pcie_gadget_show_no_of_msi(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;

__iomem

> +	u32 cap, vector, vec, flags;
> +
> +	if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
> +			!= (1 << CFG_MSI_EN_ID))
> +		vector = 0;
> +	else {
> +		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
> +		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
> +		flags &= ~PCI_MSI_FLAGS_QSIZE;
> +		vec = flags >> 4;
> +		vector = 1;
> +		while (vec--)
> +			vector *= 2;
> +	}
> +	config->configured_msi = vector;
> +
> +	return sprintf(buf, "%u", vector);
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_store_inta(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;
> +	int en;
> +
> +	if (sscanf(buf, "%d", &en) != 1)

strict_strtoul() would be better.  It will reject input of the form "42foo".

> +		return -EINVAL;
> +
> +	if (en)
> +		writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
> +				&app_reg->app_ctrl_0);
> +	else
> +		writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
> +				&app_reg->app_ctrl_0);
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR(inta, S_IWUSR, NULL, pcie_gadget_store_inta);
> +
> +static ssize_t pcie_gadget_store_send_msi(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;
> +	int vector;
> +	u32 ven_msi;
> +
> +	if (sscanf(buf, "%d", &vector) != 1)

strict_strtoul().

> +		return -EINVAL;
> +
> +	if (!config->configured_msi)
> +		return -EINVAL;
> +
> +	if (vector >= config->configured_msi)
> +		return -EINVAL;
> +
> +	ven_msi = readl(&app_reg->ven_msi_1);
> +	ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
> +	ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
> +	ven_msi &= ~VEN_MSI_TC_MASK;
> +	ven_msi |= 0 << VEN_MSI_TC_ID;
> +	ven_msi &= ~VEN_MSI_VECTOR_MASK;
> +	ven_msi |= vector << VEN_MSI_VECTOR_ID;
> +
> +	/*generating interrupt for msi vector*/
> +	ven_msi |= VEN_MSI_REQ_EN;
> +	writel(ven_msi, &app_reg->ven_msi_1);
> +	/*need to wait till this bit is cleared, it is not cleared
> +	 * autometically[Bug RTL] TBD*/
> +	udelay(1);
> +	ven_msi &= ~VEN_MSI_REQ_EN;
> +	writel(ven_msi, &app_reg->ven_msi_1);
> +
> +	return count;
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_store_vendor_id(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	u32 id;
> +
> +	if (sscanf(buf, "%x", &id) != 1)

strict_strtoul can be used here as well?

> +		return -EINVAL;
> +
> +	spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
> +
> +	return count;
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_store_device_id(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	u32 id;
> +
> +	if (sscanf(buf, "%x", &id) != 1)

etc.

> +		return -EINVAL;
> +
> +	spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
> +
> +	return count;
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_store_bar0_size(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	u32 size, pos, pos1;
> +	u32 no_of_bit = 0;
> +
> +	if (sscanf(buf, "%x", &size) != 1)

etc.

> +		return -EINVAL;
> +	/* as per PCIE specs, min bar size supported is 128 bytes. But
> +	 * our controller supports min as 256*/
> +	if (size <= 0x100)
> +		size = 0x100;
> +	/* max bar size is 1MB*/
> +	else if (size >= 0x100000)
> +		size = 0x100000;
> +	else {
> +		pos = 0;
> +		pos1 = 0;
> +		while (pos < 21) {
> +			pos = find_next_bit((unsigned long *)&size, 21, pos);
> +			if (pos != 21)
> +				pos1 = pos + 1;
> +			pos++;
> +			no_of_bit++;
> +		}
> +		if (no_of_bit == 2)
> +			pos1--;
> +
> +		size = 1 << pos1;
> +	}
> +	config->bar0_size = size;
> +	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
> +
> +	return count;
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_show_bar0_address(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> +	struct pcie_app_reg *app_reg =
> +		(struct pcie_app_reg *)config->va_app_base;

etc

> +	u32 address = readl(&app_reg->pim0_mem_addr_start);
> +
> +	return sprintf(buf, "%x", address);
> +}
> +
>
> ...
>
> +static ssize_t pcie_gadget_show_help(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	char text[] = "\t\tlink read->ltssm status\n \
> +		link write->arg1 = UP to enable ltsmm DOWN to disable\n \
> +		int_type read->type of supported interrupt\n \
> +		int_type write->arg1 = interrupt type to be configured and\n \
> +		can be INTA, MSI or NO_INT\n \
> +		(select MSI only when you have programmed no_of_msi)\n \
> +		no_of_msi read->zero if MSI is not enabled by host\n \
> +		and positive value is the number of MSI vector granted\n \
> +		no_of_msi write->arg1 = number of MSI vector needed\n \
> +		inta write->arg1 = 1 to assert INTA and 0 to de-assert\n \
> +		send_msi write->arg1 = MSI vector to be send\n \
> +		vendor_id read->programmed vendor id (hex)\n\
> +		vendor_id write->arg1 = vendor id(hex) to be programmed\n \
> +		device_id read->programmed device id(hex)\n \
> +		device_id write->arg1 = device id(hex) to be programmed\n \
> +		bar0_size read->size of bar0 in hex\n \
> +		bar0_size write->arg1= size of bar0 in hex\n \
> +		(default bar0 size is 1000 (hex) bytes)\n \
> +		bar0_address read->address of bar0 mapped area in hex\n \
> +		bar0_address write->arg1 = address of bar0 mapped area in hex\n\
> +		(default mapping of bar0 is SYSRAM1(E0800000)\n \
> +		(always program bar size before bar address)\n \
> +		(kernel might modify bar size and address to align)\n \
> +		(read back bar size and address after writing to check)\n \
> +		bar0_rw_offset read->offset of bar0 for which bar0_data \n \
> +		will return value\n \
> +		bar0_rw_offset write->arg1 = offset of bar0 for which\n \
> +		bar0_data will write value\n \
> +		bar0_data read->data at bar0_rw_offset\n \
> +		bar0_data write->arg1 = data to be written at\n \
> +		bar0_rw_offset\n";
> +
> +	int size = (sizeof(text) < PAGE_SIZE) ? sizeof(text) : PAGE_SIZE;
> +
> +	return snprintf(buf, size, "%s", text);
> +}

What the heck is this??

> +static DEVICE_ATTR(help, S_IRUGO, pcie_gadget_show_help, NULL);
> +
> +static struct attribute *pcie_gadget_attributes[] = {
> +	&dev_attr_link.attr,
> +	&dev_attr_int_type.attr,
> +	&dev_attr_no_of_msi.attr,
> +	&dev_attr_inta.attr,
> +	&dev_attr_send_msi.attr,
> +	&dev_attr_vendor_id.attr,
> +	&dev_attr_device_id.attr,
> +	&dev_attr_bar0_size.attr,
> +	&dev_attr_bar0_address.attr,
> +	&dev_attr_bar0_rw_offset.attr,
> +	&dev_attr_bar0_data.attr,
> +	&dev_attr_help.attr,
> +	NULL
> +};
> +
>
> ...
>
> +static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
> +{
> +	struct resource *res0, *res1;
> +	struct spear_pcie_gadget_config *config;
> +	unsigned int status = 0;
> +	int irq;
> +	struct clk *clk;
> +
> +	/* get resource for application registers*/
> +
> +	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res0) {
> +		dev_err(&pdev->dev, "no resource defined\n");
> +		return -EBUSY;
> +	}
> +	if (!request_mem_region(res0->start, resource_size(res0),
> +				pdev->name)) {
> +		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
> +		return -EBUSY;
> +	}
> +	/* get resource for dbi registers*/
> +
> +	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!res1) {
> +		dev_err(&pdev->dev, "no resource defined\n");
> +		goto err_rel_res0;
> +	}
> +	if (!request_mem_region(res1->start, resource_size(res1),
> +				pdev->name)) {
> +		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
> +		goto err_rel_res0;
> +	}
> +
> +	config = kzalloc(sizeof(*config), GFP_KERNEL);
> +	if (!config) {
> +		dev_err(&pdev->dev, "out of memory\n");
> +		status = -ENOMEM;
> +		goto err_rel_res;
> +	}
> +
> +	config->va_app_base = ioremap(res0->start, resource_size(res0));
> +	if (!config->va_app_base) {
> +		dev_err(&pdev->dev, "ioremap fail\n");
> +		status = -ENOMEM;
> +		goto err_kzalloc;
> +	}
> +
> +	config->base = (void *)res1->start;

Is that __iomem?

> +	config->va_dbi_base = ioremap(res1->start, resource_size(res1));
> +	if (!config->va_dbi_base) {
> +		dev_err(&pdev->dev, "ioremap fail\n");
> +		status = -ENOMEM;
> +		goto err_iounmap_app;
> +	}
> +
> +	dev_set_drvdata(&pdev->dev, config);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0) {
> +		dev_err(&pdev->dev, "no update irq?\n");
> +		status = irq;
> +		goto err_iounmap;
> +	}
> +
> +	status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
> +	if (status) {
> +		dev_err(&pdev->dev, "pcie gadget interrupt IRQ%d already \
> +				claimed\n", irq);
> +		goto err_get_irq;
> +	}
> +	/* Register sysfs hooks */
> +	status = sysfs_create_group(&pdev->dev.kobj, &pcie_gadget_attr_group);
> +	if (status)
> +		goto err_irq;
> +
> +	/* init basic pcie application registers*/
> +	/* do not enable clock if it is PCIE0.Ideally , all controller should
> +	 * have been independent from others with respect to clock. But PCIE1
> +	 * and 2 depends on PCIE0.So PCIE0 clk is provided during board init.*/
> +	if (pdev->id == 1) {
> +		/* Ideally CFG Clock should have been also enabled here. But
> +		 * it is done currently during board init routne*/
> +		clk = clk_get_sys("pcie1", NULL);
> +		if (!clk) {
> +			pr_err("%s:couldn't get clk for pcie1\n", __func__);
> +			goto err_irq;
> +		}
> +		if (clk_enable(clk)) {
> +			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
> +			goto err_irq;
> +		}
> +	} else if (pdev->id == 2) {
> +		/* Ideally CFG Clock should have been also enabled here. But
> +		 * it is done currently during board init routne*/
> +		clk = clk_get_sys("pcie2", NULL);
> +		if (!clk) {
> +			pr_err("%s:couldn't get clk for pcie2\n", __func__);
> +			goto err_irq;
> +		}
> +		if (clk_enable(clk)) {
> +			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
> +			goto err_irq;
> +		}
> +	}
> +	spear13xx_pcie_device_init(config);
> +
> +	return 0;
> +err_irq:
> +	free_irq(irq, NULL);
> +err_get_irq:
> +	dev_set_drvdata(&pdev->dev, NULL);
> +err_iounmap:
> +	iounmap(config->va_dbi_base);
> +err_iounmap_app:
> +	iounmap(config->va_app_base);
> +err_kzalloc:
> +	kfree(config);
> +err_rel_res:
> +	release_mem_region(res1->start, resource_size(res1));
> +err_rel_res0:
> +	release_mem_region(res0->start, resource_size(res0));
> +	return status;
> +}
> +
>
> ...
>

The driver implements a large, complex userspace interface and afaict
that interface wasn't documented anywhere. 

But the interface is the most important part of the driver!  It should
be documented in a permanent fashion so that reviewers can understand
and review your proposed interface.  They will want to do that before
even looking at the code.


From r61911 at freescale.com  Wed Oct 20 01:12:20 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Wed, 20 Oct 2010 13:12:20 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc devices
In-Reply-To: <2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B08A5@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Kumar Gala [mailto:galak at kernel.crashing.org]
> Sent: Tuesday, October 19, 2010 21:19 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421;
dedekind1 at gmail.com; Lan
> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
> dwmw2 at infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
common to
> elbc devices
> 
> 
> On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:
> 
> > Move Freescale elbc interrupt from nand dirver to elbc driver.
> > Then all elbc devices can use the interrupt instead of ONLY nand.
> >
> > For former nand driver, it had the two functions:
> >
> > 1. detecting nand flash partitions;
> > 2. registering elbc interrupt.
> >
> > Now, second function is removed to fsl_lbc.c.
> >
> > Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
> > Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
> > Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
> > Cc: Wood Scott-B07421 <B07421 at freescale.com>
> > ---
> 
> Roy, this is a nit, but are these really p4080 specific?  just
wondering why
> the subject is P4080/eLBC:...
We start these code in P4080 project. Some customer want to track eLBC
error on P4080, but some of the code is limited in nand driver only ...
That is why P4080/eLBC ...
Roy



From computersforpeace at gmail.com  Wed Oct 20 02:45:24 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 19 Oct 2010 23:45:24 -0700
Subject: [PATCH 1/2] mtd-utils: more style fixups
Message-ID: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c  |    7 +++----
 nandwrite.c |    6 +++---
 2 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index bb649da..6428bc4 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -308,7 +308,7 @@ int main(int argc, char * const argv[])
 	oob.ptr = oobbuf;
 
 	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
+		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
 		if (ret == 0) {
 			oobinfochanged = 2;
 		} else {
@@ -330,7 +330,6 @@ int main(int argc, char * const argv[])
 			}
 		}
 	} else {
-
 		/* check if we can read ecc stats */
 		if (!ioctl(fd, ECCGETSTATS, &stat1)) {
 			eccstats = true;
@@ -375,7 +374,6 @@ int main(int argc, char * const argv[])
 	bs = meminfo.writesize;
 
 	/* Print informative message */
-
 	if (!quiet) {
 		fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
 				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
@@ -383,6 +381,7 @@ int main(int argc, char * const argv[])
 				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
 				(unsigned int)start_addr, (unsigned int)end_addr);
 	}
+
 	/* Dump the flash contents */
 	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
 		/* Check for bad block */
@@ -401,7 +400,7 @@ int main(int argc, char * const argv[])
 		if (badblock) {
 			if (omitbad)
 				continue;
-			memset (readbuf, 0xff, bs);
+			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
 			if (pread(fd, readbuf, bs, ofs) != bs) {
diff --git a/nandwrite.c b/nandwrite.c
index b5745b9..fe03115 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -592,14 +592,14 @@ int main(int argc, char * const argv[])
 				int i, start, len;
 				int tags_pos = 0;
 				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
+				 * We use autoplacement and have the oobinfo with the autoplacement
 				 * information from the kernel available
 				 *
 				 * Modified to support out of order oobfree segments,
 				 * such as the layout used by diskonchip.c
 				 */
 				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
+					for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
 						/* Set the reserved bytes to 0xff */
 						start = old_oobinfo.oobfree[i][0];
 						len = old_oobinfo.oobfree[i][1];
@@ -620,7 +620,7 @@ int main(int argc, char * const argv[])
 							len);
 				}
 			}
-			/* Write OOB data first, as ecc will be placed in there*/
+			/* Write OOB data first, as ecc will be placed in there */
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
 				perror("ioctl(MEMWRITEOOB)");
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Oct 20 02:45:25 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 19 Oct 2010 23:45:25 -0700
Subject: [PATCH 2/2] mtd-utils: nanddump: add 64-bit support, utilize
 libmtd
In-Reply-To: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
References: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287557125-2672-2-git-send-email-computersforpeace@gmail.com>

Adds support for 64-bit offsets (i.e., devices larger than 4GB).
Calls to ioctls are mostly replaced by libmtd interfaces; however,
a few remain and probably should be handled with more robust
interfaces, as some of these ioctls are considered "legacy."

Similar updates to nandwrite will come shortly.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c  |  117 +++++++++++++++++++++++++++++------------------------------
 nandwrite.c |    7 ++--
 2 files changed, 60 insertions(+), 64 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 6428bc4..55dbd37 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -33,6 +33,7 @@
 #include <asm/types.h>
 #include <mtd/mtd-user.h>
 #include "common.h"
+#include <libmtd.h>
 
 static struct nand_oobinfo none_oobinfo = {
 	.useecc = MTD_NANDECC_OFF,
@@ -77,18 +78,18 @@ static void display_version(void)
 
 // Option variables
 
-static bool		pretty_print = false;	// print nice
-static bool		noecc = false;		// don't error correct
-static bool		noskipbad = false;	// don't skip bad blocks
-static bool		omitoob = false;	// omit oob data
-static unsigned long	start_addr;		// start address
-static unsigned long	length;			// dump length
-static const char	*mtddev;		// mtd device name
-static const char	*dumpfile;		// dump file name
-static bool		omitbad = false;
-static bool		quiet = false;		// suppress diagnostic output
-static bool		canonical = false;	// print nice + ascii
-static bool		forcebinary = false;	// force printing binary to tty
+static bool			pretty_print = false;	// print nice
+static bool			noecc = false;		// don't error correct
+static bool			noskipbad = false;	// don't skip bad blocks
+static bool			omitoob = false;	// omit oob data
+static unsigned long long	start_addr;		// start address
+static unsigned long		length;			// dump length
+static const char		*mtddev;		// mtd device name
+static const char		*dumpfile;		// dump file name
+static bool			omitbad = false;
+static bool			quiet = false;		// suppress diagnostic output
+static bool			canonical = false;	// print nice + ascii
+static bool			forcebinary = false;	// force printing binary to tty
 
 static void process_options(int argc, char * const argv[])
 {
@@ -135,7 +136,7 @@ static void process_options(int argc, char * const argv[])
 				omitbad = true;
 				break;
 			case 's':
-				start_addr = strtol(optarg, NULL, 0);
+				start_addr = strtoull(optarg, NULL, 0);
 				break;
 			case 'f':
 				if (!(dumpfile = strdup(optarg))) {
@@ -221,18 +222,16 @@ static void process_options(int argc, char * const argv[])
  */
 static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
 		char *linebuf, size_t linebuflen, bool pagedump, bool ascii,
-		unsigned int prefix)
+		unsigned long long prefix)
 {
 	static const char hex_asc[] = "0123456789abcdef";
 	unsigned char ch;
-	int j, lx = 0;
-	int ascii_column;
+	unsigned int j, lx = 0, ascii_column;
 
 	if (pagedump)
-		sprintf(linebuf, "0x%.8x: ", prefix);
+		lx += sprintf(linebuf, "0x%.8llx: ", prefix);
 	else
-		sprintf(linebuf, "  OOB Data: ");
-	lx += 12;
+		lx += sprintf(linebuf, "  OOB Data: ");
 
 	if (!len)
 		goto nil;
@@ -253,8 +252,10 @@ static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
 	if (!ascii)
 		goto nil;
 
-	while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
+	do {
 		linebuf[lx++] = ' ';
+	} while (lx < (linebuflen - 1) && lx < (ascii_column - 1));
+
 	linebuf[lx++] = '|';
 	for (j = 0; (j < len) && (lx + 2) < linebuflen; j++)
 		linebuf[lx++] = (isascii(buf[j]) && isprint(buf[j])) ? buf[j]
@@ -271,20 +272,25 @@ nil:
  */
 int main(int argc, char * const argv[])
 {
-	unsigned long ofs, end_addr = 0;
+	unsigned long long ofs, end_addr = 0;
 	unsigned long long blockstart = 1;
 	int ret, i, fd, ofd = 0, bs, badblock = 0;
-	struct mtd_oob_buf oob;
-	mtd_info_t meminfo;
+	struct mtd_dev_info mtd;
 	char pretty_buf[PRETTY_BUF_LEN];
 	int oobinfochanged = 0, firstblock = 1;
 	struct nand_oobinfo old_oobinfo;
 	struct mtd_ecc_stats stat1, stat2;
 	bool eccstats = false;
 	unsigned char *readbuf = NULL, *oobbuf = NULL;
+	libmtd_t mtd_desc;
 
 	process_options(argc, argv);
 
+	/* Initialize libmtd */
+	mtd_desc = libmtd_open();
+	if (!mtd_desc)
+		return errmsg("can't initialize libmtd");
+
 	/* Open MTD device */
 	if ((fd = open(mtddev, O_RDONLY)) == -1) {
 		perror(mtddev);
@@ -292,20 +298,12 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
+	if (mtd_get_dev_info(mtd_desc, mtddev, &mtd) < 0)
+		return errmsg("mtd_get_dev_info failed");
 
 	/* Allocate buffers */
-	oobbuf = xmalloc(sizeof(oobbuf) * meminfo.oobsize);
-	readbuf = xmalloc(sizeof(readbuf) * meminfo.writesize);
-
-	/* Fill in oob info */
-	oob.start = 0;
-	oob.length = meminfo.oobsize;
-	oob.ptr = oobbuf;
+	oobbuf = xmalloc(sizeof(oobbuf) * mtd.oob_size);
+	readbuf = xmalloc(sizeof(readbuf) * mtd.min_io_size);
 
 	if (noecc)  {
 		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
@@ -359,27 +357,27 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Initialize start/end addresses and block size */
-	if (start_addr & (meminfo.writesize - 1)) {
+	if (start_addr & (mtd.min_io_size - 1)) {
 		fprintf(stderr, "WARNING: The start address is not page-aligned !\n"
 				"The pagesize of this NAND Flash is 0x%x.\n"
 				"nandwrite doesn't allow writes starting at this location.\n"
 				"Future versions of nanddump will fail here.\n",
-				meminfo.writesize);
+				mtd.min_io_size);
 	}
 	if (length)
 		end_addr = start_addr + length;
-	if (!length || end_addr > meminfo.size)
-		end_addr = meminfo.size;
+	if (!length || end_addr > mtd.size)
+		end_addr = mtd.size;
 
-	bs = meminfo.writesize;
+	bs = mtd.min_io_size;
 
 	/* Print informative message */
 	if (!quiet) {
 		fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
-				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
+				mtd.eb_size, mtd.min_io_size, mtd.oob_size);
 		fprintf(stderr,
-				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
-				(unsigned int)start_addr, (unsigned int)end_addr);
+				"Dumping data starting at 0x%08llx and ending at 0x%08llx...\n",
+				start_addr, end_addr);
 	}
 
 	/* Dump the flash contents */
@@ -387,12 +385,12 @@ int main(int argc, char * const argv[])
 		/* Check for bad block */
 		if (noskipbad) {
 			badblock = 0;
-		} else if (blockstart != (ofs & (~meminfo.erasesize + 1)) ||
+		} else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
 				firstblock) {
-			blockstart = ofs & (~meminfo.erasesize + 1);
+			blockstart = ofs & (~mtd.eb_size + 1);
 			firstblock = 0;
-			if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
-				perror("ioctl(MEMGETBADBLOCK)");
+			if ((badblock = mtd_is_bad(&mtd, fd, ofs / mtd.eb_size)) < 0) {
+				errmsg("libmtd: mtd_is_bad");
 				goto closeall;
 			}
 		}
@@ -403,8 +401,8 @@ int main(int argc, char * const argv[])
 			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
-			if (pread(fd, readbuf, bs, ofs) != bs) {
-				perror("pread");
+			if (mtd_read(&mtd, fd, ofs / mtd.eb_size, ofs % mtd.eb_size, readbuf, bs)) {
+				errmsg("mtd_read");
 				goto closeall;
 			}
 		}
@@ -417,11 +415,11 @@ int main(int argc, char * const argv[])
 			}
 			if (stat1.failed != stat2.failed)
 				fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
-						" at offset 0x%08lx\n",
+						" at offset 0x%08llx\n",
 						stat2.failed - stat1.failed, ofs);
 			if (stat1.corrected != stat2.corrected)
 				fprintf(stderr, "ECC: %d corrected bitflip(s) at"
-						" offset 0x%08lx\n",
+						" offset 0x%08llx\n",
 						stat2.corrected - stat1.corrected, ofs);
 			stat1 = stat2;
 		}
@@ -429,8 +427,8 @@ int main(int argc, char * const argv[])
 		/* Write out page data */
 		if (pretty_print) {
 			for (i = 0; i < bs; i += PRETTY_ROW_SIZE) {
-				pretty_dump_to_buffer(readbuf+i, PRETTY_ROW_SIZE,
-						pretty_buf, PRETTY_BUF_LEN, true, canonical, ofs+i);
+				pretty_dump_to_buffer(readbuf + i, PRETTY_ROW_SIZE,
+						pretty_buf, PRETTY_BUF_LEN, true, canonical, ofs + i);
 				write(ofd, pretty_buf, strlen(pretty_buf));
 			}
 		} else
@@ -440,25 +438,24 @@ int main(int argc, char * const argv[])
 			continue;
 
 		if (badblock) {
-			memset(oobbuf, 0xff, meminfo.oobsize);
+			memset(oobbuf, 0xff, mtd.oob_size);
 		} else {
 			/* Read OOB data and exit on failure */
-			oob.start = ofs;
-			if (ioctl(fd, MEMREADOOB, &oob) != 0) {
-				perror("ioctl(MEMREADOOB)");
+			if (mtd_read_oob(mtd_desc, &mtd, fd, ofs, mtd.oob_size, oobbuf)) {
+				errmsg("libmtd: mtd_read_oob");
 				goto closeall;
 			}
 		}
 
 		/* Write out OOB data */
 		if (pretty_print) {
-			for (i = 0; i < meminfo.oobsize; i += 16) {
-				pretty_dump_to_buffer(oobbuf+i, meminfo.oobsize-i,
+			for (i = 0; i < mtd.oob_size; i += 16) {
+				pretty_dump_to_buffer(oobbuf + i, mtd.oob_size - i,
 						pretty_buf, PRETTY_BUF_LEN, false, canonical, 0);
 				write(ofd, pretty_buf, strlen(pretty_buf));
 			}
 		} else
-			write(ofd, oobbuf, meminfo.oobsize);
+			write(ofd, oobbuf, mtd.oob_size);
 	}
 
 	/* reset oobinfo */
diff --git a/nandwrite.c b/nandwrite.c
index fe03115..9eb63a4 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -108,7 +108,7 @@ static void display_version(void)
 
 static const char	*standard_input = "-";
 static const char	*mtd_device, *img;
-static int		mtdoffset = 0;
+static unsigned int	mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		rawoob = false;
@@ -200,7 +200,7 @@ static void process_options(int argc, char * const argv[])
 				writeoob = true;
 				break;
 			case 's':
-				mtdoffset = strtol(optarg, NULL, 0);
+				mtdoffset = strtoul(optarg, NULL, 0);
 				break;
 			case 'b':
 				blockalign = atoi(optarg);
@@ -318,7 +318,6 @@ int main(int argc, char * const argv[])
 
 		// autoplace ECC ?
 		if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
-
 			if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
 				perror("MEMSETOOBSEL");
 				close(fd);
@@ -480,7 +479,7 @@ int main(int argc, char * const argv[])
 			if (noskipbad)
 				continue;
 			do {
-				if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
+				if ((ret = 0 /*ioctl(fd, MEMGETBADBLOCK, &offs)*/) < 0) {
 					perror("ioctl(MEMGETBADBLOCK)");
 					goto closeall;
 				}
-- 
1.7.0.4




From galak at kernel.crashing.org  Wed Oct 20 02:54:53 2010
From: galak at kernel.crashing.org (Kumar Gala)
Date: Wed, 20 Oct 2010 01:54:53 -0500
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc devices
In-Reply-To: <3850A844E6A3854C827AC5C0BEC7B60A2B08A5@zch01exm23.fsl.freescale.net>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>
	<3850A844E6A3854C827AC5C0BEC7B60A2B08A5@zch01exm23.fsl.freescale.net>
Message-ID: <707F7370-D01B-462F-B896-D7F677AED8EB@kernel.crashing.org>


On Oct 20, 2010, at 12:12 AM, Zang Roy-R61911 wrote:

> 
> 
>> -----Original Message-----
>> From: Kumar Gala [mailto:galak at kernel.crashing.org]
>> Sent: Tuesday, October 19, 2010 21:19 PM
>> To: Zang Roy-R61911
>> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421;
> dedekind1 at gmail.com; Lan
>> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
>> dwmw2 at infradead.org; Gala Kumar-B11780
>> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
> common to
>> elbc devices
>> 
>> 
>> On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:
>> 
>>> Move Freescale elbc interrupt from nand dirver to elbc driver.
>>> Then all elbc devices can use the interrupt instead of ONLY nand.
>>> 
>>> For former nand driver, it had the two functions:
>>> 
>>> 1. detecting nand flash partitions;
>>> 2. registering elbc interrupt.
>>> 
>>> Now, second function is removed to fsl_lbc.c.
>>> 
>>> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
>>> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
>>> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
>>> Cc: Wood Scott-B07421 <B07421 at freescale.com>
>>> ---
>> 
>> Roy, this is a nit, but are these really p4080 specific?  just
> wondering why
>> the subject is P4080/eLBC:...
> We start these code in P4080 project. Some customer want to track eLBC
> error on P4080, but some of the code is limited in nand driver only ...
> That is why P4080/eLBC ...
> Roy

sure, but is anything about these patches p4080 specific?

- k



From vapier.adi at gmail.com  Wed Oct 20 02:58:37 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 20 Oct 2010 02:58:37 -0400
Subject: [PATCH 1/2] mtd-utils: more style fixups
In-Reply-To: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
References: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTinHRsvyH30UcCQZWKihHCPivDz8C0-9J+fLdciF@mail.gmail.com>

On Wed, Oct 20, 2010 at 02:45, Brian Norris wrote:
> - ? ? ? ? ? ? ? ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
> + ? ? ? ? ? ? ? ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);

i'd just drop the cast completely.  ioctl() is a vararg func so there
is no need to tweak the type.
-mike


From vapier.adi at gmail.com  Wed Oct 20 03:01:45 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 20 Oct 2010 03:01:45 -0400
Subject: [PATCH 2/2] mtd-utils: nanddump: add 64-bit support,
	utilize libmtd
In-Reply-To: <1287557125-2672-2-git-send-email-computersforpeace@gmail.com>
References: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
	<1287557125-2672-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>

On Wed, Oct 20, 2010 at 02:45, Brian Norris wrote:
> -static bool ? ? ? ? ? ?pretty_print = false; ? // print nice
> -static bool ? ? ? ? ? ?noecc = false; ? ? ? ? ?// don't error correct
> -static bool ? ? ? ? ? ?noskipbad = false; ? ? ?// don't skip bad blocks
> -static bool ? ? ? ? ? ?omitoob = false; ? ? ? ?// omit oob data
> -static unsigned long ? start_addr; ? ? ? ? ? ? // start address
> -static unsigned long ? length; ? ? ? ? ? ? ? ? // dump length
> -static const char ? ? ?*mtddev; ? ? ? ? ? ? ? ?// mtd device name
> -static const char ? ? ?*dumpfile; ? ? ? ? ? ? ?// dump file name
> -static bool ? ? ? ? ? ?omitbad = false;
> -static bool ? ? ? ? ? ?quiet = false; ? ? ? ? ?// suppress diagnostic output
> -static bool ? ? ? ? ? ?canonical = false; ? ? ?// print nice + ascii
> -static bool ? ? ? ? ? ?forcebinary = false; ? ?// force printing binary to tty
> +static bool ? ? ? ? ? ? ? ? ? ?pretty_print = false; ? // print nice
> +static bool ? ? ? ? ? ? ? ? ? ?noecc = false; ? ? ? ? ?// don't error correct
> +static bool ? ? ? ? ? ? ? ? ? ?noskipbad = false; ? ? ?// don't skip bad blocks
> +static bool ? ? ? ? ? ? ? ? ? ?omitoob = false; ? ? ? ?// omit oob data
> +static unsigned long long ? ? ?start_addr; ? ? ? ? ? ? // start address
> +static unsigned long ? ? ? ? ? length; ? ? ? ? ? ? ? ? // dump length
> +static const char ? ? ? ? ? ? ?*mtddev; ? ? ? ? ? ? ? ?// mtd device name
> +static const char ? ? ? ? ? ? ?*dumpfile; ? ? ? ? ? ? ?// dump file name
> +static bool ? ? ? ? ? ? ? ? ? ?omitbad = false;
> +static bool ? ? ? ? ? ? ? ? ? ?quiet = false; ? ? ? ? ?// suppress diagnostic output
> +static bool ? ? ? ? ? ? ? ? ? ?canonical = false; ? ? ?// print nice + ascii
> +static bool ? ? ? ? ? ? ? ? ? ?forcebinary = false; ? ?// force printing binary to tty

only one of these lines are functional.  please fold the rest into
your "style fixup" patch.

> @@ -318,7 +318,6 @@ int main(int argc, char * const argv[])
>
> ? ? ? ? ? ? ? ?// autoplace ECC ?
> ? ? ? ? ? ? ? ?if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
> -
> ? ? ? ? ? ? ? ? ? ? ? ?if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("MEMSETOOBSEL");
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?close(fd);

same here

> @@ -480,7 +479,7 @@ int main(int argc, char * const argv[])
> ? ? ? ? ? ? ? ? ? ? ? ?if (noskipbad)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?continue;
> ? ? ? ? ? ? ? ? ? ? ? ?do {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if ((ret = 0 /*ioctl(fd, MEMGETBADBLOCK, &offs)*/) < 0) {
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("ioctl(MEMGETBADBLOCK)");
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto closeall;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?}

doesnt seem to belong.  then again, none of the changes to this file
look like they belong in this patch.
-mike

From kmpark at infradead.org  Wed Oct 20 04:31:02 2010
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 20 Oct 2010 17:31:02 +0900
Subject: [PATCH] mtd: OneNAND: S5PC110: Fix double call suspend & resume
	function
Message-ID: <20101020083102.GA30414@july>

From: Kyungmin Park <kyungmin.park at samsung.com>

The suspend & resume called from mtd core. So no need to call at driver.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 214ed1e..0de7a05 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -1098,7 +1098,7 @@ static int s3c_pm_ops_suspend(struct device *dev)
 	struct onenand_chip *this = mtd->priv;
 
 	this->wait(mtd, FL_PM_SUSPENDED);
-	return mtd->suspend(mtd);
+	return 0;
 }
 
 static  int s3c_pm_ops_resume(struct device *dev)
@@ -1107,7 +1107,6 @@ static  int s3c_pm_ops_resume(struct device *dev)
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 	struct onenand_chip *this = mtd->priv;
 
-	mtd->resume(mtd);
 	this->unlock_all(mtd);
 	return 0;
 }


From r61911 at freescale.com  Wed Oct 20 04:33:23 2010
From: r61911 at freescale.com (Zang Roy-R61911)
Date: Wed, 20 Oct 2010 16:33:23 +0800
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common to
	elbc devices
In-Reply-To: <707F7370-D01B-462F-B896-D7F677AED8EB@kernel.crashing.org>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<2D2A6B88-DA17-467D-BB43-919C1CAAB894@kernel.crashing.org>
	<3850A844E6A3854C827AC5C0BEC7B60A2B08A5@zch01exm23.fsl.freescale.net>
	<707F7370-D01B-462F-B896-D7F677AED8EB@kernel.crashing.org>
Message-ID: <3850A844E6A3854C827AC5C0BEC7B60A2B090E@zch01exm23.fsl.freescale.net>



> -----Original Message-----
> From: Kumar Gala [mailto:galak at kernel.crashing.org]
> Sent: Wednesday, October 20, 2010 14:55 PM
> To: Zang Roy-R61911
> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421;
dedekind1 at gmail.com; Lan
> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
> dwmw2 at infradead.org; Gala Kumar-B11780
> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
common to
> elbc devices
> 
> 
> On Oct 20, 2010, at 12:12 AM, Zang Roy-R61911 wrote:
> 
> >
> >
> >> -----Original Message-----
> >> From: Kumar Gala [mailto:galak at kernel.crashing.org]
> >> Sent: Tuesday, October 19, 2010 21:19 PM
> >> To: Zang Roy-R61911
> >> Cc: linux-mtd at lists.infradead.org; Wood Scott-B07421;
> > dedekind1 at gmail.com; Lan
> >> Chunhe-B25806; linuxppc-dev at ozlabs.org; akpm at linux-foundation.org;
> >> dwmw2 at infradead.org; Gala Kumar-B11780
> >> Subject: Re: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt
> > common to
> >> elbc devices
> >>
> >>
> >> On Oct 18, 2010, at 2:22 AM, Roy Zang wrote:
> >>
> >>> Move Freescale elbc interrupt from nand dirver to elbc driver.
> >>> Then all elbc devices can use the interrupt instead of ONLY nand.
> >>>
> >>> For former nand driver, it had the two functions:
> >>>
> >>> 1. detecting nand flash partitions;
> >>> 2. registering elbc interrupt.
> >>>
> >>> Now, second function is removed to fsl_lbc.c.
> >>>
> >>> Signed-off-by: Lan Chunhe-B25806 <b25806 at freescale.com>
> >>> Signed-off-by: Roy Zang <tie-fei.zang at freescale.com>
> >>> Reviewed-by: Anton Vorontsov <cbouatmailru at gmail.com>
> >>> Cc: Wood Scott-B07421 <B07421 at freescale.com>
> >>> ---
> >>
> >> Roy, this is a nit, but are these really p4080 specific?  just
> > wondering why
> >> the subject is P4080/eLBC:...
> > We start these code in P4080 project. Some customer want to track
eLBC
> > error on P4080, but some of the code is limited in nand driver only
...
> > That is why P4080/eLBC ...
> > Roy
> 
> sure, but is anything about these patches p4080 specific?
No.
Should I update the subject by a new version.
Thanks.
Roy



From dedekind1 at gmail.com  Wed Oct 20 05:07:16 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 20 Oct 2010 12:07:16 +0300
Subject: [PATCH 3/3] UBI: tighten the corrupted PEB criteria
In-Reply-To: <1287565636-18825-1-git-send-email-dedekind1@gmail.com>
References: <1287565636-18825-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1287565636-18825-3-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

If we get a bit-flip of ECC error while reading the data area, do not add it to
corrupted list, because it is possible that this is just unstable PEB with
corruptions caused by unclean reboots.

This patch also improves commentaries.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/ubi/scan.c |   41 ++++++++++++++++++++++++++++++++---------
 1 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index e7b800b..c1191b7 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -45,14 +45,26 @@
  *    many warnings and error messages. The idea is that we do not lose
  *    important data in these case - we may lose only the data which was being
  *    written to the media just before the power cut happened, and the upper
- *    layers are supposed to handle these situations. UBI puts these PEBs to
- *    the head of the @erase list and they are scheduled for erasure.
+ *    layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
+ *    these PEBs to the head of the @erase list and they are scheduled for
+ *    erasure.
  *
  * 2. Unexpected corruptions which are not caused by power cuts. During
  *    scanning, such PEBs are put to the @corr list and UBI preserves them.
  *    Obviously, this lessens the amount of available PEBs, and if at some
  *    point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
  *    informs about such PEBs every time the MTD device is attached.
+ *
+ * However, it is difficult to reliably distinguish between these types of
+ * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
+ * header is corrupted and the data area does not contain all 0xFFs, and there
+ * were not bit-flips or integrity errors while reading the data area. Otherwise
+ * UBI assumes (1.). The assumptions are:
+ *   o if the data area contains only 0xFFs, there is no data, and it is safe
+ *     to just erase this PEB.
+ *   o if the data area has bit-flips and data integrity errors (ECC errors on
+ *     NAND), it is probably a PEB which was being erased when power cut
+ *     happened.
  */
 
 #include <linux/err.h>
@@ -741,23 +753,23 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
 }
 
 /**
- * check_data_ff - make sure PEB contains only 0xFF data.
+ * check_corruption - check the data area of PEB.
  * @ubi: UBI device description object
  * @vid_hrd: the (corrupted) VID header of this PEB
  * @pnum: the physical eraseblock number to check
  *
  * This is a helper function which is used to distinguish between VID header
  * corruptions caused by power cuts and other reasons. If the PEB contains only
- * 0xFF bytes at the data area, the VID header is most probably corrupted
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
  * because of a power cut (%0 is returned in this case). Otherwise, it was
- * corrupted for some other reasons (%1 is returned in this case). A negative
- * error code is returned if a read error occurred.
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
  *
  * If the corruption reason was a power cut, UBI can safely erase this PEB.
  * Otherwise, it should preserve it to avoid possibly destroying important
  * information.
  */
-static int check_data_ff(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
 			 int pnum)
 {
 	int err;
@@ -767,7 +779,18 @@ static int check_data_ff(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
 
 	err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
 			  ubi->leb_size);
-	if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+	if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+		/*
+		 * Bit-flips or integrity errors while reading the data area.
+		 * It is difficult to say for sure what type of corruption is
+		 * this, but presumably a power cut happened while this PEB was
+		 * erased, so it became unstable and corrupted, and should be
+		 * erased.
+		 */
+		return 0;
+	}
+
+	if (err)
 		return err;
 
 	if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
@@ -926,7 +949,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 			 * that this a valid UBI PEB which has corresponding
 			 * LEB, but the headers are corrupted. However, it is
 			 * impossible to distinguish it from a PEB which just
-			 * contains garbage because a power cut during erase
+			 * contains garbage because of a power cut during erase
 			 * operation. So we just schedule this PEB for erasure.
 			 */
 			err = 0;
-- 
1.7.2.3



From dedekind1 at gmail.com  Wed Oct 20 05:07:14 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 20 Oct 2010 12:07:14 +0300
Subject: [PATCH 1/3] UBI: remember copy_flag while scanning
Message-ID: <1287565636-18825-1-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

While scanning the flash we read all VID headers and store some important
information in 'struct ubi_scan_leb'. Store also the 'copy_flag' value there
as it is needed when comparing LEBs. We do not increase memory consumption
because this is just one bit and we have plenty of spare bits in
'struct ubi_scan_leb' (sizeof(struct ubi_scan_leb) is 48 both with and
without this patch).

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/ubi/scan.c |   20 ++++++++++----------
 drivers/mtd/ubi/scan.h |    4 +++-
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 30b7102..2fbb571 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -330,12 +330,18 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
 			return 1;
 		}
 	} else {
-		pnum = seb->pnum;
+		if (!seb->copy_flag) {
+			/* It is not a copy, so it is newer */
+			dbg_bld("first PEB %d is newer, copy_flag is unset",
+				pnum);
+			return bitflips << 1;
+		}
 
 		vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 		if (!vh)
 			return -ENOMEM;
 
+		pnum = seb->pnum;
 		err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
 		if (err) {
 			if (err == UBI_IO_BITFLIPS)
@@ -350,14 +356,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
 			}
 		}
 
-		if (!vh->copy_flag) {
-			/* It is not a copy, so it is newer */
-			dbg_bld("first PEB %d is newer, copy_flag is unset",
-				pnum);
-			err = bitflips << 1;
-			goto out_free_vidh;
-		}
-
 		vid_hdr = vh;
 	}
 
@@ -516,6 +514,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 			seb->ec = ec;
 			seb->pnum = pnum;
 			seb->scrub = ((cmp_res & 2) || bitflips);
+			seb->copy_flag = vid_hdr->copy_flag;
 			seb->sqnum = sqnum;
 
 			if (sv->highest_lnum == lnum)
@@ -549,8 +548,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 	seb->ec = ec;
 	seb->pnum = pnum;
 	seb->lnum = lnum;
-	seb->sqnum = sqnum;
 	seb->scrub = bitflips;
+	seb->copy_flag = vid_hdr->copy_flag;
+	seb->sqnum = sqnum;
 
 	if (sv->highest_lnum <= lnum) {
 		sv->highest_lnum = lnum;
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index 12ac852..a3264f0 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -30,6 +30,7 @@
  * @pnum: physical eraseblock number
  * @lnum: logical eraseblock number
  * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
  * @sqnum: sequence number
  * @u: unions RB-tree or @list links
  * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
@@ -42,7 +43,8 @@ struct ubi_scan_leb {
 	int ec;
 	int pnum;
 	int lnum;
-	int scrub;
+	unsigned int scrub:1;
+	unsigned int copy_flag:1;
 	unsigned long long sqnum;
 	union {
 		struct rb_node rb;
-- 
1.7.2.3



From dedekind1 at gmail.com  Wed Oct 20 05:07:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 20 Oct 2010 12:07:15 +0300
Subject: [PATCH 2/3] UBI: fix check_data_ff return code
In-Reply-To: <1287565636-18825-1-git-send-email-dedekind1@gmail.com>
References: <1287565636-18825-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1287565636-18825-2-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

When the data does not contain all 0xFF bytes, 'check_data_ff()' should return
1, not -EINVAL; Also, the caller ('process_eb()') should not add the PEB to the
"corrupted" list if there was a read error.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/ubi/scan.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 2fbb571..e7b800b 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -784,7 +784,7 @@ static int check_data_ff(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
 	ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
 			       ubi->peb_buf1, ubi->leb_size, 1);
 	mutex_unlock(&ubi->buf_mutex);
-	return -EINVAL;
+	return 1;
 }
 
 /**
@@ -936,7 +936,10 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 			 * have to check what is in the data area.
 			 */
 			err = check_data_ff(ubi, vidh, pnum);
-		if (!err)
+
+		if (err < 0)
+			return err;
+		else if (!err)
 			/* This corruption is caused by a power cut */
 			err = add_to_list(si, pnum, ec, 1, &si->erase);
 		else
-- 
1.7.2.3



From matthieu.castet at parrot.com  Wed Oct 20 05:52:09 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Wed, 20 Oct 2010 11:52:09 +0200
Subject: [PATCH 2/2] UBIFS: add unstable pages problem description
In-Reply-To: <1287475068.9272.8.camel@localhost>
References: <1287396125-1890-1-git-send-email-dedekind1@gmail.com>
	<1287475068.9272.8.camel@localhost>
Message-ID: <4CBEBBC9.5040902@parrot.com>

Hi Artem,

Artem Bityutskiy a ?crit :
> On Mon, 2010-10-18 at 13:02 +0300, Artem Bityutskiy wrote:
>> From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
>>
>> Describe a problem reported by Matthieu CASTET which is currently
>> not handled by UBIFS.
>>
>> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> 
> Matthiew, are you happy with this description? Does it properly reflect
> your findings? Could you please correct, if not?
Yes that seems correct.

> 
> I'm starting working on your problem. Since I do not have much time,
> I'll do a little everyday, but hope to come up with some patches this
> week already. The thing is that it is a lot of work. We need to go
> through a lot of UBI/UBIFS subsystems and analyze them.
> 
> Why a lot of work? Because we assumed everywhere we can rely on CRC - if
> it is correct, we are safe. However, according to you this is not
> reliable for unstable pages - you do not have guarantee that next time
> you read it you will get correct data.
> 
> Also, I do not have HW to test this, so I expect you to help by testing,
> are your testing set-ups kept ready? :-)
> 
Yes our boards are ready to test things.

But we can sent you flashs or boards with the problem.
What flash/board do you have on your side ?
Could you swap nand on your board (via tsop socket) ?

We could sent one of our board, but the update side can be complex/tricky.

Some of beagleboard may have the problem. But I am unable to test it.
On the beagleboard I have, I got strange ecc error [1] event without 
reboot. Also the driver look strange (for example doesn't do bad block 
scanning [2]). I end up with unusable nand [3]. Do you know if there is 
a better version of the nand driver for beagle (I use the one from 
ubi-2.6) ?

Matthieu

[1]
UBI error: ubi_io_read: error -74 (ECC error) while reading 4144
bytes from PEB 3:45056, read 4144 bytes
[...]
UBI error: do_sync_erase: cannot erase PEB 137, error -5


[2]
for each format I got
ubiformat: formatting eraseblock 137 -- 53 % complete
ubiformat: error!: failed to erase eraseblock 137
            error 5 (Input/output error)
ubiformat: marking block 137 bad

[3]
# ubiformat /dev/mtd3 -y 

ubiformat: mtd3 (nand), size 33554432 bytes (32.0 MiB), 256 eraseblocks 
of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes
libscan: scanning eraseblock 255 -- 100 % complete 

ubiformat: 255 eraseblocks have valid erase counter, mean value is 10 

ubiformat: 1 bad eraseblocks found, numbers: 137 

ubiformat: warning!: VID header and data offsets on flash are 2048 and 
4096, which is different to requested offsets 512 and 28
ubiformat: use new offsets 512 and 2048? (yes/no)  yes 

ubiformat: use offsets 512 and 2048 

ubiformat: formatting eraseblock 255 -- 100 % complete 

# ubiattach /dev/ubi_ctrl -m 3 -d 3 

[  166.922119] UBI: attaching mtd3 to ubi3 

[  166.926177] UBI: physical eraseblock size:   131072 bytes (128 KiB) 

[  166.932495] UBI: logical eraseblock size:    129024 bytes 

[  166.937927] UBI: smallest flash I/O unit:    2048 

[  166.942657] UBI: sub-page size:              512 

[  166.947326] UBI: VID header offset:          512 (aligned 512) 

[  166.953186] UBI: data offset:                2048 

[  166.958740] Correcting single bit ECC error at offset: 389, bit: 3 

[  167.137695] UBI: max. sequence number:       0 

[  167.142883] Correcting single bit ECC error at offset: 340, bit: 6 

[  167.149108] ecc failure 

[  167.151580] Correcting single bit ECC error at offset: 12, bit: 6 

[  167.158325] ecc failure 

[  167.160797] ecc failure 

[  167.163269] Correcting single bit ECC error at offset: 44, bit: 6 

[  167.170013] ecc failure 

[  167.172485] ecc failure 

[  167.175567] ecc failure 

[  167.178039] ecc failure 

[  167.181121] ecc failure 

[  167.183593] ecc failure 

[  167.186645] ecc failure 

[  167.189147] ecc failure 

[  167.192199] Correcting single bit ECC error at offset: 188, bit: 6 

[  167.198455] Correcting single bit ECC error at offset: 196, bit: 6 

[  167.205291] Correcting single bit ECC error at offset: 220, bit: 6 

[  167.211517] Correcting single bit ECC error at offset: 228, bit: 6 

[  167.218353] Correcting single bit ECC error at offset: 252, bit: 6 

[  167.224578] Correcting single bit ECC error at offset: 260, bit: 6 

[  167.231445] Correcting single bit ECC error at offset: 284, bit: 6 

[  167.237670] Correcting single bit ECC error at offset: 292, bit: 6 

[  167.244537] Correcting single bit ECC error at offset: 316, bit: 6 

[  167.250762] Correcting single bit ECC error at offset: 324, bit: 6 

[  167.256988] UBI error: ubi_io_read: error -74 (ECC error) while 
reading 22528 bytes from PEB 0:2048, read 22528 bytes
[  167.267700] [<c0034d5c>] (unwind_backtrace+0x0/0xf4) from 
[<c01db4dc>] (ubi_io_read+0x1b0/0x340)
[  167.276580] [<c01db4dc>] (ubi_io_read+0x1b0/0x340) from [<c01d1728>] 
(ubi_read_volume_table+0xbc/0xa44)
[  167.286071] [<c01d1728>] (ubi_read_volume_table+0xbc/0xa44) from 
[<c01d537c>] (ubi_attach_mtd_dev+0x674/0xcd0)
[  167.296173] [<c01d537c>] (ubi_attach_mtd_dev+0x674/0xcd0) from 
[<c01d5b80>] (ctrl_cdev_ioctl+0xec/0x164)
[  167.305725] [<c01d5b80>] (ctrl_cdev_ioctl+0xec/0x164) from 
[<c00d63d0>] (do_vfs_ioctl+0x7c/0x5f8)
[  167.314697] [<c00d63d0>] (do_vfs_ioctl+0x7c/0x5f8) from [<c00d6984>] 
(sys_ioctl+0x38/0x60)
[  167.323028] [<c00d6984>] (sys_ioctl+0x38/0x60) from [<c00300c0>] 
(ret_fast_syscall+0x0/0x30)
[  167.332214] Correcting single bit ECC error at offset: 340, bit: 6 

[  167.338470] ecc failure 

[  167.340942] Correcting single bit ECC error at offset: 12, bit: 6 

[  167.347686] ecc failure 

[  167.350158] ecc failure 

[  167.352630] Correcting single bit ECC error at offset: 44, bit: 6 

[  167.359375] ecc failure 

[  167.361846] ecc failure 

[  167.364929] ecc failure 

[  167.367401] ecc failure 

[  167.370452] ecc failure 

[  167.372955] ecc failure 

[  167.376007] ecc failure 

[  167.378479] ecc failure 

[  167.381561] Correcting single bit ECC error at offset: 188, bit: 6 

[  167.387786] Correcting single bit ECC error at offset: 196, bit: 6 

[  167.394653] Correcting single bit ECC error at offset: 220, bit: 6 

[  167.400848] Correcting single bit ECC error at offset: 228, bit: 6 

[  167.407714] Correcting single bit ECC error at offset: 252, bit: 6 

[  167.413940] Correcting single bit ECC error at offset: 260, bit: 6 

[  167.420806] Correcting single bit ECC error at offset: 284, bit: 6 

[  167.427032] Correcting single bit ECC error at offset: 292, bit: 6 

[  167.433868] Correcting single bit ECC error at offset: 316, bit: 6 

[  167.440124] Correcting single bit ECC error at offset: 324, bit: 6 

[  167.446350] UBI error: ubi_io_read: error -74 (ECC error) while 
reading 22528 bytes from PEB 1:2048, read 22528 bytes
[  167.457031] [<c0034d5c>] (unwind_backtrace+0x0/0xf4) from 
[<c01db4dc>] (ubi_io_read+0x1b0/0x340)
[  167.465911] [<c01db4dc>] (ubi_io_read+0x1b0/0x340) from [<c01d1728>] 
(ubi_read_volume_table+0xbc/0xa44)
[  167.475402] [<c01d1728>] (ubi_read_volume_table+0xbc/0xa44) from 
[<c01d537c>] (ubi_attach_mtd_dev+0x674/0xcd0)
[  167.485473] [<c01d537c>] (ubi_attach_mtd_dev+0x674/0xcd0) from 
[<c01d5b80>] (ctrl_cdev_ioctl+0xec/0x164)
[  167.495056] [<c01d5b80>] (ctrl_cdev_ioctl+0xec/0x164) from 
[<c00d63d0>] (do_vfs_ioctl+0x7c/0x5f8)
[  167.503997] [<c00d63d0>] (do_vfs_ioctl+0x7c/0x5f8) from [<c00d6984>] 
(sys_ioctl+0x38/0x60)
[  167.512329] [<c00d6984>] (sys_ioctl+0x38/0x60) from [<c00300c0>] 
(ret_fast_syscall+0x0/0x30)
[  167.520874] UBI error: vtbl_check: bad CRC at record 1: 0xf116c36b, 
not 0xb116c36b
[  167.528594] UBI error: vtbl_check: bad CRC at record 1: 0xf116c36b, 
not 0xb116c36b
[  167.536285] UBI error: process_lvol: both volume tables are corrupted 

[  167.542877] UBI error: ubi_attach_mtd_dev: failed to attach by 
scanning, error -22
ubiattach: error!: cannot attach mtd3 

            error 22 (Invalid argument)


From savinay.dharmappa at ti.com  Wed Oct 20 05:20:24 2010
From: savinay.dharmappa at ti.com (Savinay Dharmappa)
Date: Wed, 20 Oct 2010 14:50:24 +0530
Subject: [PATCH] davinci: Platform support for OMAP-L137/AM17x NOR flash driver
Message-ID: <1287566424-9851-1-git-send-email-savinay.dharmappa@ti.com>

From: David Griego <dgriego at mvista.com>

Adds platform support for OMAP-L137/AM17x NOR flash driver.

Also, configures chip select 3 to control NOR flash's upper
address lines.

Signed-off-by: Aleksey Makarov <amakarov at ru.mvista.com>
Signed-off-by: Sergei Shtylyov <sshtylyov at ru.mvista.com>
Signed-off-by: Savinay Dharmappa <savinay.dharmappa at ti.com>
---
 arch/arm/mach-davinci/Kconfig           |    8 +
 arch/arm/mach-davinci/board-da830-evm.c |  220 +++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 9aca60c..baa39ee 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -142,6 +142,14 @@ config DA830_UI_NAND
 	help
 	  Say Y here to use the NAND flash. Do not forget to setup
 	  the switch correctly.
+
+config DA830_UI_NOR
+        bool "NOR flash"
+        help
+          Configure this option to specify the that AEMIF CE2/CE3 will be used to
+          communicate to the NOR flash. Do not forget to setup the switch SW1
+          on UI card correctly.
+
 endchoice
 
 config MACH_DAVINCI_DA850_EVM
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 1bb89d3..c8a5d4b 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -20,6 +20,8 @@
 #include <linux/i2c/at24.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/clk.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -429,6 +431,222 @@ static inline void da830_evm_init_nand(int mux_mode)
 static inline void da830_evm_init_nand(int mux_mode) { }
 #endif
 
+#ifdef CONFIG_DA830_UI_NOR
+/*
+ * Number of Address line going to the NOR flash that are latched using
+ * AEMIF address lines  B_EMIF_BA0-B_EMIF_A12  on CS2.
+ */
+#define NOR_WINDOW_SIZE_LOG2     15
+#define NOR_WINDOW_SIZE         (1 << NOR_WINDOW_SIZE_LOG2)
+
+static struct {
+	struct clk *clk;
+	struct {
+		struct resource *res;
+		void __iomem *addr;
+	} latch, aemif;
+} da830_evm_nor;
+
+static struct davinci_aemif_timing da830_evm_norflash_timing = {
+	.wsetup		= 0,
+	.wstrobe	= 40,
+	.whold		= 0,
+	.rsetup		= 0,
+	.rstrobe	= 130,
+	.rhold		= 0,
+	.ta		= 20,
+};
+
+static void da830_evm_nor_set_window(unsigned long offset, void *data)
+{
+	/*
+	 * CS2 and CS3 address lines are used to address nor flash. Address
+	 * line A0-A14 going to the NOR flash are latched using AEMIF address
+	 * lines B_EMIF_BA0-B_EMIF_A12 on CS2. Address lines A15-A23 of the
+	 * NOR flash are latched using AEMIF address lines B_EMIF_A0-B_EMIF_A6
+	 * on CS3. The offset argument received by this function is the offset
+	 * within NOR flash. Upper address is obtained  by shifting the offset
+	 * by the number of CS2 address lines used (13) and masking it with
+	 * complement of 3 (2 address lines used to address banks) and adding
+	 * the resultant offset value to CS3 base address. Writing a zero to
+	 * this address will latch the upper address lines.
+	 */
+	writeb(0, da830_evm_nor.latch.addr +
+		(~3UL & (offset >> (NOR_WINDOW_SIZE_LOG2 - 2))));
+}
+
+static void da830_evm_nor_done(void *data)
+{
+	clk_disable(da830_evm_nor.clk);
+	clk_put(da830_evm_nor.clk);
+	iounmap(da830_evm_nor.latch.addr);
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	iounmap(da830_evm_nor.aemif.addr);
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+}
+
+static int da830_evm_nor_init(void *data, int cs)
+{
+	/* Turn on AEMIF clocks */
+	da830_evm_nor.clk = clk_get(NULL, "aemif");
+	if (IS_ERR(da830_evm_nor.clk)) {
+		pr_err("%s: could not get AEMIF clock\n", __func__);
+		da830_evm_nor.clk = NULL;
+		return -ENODEV;
+	}
+	clk_enable(da830_evm_nor.clk);
+
+	da830_evm_nor.aemif.res = request_mem_region(DA8XX_AEMIF_CTL_BASE,
+						     SZ_32K, "AEMIF control");
+	if (da830_evm_nor.aemif.res == NULL) {
+		pr_err("%s: could not request AEMIF control region\n",
+			__func__);
+		goto err_clk;
+	}
+
+	da830_evm_nor.aemif.addr = ioremap_nocache(DA8XX_AEMIF_CTL_BASE,
+						   SZ_32K);
+	if (da830_evm_nor.aemif.addr == NULL) {
+		pr_err("%s: could not remap AEMIF control region\n", __func__);
+		goto err_aemif_region;
+	}
+
+	/* Setup AEMIF -- timings, etc. */
+
+	/* Set maximum wait cycles */
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+						da830_evm_nor.aemif.addr, cs);
+
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+					da830_evm_nor.aemif.addr, cs + 1);
+
+	/* Setup the window to access the latch */
+	da830_evm_nor.latch.res =
+		request_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE,
+				   "DA830 UI NOR address latch");
+	if (da830_evm_nor.latch.res == NULL) {
+		pr_err("%s: could not request address latch region\n",
+			__func__);
+		goto err_aemif_ioremap;
+	}
+
+	da830_evm_nor.latch.addr =
+		ioremap_nocache(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	if (da830_evm_nor.latch.addr == NULL) {
+		pr_err("%s: could not remap address latch region\n", __func__);
+		goto err_latch_region;
+	}
+	return 0;
+
+err_latch_region:
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	da830_evm_nor.latch.res = NULL;
+err_aemif_ioremap:
+	iounmap(da830_evm_nor.aemif.addr);
+	da830_evm_nor.aemif.addr = NULL;
+err_aemif_region:
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+	da830_evm_nor.aemif.res = NULL;
+err_clk:
+	clk_disable(da830_evm_nor.clk);
+	clk_put(da830_evm_nor.clk);
+	da830_evm_nor.clk  = NULL;
+
+	return -EBUSY;
+}
+
+static struct mtd_partition da830_evm_nor_partitions[] = {
+	/* bootloader (U-Boot, etc) in first 2 sectors */
+	[0] = {
+		.name           = "bootloader",
+		.offset		= 0,
+		.size           = SZ_128K,
+		.mask_flags     = MTD_WRITEABLE, /* force read-only */
+	},
+	/* bootloader parameters in the next 1 sector */
+	[1] = {
+		.name           = "params",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_64K,
+	},
+	/* kernel */
+	[2] = {
+		.name           = "kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_2M,
+	},
+	/* file system */
+	[3] = {
+		.name           = "filesystem",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	}
+};
+
+static struct latch_addr_flash_data da830_evm_nor_pdata = {
+	.width          = 1,
+	.size           = SZ_4M,
+	.init           = da830_evm_nor_init,
+	.done           = da830_evm_nor_done,
+	.set_window     = da830_evm_nor_set_window,
+	.nr_parts       = ARRAY_SIZE(da830_evm_nor_partitions),
+	.parts          = da830_evm_nor_partitions,
+};
+
+static struct resource da830_evm_nor_resource[] = {
+	[0] = {
+		.start  = DA8XX_AEMIF_CS2_BASE,
+		.end    = DA8XX_AEMIF_CS2_BASE + NOR_WINDOW_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = DA8XX_AEMIF_CS3_BASE,
+		.end    = DA8XX_AEMIF_CS3_BASE + PAGE_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = DA8XX_AEMIF_CTL_BASE,
+		.end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+		.flags  = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device da830_evm_nor_device = {
+	.name           = "latch-addr-flash",
+	.id             = 0,
+	.dev            = {
+		.platform_data  = &da830_evm_nor_pdata,
+	},
+	.num_resources  = ARRAY_SIZE(da830_evm_nor_resource),
+	.resource       = da830_evm_nor_resource,
+};
+
+static inline void da830_evm_init_nor(int mux_mode)
+{
+	int ret;
+
+	if (HAS_MMC) {
+		pr_warning("WARNING: both MMC/SD and NOR are "
+				"enabled, but they share AEMIF pins.\n"
+					"\tDisable MMC/SD for NOR support.\n");
+		return;
+	}
+
+	ret = davinci_cfg_reg_list(da830_evm_emif25_pins);
+	if (ret)
+		pr_warning("da830_evm_init: emif25 mux setup failed: %d\n",
+			  ret);
+
+	ret = platform_device_register(&da830_evm_nor_device);
+	if (ret)
+		pr_warning("da830_evm_init: NOR device not registered.\n");
+
+	gpio_direction_output(mux_mode, 1);
+}
+#else
+static inline void da830_evm_init_nor(int mux_mode) { }
+#endif  /* CONFIG_DA830_UI_NOR */
+
 #ifdef CONFIG_DA830_UI_LCD
 static inline void da830_evm_init_lcdc(int mux_mode)
 {
@@ -469,6 +687,8 @@ static int __init da830_evm_ui_expander_setup(struct i2c_client *client,
 
 	da830_evm_init_nand(gpio + 6);
 
+	da830_evm_init_nor(gpio + 6);
+
 	return 0;
 }
 
-- 
1.5.6



From savinay.dharmappa at ti.com  Wed Oct 20 07:02:34 2010
From: savinay.dharmappa at ti.com (Savinay Dharmappa)
Date: Wed, 20 Oct 2010 16:32:34 +0530
Subject: [PATCH] davinci: Platform support for OMAP-L137/AM17x NOR flash
	driver
In-Reply-To: <1287566424-9851-1-git-send-email-savinay.dharmappa@ti.com>
References: <1287566424-9851-1-git-send-email-savinay.dharmappa@ti.com>
Message-ID: <000301cb7046$4c5bfe30$e513fa90$@dharmappa@ti.com>

Hi all,
		Please ignore this patch, as this was sent accidentally.
Thanks
Savinay

-----Original Message-----
From: Savinay Dharmappa [mailto:savinay.dharmappa at ti.com] 
Sent: Wednesday, October 20, 2010 2:50 PM
To: sudhakar.raj at ti.com
Cc: linux-mtd at lists.infradead.org; David Griego; Aleksey Makarov; Sergei
Shtylyov; Savinay Dharmappa
Subject: [PATCH] davinci: Platform support for OMAP-L137/AM17x NOR flash
driver

From: David Griego <dgriego at mvista.com>

Adds platform support for OMAP-L137/AM17x NOR flash driver.

Also, configures chip select 3 to control NOR flash's upper
address lines.

Signed-off-by: Aleksey Makarov <amakarov at ru.mvista.com>
Signed-off-by: Sergei Shtylyov <sshtylyov at ru.mvista.com>
Signed-off-by: Savinay Dharmappa <savinay.dharmappa at ti.com>
---
 arch/arm/mach-davinci/Kconfig           |    8 +
 arch/arm/mach-davinci/board-da830-evm.c |  220
+++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 9aca60c..baa39ee 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -142,6 +142,14 @@ config DA830_UI_NAND
 	help
 	  Say Y here to use the NAND flash. Do not forget to setup
 	  the switch correctly.
+
+config DA830_UI_NOR
+        bool "NOR flash"
+        help
+          Configure this option to specify the that AEMIF CE2/CE3 will be
used to
+          communicate to the NOR flash. Do not forget to setup the switch
SW1
+          on UI card correctly.
+
 endchoice
 
 config MACH_DAVINCI_DA850_EVM
diff --git a/arch/arm/mach-davinci/board-da830-evm.c
b/arch/arm/mach-davinci/board-da830-evm.c
index 1bb89d3..c8a5d4b 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -20,6 +20,8 @@
 #include <linux/i2c/at24.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/clk.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -429,6 +431,222 @@ static inline void da830_evm_init_nand(int mux_mode)
 static inline void da830_evm_init_nand(int mux_mode) { }
 #endif
 
+#ifdef CONFIG_DA830_UI_NOR
+/*
+ * Number of Address line going to the NOR flash that are latched using
+ * AEMIF address lines  B_EMIF_BA0-B_EMIF_A12  on CS2.
+ */
+#define NOR_WINDOW_SIZE_LOG2     15
+#define NOR_WINDOW_SIZE         (1 << NOR_WINDOW_SIZE_LOG2)
+
+static struct {
+	struct clk *clk;
+	struct {
+		struct resource *res;
+		void __iomem *addr;
+	} latch, aemif;
+} da830_evm_nor;
+
+static struct davinci_aemif_timing da830_evm_norflash_timing = {
+	.wsetup		= 0,
+	.wstrobe	= 40,
+	.whold		= 0,
+	.rsetup		= 0,
+	.rstrobe	= 130,
+	.rhold		= 0,
+	.ta		= 20,
+};
+
+static void da830_evm_nor_set_window(unsigned long offset, void *data)
+{
+	/*
+	 * CS2 and CS3 address lines are used to address nor flash. Address
+	 * line A0-A14 going to the NOR flash are latched using AEMIF
address
+	 * lines B_EMIF_BA0-B_EMIF_A12 on CS2. Address lines A15-A23 of the
+	 * NOR flash are latched using AEMIF address lines
B_EMIF_A0-B_EMIF_A6
+	 * on CS3. The offset argument received by this function is the
offset
+	 * within NOR flash. Upper address is obtained  by shifting the
offset
+	 * by the number of CS2 address lines used (13) and masking it with
+	 * complement of 3 (2 address lines used to address banks) and
adding
+	 * the resultant offset value to CS3 base address. Writing a zero to
+	 * this address will latch the upper address lines.
+	 */
+	writeb(0, da830_evm_nor.latch.addr +
+		(~3UL & (offset >> (NOR_WINDOW_SIZE_LOG2 - 2))));
+}
+
+static void da830_evm_nor_done(void *data)
+{
+	clk_disable(da830_evm_nor.clk);
+	clk_put(da830_evm_nor.clk);
+	iounmap(da830_evm_nor.latch.addr);
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	iounmap(da830_evm_nor.aemif.addr);
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+}
+
+static int da830_evm_nor_init(void *data, int cs)
+{
+	/* Turn on AEMIF clocks */
+	da830_evm_nor.clk = clk_get(NULL, "aemif");
+	if (IS_ERR(da830_evm_nor.clk)) {
+		pr_err("%s: could not get AEMIF clock\n", __func__);
+		da830_evm_nor.clk = NULL;
+		return -ENODEV;
+	}
+	clk_enable(da830_evm_nor.clk);
+
+	da830_evm_nor.aemif.res = request_mem_region(DA8XX_AEMIF_CTL_BASE,
+						     SZ_32K, "AEMIF
control");
+	if (da830_evm_nor.aemif.res == NULL) {
+		pr_err("%s: could not request AEMIF control region\n",
+			__func__);
+		goto err_clk;
+	}
+
+	da830_evm_nor.aemif.addr = ioremap_nocache(DA8XX_AEMIF_CTL_BASE,
+						   SZ_32K);
+	if (da830_evm_nor.aemif.addr == NULL) {
+		pr_err("%s: could not remap AEMIF control region\n",
__func__);
+		goto err_aemif_region;
+	}
+
+	/* Setup AEMIF -- timings, etc. */
+
+	/* Set maximum wait cycles */
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+						da830_evm_nor.aemif.addr,
cs);
+
+	davinci_aemif_setup_timing(&da830_evm_norflash_timing,
+					da830_evm_nor.aemif.addr, cs + 1);
+
+	/* Setup the window to access the latch */
+	da830_evm_nor.latch.res =
+		request_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE,
+				   "DA830 UI NOR address latch");
+	if (da830_evm_nor.latch.res == NULL) {
+		pr_err("%s: could not request address latch region\n",
+			__func__);
+		goto err_aemif_ioremap;
+	}
+
+	da830_evm_nor.latch.addr =
+		ioremap_nocache(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	if (da830_evm_nor.latch.addr == NULL) {
+		pr_err("%s: could not remap address latch region\n",
__func__);
+		goto err_latch_region;
+	}
+	return 0;
+
+err_latch_region:
+	release_mem_region(DA8XX_AEMIF_CS3_BASE, PAGE_SIZE);
+	da830_evm_nor.latch.res = NULL;
+err_aemif_ioremap:
+	iounmap(da830_evm_nor.aemif.addr);
+	da830_evm_nor.aemif.addr = NULL;
+err_aemif_region:
+	release_mem_region(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+	da830_evm_nor.aemif.res = NULL;
+err_clk:
+	clk_disable(da830_evm_nor.clk);
+	clk_put(da830_evm_nor.clk);
+	da830_evm_nor.clk  = NULL;
+
+	return -EBUSY;
+}
+
+static struct mtd_partition da830_evm_nor_partitions[] = {
+	/* bootloader (U-Boot, etc) in first 2 sectors */
+	[0] = {
+		.name           = "bootloader",
+		.offset		= 0,
+		.size           = SZ_128K,
+		.mask_flags     = MTD_WRITEABLE, /* force read-only */
+	},
+	/* bootloader parameters in the next 1 sector */
+	[1] = {
+		.name           = "params",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_64K,
+	},
+	/* kernel */
+	[2] = {
+		.name           = "kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_2M,
+	},
+	/* file system */
+	[3] = {
+		.name           = "filesystem",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = MTDPART_SIZ_FULL,
+	}
+};
+
+static struct latch_addr_flash_data da830_evm_nor_pdata = {
+	.width          = 1,
+	.size           = SZ_4M,
+	.init           = da830_evm_nor_init,
+	.done           = da830_evm_nor_done,
+	.set_window     = da830_evm_nor_set_window,
+	.nr_parts       = ARRAY_SIZE(da830_evm_nor_partitions),
+	.parts          = da830_evm_nor_partitions,
+};
+
+static struct resource da830_evm_nor_resource[] = {
+	[0] = {
+		.start  = DA8XX_AEMIF_CS2_BASE,
+		.end    = DA8XX_AEMIF_CS2_BASE + NOR_WINDOW_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = DA8XX_AEMIF_CS3_BASE,
+		.end    = DA8XX_AEMIF_CS3_BASE + PAGE_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	[2] = {
+		.start  = DA8XX_AEMIF_CTL_BASE,
+		.end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+		.flags  = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device da830_evm_nor_device = {
+	.name           = "latch-addr-flash",
+	.id             = 0,
+	.dev            = {
+		.platform_data  = &da830_evm_nor_pdata,
+	},
+	.num_resources  = ARRAY_SIZE(da830_evm_nor_resource),
+	.resource       = da830_evm_nor_resource,
+};
+
+static inline void da830_evm_init_nor(int mux_mode)
+{
+	int ret;
+
+	if (HAS_MMC) {
+		pr_warning("WARNING: both MMC/SD and NOR are "
+				"enabled, but they share AEMIF pins.\n"
+					"\tDisable MMC/SD for NOR
support.\n");
+		return;
+	}
+
+	ret = davinci_cfg_reg_list(da830_evm_emif25_pins);
+	if (ret)
+		pr_warning("da830_evm_init: emif25 mux setup failed: %d\n",
+			  ret);
+
+	ret = platform_device_register(&da830_evm_nor_device);
+	if (ret)
+		pr_warning("da830_evm_init: NOR device not registered.\n");
+
+	gpio_direction_output(mux_mode, 1);
+}
+#else
+static inline void da830_evm_init_nor(int mux_mode) { }
+#endif  /* CONFIG_DA830_UI_NOR */
+
 #ifdef CONFIG_DA830_UI_LCD
 static inline void da830_evm_init_lcdc(int mux_mode)
 {
@@ -469,6 +687,8 @@ static int __init da830_evm_ui_expander_setup(struct
i2c_client *client,
 
 	da830_evm_init_nand(gpio + 6);
 
+	da830_evm_init_nor(gpio + 6);
+
 	return 0;
 }
 
-- 
1.5.6




From dedekind1 at gmail.com  Wed Oct 20 07:19:54 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 20 Oct 2010 14:19:54 +0300
Subject: Expanding UBI fs to maxavailable size
In-Reply-To: <968604.60195.qm@web120213.mail.ne1.yahoo.com>
References: <4CBCBA9D.4040202@jeppesens.com> <1287465154.1911.2.camel@brekeke>
	<968604.60195.qm@web120213.mail.ne1.yahoo.com>
Message-ID: <1287573594.9272.64.camel@localhost>

On Tue, 2010-10-19 at 01:17 -0700, Karsten Jeppesen wrote:
> Hi Artem,
> 
> This is Karsten Jeppesen, just using an out-of-the-house account,
> and thanks for your very quick reply.

UBI and UBIFS always print something, refer:
http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport
item 3.

Anyway, AFAICS, UBI auto-resize the UBI volume correctly, because of
this:

> ubi0
> Volumes count:                           1
> Logical eraseblock size:                 130944 bytes, 127.9 KiB
> Total amount of logical eraseblocks:     486 (63638784 bytes, 60.7 MiB)

I re-sized.

However, UBIFS file-system did not re-size, because you specified too
small maximum UBIFS LEB count: --max-leb-cnt=232

Try --max-leb-cnt=511 and it should work. Take a look here:
http://www.linux-mtd.infradead.org/faq/ubifs.html#L_max_leb_cnt

I agree this all stuff is not as user-friendly as it could, but you have
a good chance to make it user-friendlier by contributing docs or code.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Oct 20 09:26:58 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 20 Oct 2010 16:26:58 +0300
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <20101013163005.GB1889@silverbox.local>
References: <20101013163005.GB1889@silverbox.local>
Message-ID: <1287581218.9272.67.camel@localhost>

On Wed, 2010-10-13 at 18:30 +0200, Hans J. Koch wrote:
> Running this command:
> 
> # while true ; do sync; sleep 1; done
> 
> causes two eraseblocks being erased every second, although there
> are no writes to the ubifs filesystem. I hacked some printks into
> my NAND driver that print page_address and column for each erase.
> With that, I get this output every second:
> 
> ...
> [   63.701765] erase p=0x0000ae40 c=0xffffffff
> [   63.706534] erase p=0xffffffff c=0xffffffff
> [   63.725492] erase p=0x0000ae80 c=0xffffffff
> [   63.730260] erase p=0xffffffff c=0xffffffff
> ...
> 
> From a quick glance at the ubifs code, this might come out of the
> garbage collector that is triggered on every sync() and writes
> something even if nothing has changed.
> 
> Is that really needed?

I briefly looked, and UBIFS is doing a lot of I/O in that case, which is
unnecessary and should not be done, I'll need to investigate this.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Wed Oct 20 10:03:38 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 20 Oct 2010 07:03:38 -0700
Subject: [PATCH 2/2] mtd-utils: nanddump: add 64-bit support, utilize
	libmtd
In-Reply-To: <AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>
References: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
	<1287557125-2672-2-git-send-email-computersforpeace@gmail.com>
	<AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>
Message-ID: <4CBEF6BA.8080103@gmail.com>

Mike,

On 10/20/2010 12:01 AM, Mike Frysinger wrote:
> On Wed, Oct 20, 2010 at 02:45, Brian Norris wrote:
>> ...
>> -static unsigned long   start_addr;             // start address
>> ...
>> -static bool            forcebinary = false;    // force printing binary to tty
...
>> +static unsigned long long      start_addr;             // start address
...
>> +static bool                    forcebinary = false;    // force printing binary to tty
> 
> only one of these lines are functional.  please fold the rest into
> your "style fixup" patch.

True, except that they are not "style fixups" until after start_addr has
a longer data type (pun intended). I'll respin though.

>> @@ -480,7 +479,7 @@ int main(int argc, char * const argv[])
>>                        if (noskipbad)
>>                                continue;
>>                        do {
>> -                               if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
>> +                               if ((ret = 0 /*ioctl(fd, MEMGETBADBLOCK, &offs)*/) < 0) {
>>                                        perror("ioctl(MEMGETBADBLOCK)");
>>                                        goto closeall;
>>                                }
> 
> doesnt seem to belong.  then again, none of the changes to this file
> look like they belong in this patch.

Wow, I really thought I had fixed this. Sorry, I will definitely respin.
I must have been in a hurry to send this out.

Still, despite my inability/failure to fully proofread my patches, most
of the patch *is* intentional and *does* belong, IMO. I will try to
document it better in the next patch description, but do you have
specifics on what you meant?

Thanks,
Brian


From joe at perches.com  Wed Oct 20 13:39:22 2010
From: joe at perches.com (Joe Perches)
Date: Wed, 20 Oct 2010 10:39:22 -0700
Subject: [PATCH] drivers/mtd/devices/phram.c: Use KBUILD_MODNAME
Message-ID: <1287596362.1813.205.camel@Joe-Laptop>

Use the more standard #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
No change in output strings.

Signed-off-by: Joe Perches <joe at perches.com>
---
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index 1696bbe..5239328 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -15,7 +15,7 @@
  *	phram=swap,64Mi,128Mi phram=test,900Mi,1Mi
  */
 
-#define pr_fmt(fmt) "phram: " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <asm/io.h>
 #include <linux/init.h>




From vapier.adi at gmail.com  Wed Oct 20 14:26:36 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 20 Oct 2010 14:26:36 -0400
Subject: [PATCH 2/2] mtd-utils: nanddump: add 64-bit support,
	utilize libmtd
In-Reply-To: <4CBEF6BA.8080103@gmail.com>
References: <1287557125-2672-1-git-send-email-computersforpeace@gmail.com>
	<1287557125-2672-2-git-send-email-computersforpeace@gmail.com>
	<AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>
	<4CBEF6BA.8080103@gmail.com>
Message-ID: <AANLkTi=Viw6b8hhTWRc+TjrrgGuUV8dGnULqmhD0cGLH@mail.gmail.com>

On Wed, Oct 20, 2010 at 10:03, Brian Norris wrote:
> but do you have specifics on what you meant?

this patch is titled "nanddump", so you shouldnt be modifying files
outside of nanddump.  nor should you be replacing a call to an ioctl()
with 0 without any comment whatsoever as to why.
-mike


From akpm at linux-foundation.org  Wed Oct 20 18:59:08 2010
From: akpm at linux-foundation.org (akpm at linux-foundation.org)
Date: Wed, 20 Oct 2010 15:59:08 -0700
Subject: [patch 2/2] jffs2: use cond_resched() instead of yield()
Message-ID: <201010202259.o9KMx8tG009573@imap1.linux-foundation.org>

From: Wolfram Sang <w.sang at pengutronix.de>

yield() has different semantics meanwhile and even causes RT-kernels to
BUG.  Replace the only appearance left in jffs2.

Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
Cc: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Cc: Ingo Molnar <mingo at elte.hu>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Artem Bityutskiy <dedekind at infradead.org>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
---

 fs/jffs2/erase.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -puN fs/jffs2/erase.c~jffs2-use-cond_resched-instead-of-yield fs/jffs2/erase.c
--- a/fs/jffs2/erase.c~jffs2-use-cond_resched-instead-of-yield
+++ a/fs/jffs2/erase.c
@@ -151,7 +151,7 @@ int jffs2_erase_pending_blocks(struct jf
 		}
 
 		/* Be nice */
-		yield();
+		cond_resched();
 		mutex_lock(&c->erase_free_sem);
 		spin_lock(&c->erase_completion_lock);
 	}
_


From akpm at linux-foundation.org  Wed Oct 20 18:59:07 2010
From: akpm at linux-foundation.org (akpm at linux-foundation.org)
Date: Wed, 20 Oct 2010 15:59:07 -0700
Subject: [patch 1/2] mtdpart: memory accessor interface for MTD layer
Message-ID: <201010202259.o9KMx7jc009570@imap1.linux-foundation.org>

From: Sudhakar Rajashekhara <sudhakar.raj at ti.com>

Implement a memory accessor interface in the MTD layer which enables the
kernel to access flash data.

This patch adds two new members to the mtd_partition structure, a function
handler which will be called during setup of the partition and an argument
to be passed to this setup function.

Example:
+static struct mtd_partition spi_flash_partitions[] = {
+       [0] = {
+               .name       = "U-Boot",
+               .offset     = 0,
+               .size       = SZ_256K,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       [1] = {
+               .name       = "U-Boot Environment",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_64K,
+               .mask_flags = MTD_WRITEABLE,
+       },
+       [2] = {
+               .name       = "Linux",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_7M,
+               .mask_flags = 0,
+       },
+       [3] = {
+               .name       = "MAC Address",
+               .offset     = MTDPART_OFS_NXTBLK,
+               .size       = SZ_64K,
+               .mask_flags = 0,
+               .setup      = davinci_get_mac_addr,
+               .context    = (void *)0,
+       },
+};

The davinci_get_mac_addr function reads the MAC address from
offset ZERO of last MTD partition.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj at ti.com>
Acked-by: Kevin Hilman <khilman at deeprootsystems.com>
Cc: David Brownell <david-b at pacbell.net>
Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Anton Vorontsov <cbouatmailru at gmail.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
---

 drivers/mtd/mtdpart.c          |   40 +++++++++++++++++++++++++++++++
 include/linux/mtd/partitions.h |    3 ++
 2 files changed, 43 insertions(+)

diff -puN drivers/mtd/mtdpart.c~mtdpart-memory-accessor-interface-for-mtd-layer drivers/mtd/mtdpart.c
--- a/drivers/mtd/mtdpart.c~mtdpart-memory-accessor-interface-for-mtd-layer
+++ a/drivers/mtd/mtdpart.c
@@ -37,6 +37,7 @@ static LIST_HEAD(mtd_partitions);
 struct mtd_part {
 	struct mtd_info mtd;
 	struct mtd_info *master;
+	struct memory_accessor macc;
 	uint64_t offset;
 	struct list_head list;
 };
@@ -346,6 +347,39 @@ int del_mtd_partitions(struct mtd_info *
 }
 EXPORT_SYMBOL(del_mtd_partitions);
 
+/*
+ * This lets other kernel code access the flash data. For example, it
+ * might hold a board's Ethernet address, or board-specific calibration
+ * data generated on the manufacturing floor.
+ */
+static ssize_t mtd_macc_read(struct memory_accessor *macc, char *buf,
+			off_t offset, size_t count)
+{
+	struct mtd_part *part = container_of(macc, struct mtd_part, macc);
+	ssize_t ret = -EIO;
+	size_t retlen;
+
+	if (part_read((struct mtd_info *)part, offset, count,
+			&retlen, buf) == 0)
+		ret = retlen;
+
+	return ret;
+}
+
+static ssize_t mtd_macc_write(struct memory_accessor *macc, const char *buf,
+			off_t offset, size_t count)
+{
+	struct mtd_part *part = container_of(macc, struct mtd_part, macc);
+	ssize_t ret = -EIO;
+	size_t retlen;
+
+	if (part_write((struct mtd_info *)part, offset, count,
+			&retlen, buf) == 0)
+		ret = retlen;
+
+	return ret;
+}
+
 static struct mtd_part *add_one_partition(struct mtd_info *master,
 		const struct mtd_partition *part, int partno,
 		uint64_t cur_offset)
@@ -383,6 +417,9 @@ static struct mtd_part *add_one_partitio
 	slave->mtd.read = part_read;
 	slave->mtd.write = part_write;
 
+	slave->macc.read = mtd_macc_read;
+	slave->macc.write = mtd_macc_write;
+
 	if (master->panic_write)
 		slave->mtd.panic_write = part_panic_write;
 
@@ -449,6 +486,9 @@ static struct mtd_part *add_one_partitio
 	printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
 		(unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
 
+	if (part->setup)
+		part->setup(&slave->macc, (void *)part->context);
+
 	/* let's do some sanity checks */
 	if (slave->offset >= master->size) {
 		/* let's register it anyway to preserve ordering */
diff -puN include/linux/mtd/partitions.h~mtdpart-memory-accessor-interface-for-mtd-layer include/linux/mtd/partitions.h
--- a/include/linux/mtd/partitions.h~mtdpart-memory-accessor-interface-for-mtd-layer
+++ a/include/linux/mtd/partitions.h
@@ -10,6 +10,7 @@
 #define MTD_PARTITIONS_H
 
 #include <linux/types.h>
+#include <linux/memory.h>
 
 
 /*
@@ -40,6 +41,8 @@ struct mtd_partition {
 	uint64_t offset;		/* offset within the master MTD space */
 	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */
 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only)*/
+	void (*setup)(struct memory_accessor *, void *context);
+	void *context;
 };
 
 #define MTDPART_OFS_NXTBLK	(-2)
_


From manningc2 at actrix.gen.nz  Wed Oct 20 23:43:33 2010
From: manningc2 at actrix.gen.nz (Charles Manning)
Date: Thu, 21 Oct 2010 16:43:33 +1300
Subject: Issues with ubi utils Makefile
Message-ID: <201010211643.33332.manningc2@actrix.gen.nz>

Hi All

I'm getting some errors trying to mount a ubinized volume with a more recent 
kernel and think it might be due to problems in the ubi utils distributed 
with Ubuntu Meerkat.

I thus thought I'd build from git

When I do a make install from inside the mtd-utils/ubi-utils it tries to place 
the binaries in /usr/local//usr/sbin.

Same happens if I try make install from mtd-utils/

Is something broken or am I driving it incorrectly?


-- Charles



From computersforpeace at gmail.com  Thu Oct 21 03:19:35 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 21 Oct 2010 00:19:35 -0700
Subject: [PATCH v2 0/2] mtd-utils fixups
In-Reply-To: <AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>
Message-ID: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>

OK, this should be a decent rewrite. Again, I'm very sorry for the very
previous mangled patches. There was some laziness on my part compounded
by my misreading of Mike's responses.

Please provide any comments you have, especially regarding usage of libmtd
and even tips on replacing straight-up calls to ioctl. I'm sure I haven't
hit everything important.

Also, I'm working through nandwrite at the moment. It seems a tougher
slog though.

Thanks,
Brian

Brian Norris (2):
  mtd-utils: nanddump/nandwrite: style, signed-ness, printing fixups
  mtd-utils: nanddump: add 64-bit support, utilize libmtd

 nanddump.c  |  126 ++++++++++++++++++++++++++++------------------------------
 nandwrite.c |   28 +++++++-------
 2 files changed, 75 insertions(+), 79 deletions(-)




From computersforpeace at gmail.com  Thu Oct 21 03:19:36 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 21 Oct 2010 00:19:36 -0700
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style,
	signed-ness, printing fixups
In-Reply-To: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287645577-13538-2-git-send-email-computersforpeace@gmail.com>

There were some signed/unsigned integer comparisons. Their types were
changed for safety. Also, "strtol" was improperly used for unsigned
data types.

Nanddump's pretty print options needed a slight reformat to prepare for
printing offsets that are more than 32 bits (8 hex characters) wide.
This prevents overlap of output and ensures that at least one space is
printed between hex and ascii printouts. Perhaps this could use some
better alignment in the future.

Other fixes:
* Corrected several simple spacing issues
* Changed indentation of some global variable declarations in
  order to prepare for the next patch, which makes those
  declarations longer
* Used macro for PRETTY_ROW_SIZE instead of constant 16
* Reformatted, edited a multi-line comment
* Removed some unnecessary casts

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c  |   55 +++++++++++++++++++++++++++----------------------------
 nandwrite.c |   28 ++++++++++++++--------------
 2 files changed, 41 insertions(+), 42 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index bb649da..013eca0 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -77,18 +77,18 @@ static void display_version(void)
 
 // Option variables
 
-static bool		pretty_print = false;	// print nice
-static bool		noecc = false;		// don't error correct
-static bool		noskipbad = false;	// don't skip bad blocks
-static bool		omitoob = false;	// omit oob data
-static unsigned long	start_addr;		// start address
-static unsigned long	length;			// dump length
-static const char	*mtddev;		// mtd device name
-static const char	*dumpfile;		// dump file name
-static bool		omitbad = false;
-static bool		quiet = false;		// suppress diagnostic output
-static bool		canonical = false;	// print nice + ascii
-static bool		forcebinary = false;	// force printing binary to tty
+static bool			pretty_print = false;	// print nice
+static bool			noecc = false;		// don't error correct
+static bool			noskipbad = false;	// don't skip bad blocks
+static bool			omitoob = false;	// omit oob data
+static unsigned long		start_addr;		// start address
+static unsigned long		length;			// dump length
+static const char		*mtddev;		// mtd device name
+static const char		*dumpfile;		// dump file name
+static bool			omitbad = false;
+static bool			quiet = false;		// suppress diagnostic output
+static bool			canonical = false;	// print nice + ascii
+static bool			forcebinary = false;	// force printing binary to tty
 
 static void process_options(int argc, char * const argv[])
 {
@@ -135,7 +135,7 @@ static void process_options(int argc, char * const argv[])
 				omitbad = true;
 				break;
 			case 's':
-				start_addr = strtol(optarg, NULL, 0);
+				start_addr = strtoul(optarg, NULL, 0);
 				break;
 			case 'f':
 				if (!(dumpfile = strdup(optarg))) {
@@ -144,7 +144,7 @@ static void process_options(int argc, char * const argv[])
 				}
 				break;
 			case 'l':
-				length = strtol(optarg, NULL, 0);
+				length = strtoul(optarg, NULL, 0);
 				break;
 			case 'o':
 				omitoob = true;
@@ -225,14 +225,12 @@ static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
 {
 	static const char hex_asc[] = "0123456789abcdef";
 	unsigned char ch;
-	int j, lx = 0;
-	int ascii_column;
+	unsigned int j, lx = 0, ascii_column;
 
 	if (pagedump)
-		sprintf(linebuf, "0x%.8x: ", prefix);
+		lx += sprintf(linebuf, "0x%.8x: ", prefix);
 	else
-		sprintf(linebuf, "  OOB Data: ");
-	lx += 12;
+		lx += sprintf(linebuf, "  OOB Data: ");
 
 	if (!len)
 		goto nil;
@@ -253,8 +251,10 @@ static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
 	if (!ascii)
 		goto nil;
 
-	while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
+	do {
 		linebuf[lx++] = ' ';
+	} while (lx < (linebuflen - 1) && lx < (ascii_column - 1));
+
 	linebuf[lx++] = '|';
 	for (j = 0; (j < len) && (lx + 2) < linebuflen; j++)
 		linebuf[lx++] = (isascii(buf[j]) && isprint(buf[j])) ? buf[j]
@@ -308,7 +308,7 @@ int main(int argc, char * const argv[])
 	oob.ptr = oobbuf;
 
 	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
+		ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
 		if (ret == 0) {
 			oobinfochanged = 2;
 		} else {
@@ -330,7 +330,6 @@ int main(int argc, char * const argv[])
 			}
 		}
 	} else {
-
 		/* check if we can read ecc stats */
 		if (!ioctl(fd, ECCGETSTATS, &stat1)) {
 			eccstats = true;
@@ -375,7 +374,6 @@ int main(int argc, char * const argv[])
 	bs = meminfo.writesize;
 
 	/* Print informative message */
-
 	if (!quiet) {
 		fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
 				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
@@ -383,6 +381,7 @@ int main(int argc, char * const argv[])
 				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
 				(unsigned int)start_addr, (unsigned int)end_addr);
 	}
+
 	/* Dump the flash contents */
 	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
 		/* Check for bad block */
@@ -401,7 +400,7 @@ int main(int argc, char * const argv[])
 		if (badblock) {
 			if (omitbad)
 				continue;
-			memset (readbuf, 0xff, bs);
+			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
 			if (pread(fd, readbuf, bs, ofs) != bs) {
@@ -430,8 +429,8 @@ int main(int argc, char * const argv[])
 		/* Write out page data */
 		if (pretty_print) {
 			for (i = 0; i < bs; i += PRETTY_ROW_SIZE) {
-				pretty_dump_to_buffer(readbuf+i, PRETTY_ROW_SIZE,
-						pretty_buf, PRETTY_BUF_LEN, true, canonical, ofs+i);
+				pretty_dump_to_buffer(readbuf + i, PRETTY_ROW_SIZE,
+						pretty_buf, PRETTY_BUF_LEN, true, canonical, ofs + i);
 				write(ofd, pretty_buf, strlen(pretty_buf));
 			}
 		} else
@@ -453,8 +452,8 @@ int main(int argc, char * const argv[])
 
 		/* Write out OOB data */
 		if (pretty_print) {
-			for (i = 0; i < meminfo.oobsize; i += 16) {
-				pretty_dump_to_buffer(oobbuf+i, meminfo.oobsize-i,
+			for (i = 0; i < meminfo.oobsize; i += PRETTY_ROW_SIZE) {
+				pretty_dump_to_buffer(oobbuf + i, meminfo.oobsize - i,
 						pretty_buf, PRETTY_BUF_LEN, false, canonical, 0);
 				write(ofd, pretty_buf, strlen(pretty_buf));
 			}
diff --git a/nandwrite.c b/nandwrite.c
index b5745b9..b0c4366 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -318,7 +318,6 @@ int main(int argc, char * const argv[])
 
 		// autoplace ECC ?
 		if (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE) {
-
 			if (ioctl(fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
 				perror("MEMSETOOBSEL");
 				close(fd);
@@ -329,7 +328,7 @@ int main(int argc, char * const argv[])
 	}
 
 	if (noecc)  {
-		ret = ioctl(fd, MTDFILEMODE, (void *)MTD_MODE_RAW);
+		ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
 		if (ret == 0) {
 			oobinfochanged = 2;
 		} else {
@@ -428,7 +427,7 @@ int main(int argc, char * const argv[])
 	}
 
 	// Check, if length fits into device
-	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
+	if (((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
 		fprintf(stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
 				imglen, pagelen, meminfo.writesize, meminfo.size);
 		perror("Input file does not fit into device");
@@ -451,14 +450,15 @@ int main(int argc, char * const argv[])
 	 * length or zero.
 	 */
 	while (((imglen > 0) || (writebuf < (filebuf + filebuf_len)))
-		&& (mtdoffset < meminfo.size))
-	{
-		// new eraseblock , check for bad block(s)
-		// Stay in the loop to be sure if the mtdoffset changes because
-		// of a bad block, that the next block that will be written to
-		// is also checked. Thus avoiding errors if the block(s) after the
-		// skipped block(s) is also bad (number of blocks depending on
-		// the blockalign
+		&& (mtdoffset < meminfo.size)) {
+		/*
+		 * New eraseblock, check for bad block(s)
+		 * Stay in the loop to be sure that, if mtdoffset changes because
+		 * of a bad block, the next block that will be written to
+		 * is also checked. Thus, we avoid errors if the block(s) after the
+		 * skipped block(s) is also bad (number of blocks depending on
+		 * the blockalign).
+		 */
 		while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) {
 			blockstart = mtdoffset & (~meminfo.erasesize + 1);
 			offs = blockstart;
@@ -592,14 +592,14 @@ int main(int argc, char * const argv[])
 				int i, start, len;
 				int tags_pos = 0;
 				/*
-				 *  We use autoplacement and have the oobinfo with the autoplacement
+				 * We use autoplacement and have the oobinfo with the autoplacement
 				 * information from the kernel available
 				 *
 				 * Modified to support out of order oobfree segments,
 				 * such as the layout used by diskonchip.c
 				 */
 				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
-					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
+					for (i = 0; old_oobinfo.oobfree[i][1]; i++) {
 						/* Set the reserved bytes to 0xff */
 						start = old_oobinfo.oobfree[i][0];
 						len = old_oobinfo.oobfree[i][1];
@@ -620,7 +620,7 @@ int main(int argc, char * const argv[])
 							len);
 				}
 			}
-			/* Write OOB data first, as ecc will be placed in there*/
+			/* Write OOB data first, as ecc will be placed in there */
 			oob.start = mtdoffset;
 			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
 				perror("ioctl(MEMWRITEOOB)");
-- 
1.7.0.4




From computersforpeace at gmail.com  Thu Oct 21 03:19:37 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 21 Oct 2010 00:19:37 -0700
Subject: [PATCH v2 2/2] mtd-utils: nanddump: add 64-bit support, utilize libmtd
In-Reply-To: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1287645577-13538-3-git-send-email-computersforpeace@gmail.com>

Adds support for 64-bit offsets (i.e., devices larger than 4GB).
Utilizes the "unsigned long long" data type as the standard type
for 64-bit offsets throughout. Reformats a few printf statements
to avoid casting and to properly handle "long long."

Calls to ioctls are mostly replaced by libmtd interfaces (which should
choose the proper ioctls for us); however, a few remain and probably
should be handled with more robust interfaces, as some of these
ioctls are considered "legacy."

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   83 +++++++++++++++++++++++++++++-------------------------------
 1 files changed, 40 insertions(+), 43 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 013eca0..86a71c9 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -33,6 +33,7 @@
 #include <asm/types.h>
 #include <mtd/mtd-user.h>
 #include "common.h"
+#include <libmtd.h>
 
 static struct nand_oobinfo none_oobinfo = {
 	.useecc = MTD_NANDECC_OFF,
@@ -81,7 +82,7 @@ static bool			pretty_print = false;	// print nice
 static bool			noecc = false;		// don't error correct
 static bool			noskipbad = false;	// don't skip bad blocks
 static bool			omitoob = false;	// omit oob data
-static unsigned long		start_addr;		// start address
+static unsigned long long	start_addr;		// start address
 static unsigned long		length;			// dump length
 static const char		*mtddev;		// mtd device name
 static const char		*dumpfile;		// dump file name
@@ -135,7 +136,7 @@ static void process_options(int argc, char * const argv[])
 				omitbad = true;
 				break;
 			case 's':
-				start_addr = strtoul(optarg, NULL, 0);
+				start_addr = strtoull(optarg, NULL, 0);
 				break;
 			case 'f':
 				if (!(dumpfile = strdup(optarg))) {
@@ -144,7 +145,7 @@ static void process_options(int argc, char * const argv[])
 				}
 				break;
 			case 'l':
-				length = strtoul(optarg, NULL, 0);
+				length = strtoull(optarg, NULL, 0);
 				break;
 			case 'o':
 				omitoob = true;
@@ -221,14 +222,14 @@ static void process_options(int argc, char * const argv[])
  */
 static void pretty_dump_to_buffer(const unsigned char *buf, size_t len,
 		char *linebuf, size_t linebuflen, bool pagedump, bool ascii,
-		unsigned int prefix)
+		unsigned long long prefix)
 {
 	static const char hex_asc[] = "0123456789abcdef";
 	unsigned char ch;
 	unsigned int j, lx = 0, ascii_column;
 
 	if (pagedump)
-		lx += sprintf(linebuf, "0x%.8x: ", prefix);
+		lx += sprintf(linebuf, "0x%.8llx: ", prefix);
 	else
 		lx += sprintf(linebuf, "  OOB Data: ");
 
@@ -271,20 +272,25 @@ nil:
  */
 int main(int argc, char * const argv[])
 {
-	unsigned long ofs, end_addr = 0;
+	unsigned long long ofs, end_addr = 0;
 	unsigned long long blockstart = 1;
 	int ret, i, fd, ofd = 0, bs, badblock = 0;
-	struct mtd_oob_buf oob;
-	mtd_info_t meminfo;
+	struct mtd_dev_info mtd;
 	char pretty_buf[PRETTY_BUF_LEN];
 	int oobinfochanged = 0, firstblock = 1;
 	struct nand_oobinfo old_oobinfo;
 	struct mtd_ecc_stats stat1, stat2;
 	bool eccstats = false;
 	unsigned char *readbuf = NULL, *oobbuf = NULL;
+	libmtd_t mtd_desc;
 
 	process_options(argc, argv);
 
+	/* Initialize libmtd */
+	mtd_desc = libmtd_open();
+	if (!mtd_desc)
+		return errmsg("can't initialize libmtd");
+
 	/* Open MTD device */
 	if ((fd = open(mtddev, O_RDONLY)) == -1) {
 		perror(mtddev);
@@ -292,20 +298,12 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
-		close(fd);
-		exit(EXIT_FAILURE);
-	}
+	if (mtd_get_dev_info(mtd_desc, mtddev, &mtd) < 0)
+		return errmsg("mtd_get_dev_info failed");
 
 	/* Allocate buffers */
-	oobbuf = xmalloc(sizeof(oobbuf) * meminfo.oobsize);
-	readbuf = xmalloc(sizeof(readbuf) * meminfo.writesize);
-
-	/* Fill in oob info */
-	oob.start = 0;
-	oob.length = meminfo.oobsize;
-	oob.ptr = oobbuf;
+	oobbuf = xmalloc(sizeof(oobbuf) * mtd.oob_size);
+	readbuf = xmalloc(sizeof(readbuf) * mtd.min_io_size);
 
 	if (noecc)  {
 		ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
@@ -359,27 +357,27 @@ int main(int argc, char * const argv[])
 	}
 
 	/* Initialize start/end addresses and block size */
-	if (start_addr & (meminfo.writesize - 1)) {
+	if (start_addr & (mtd.min_io_size - 1)) {
 		fprintf(stderr, "WARNING: The start address is not page-aligned !\n"
 				"The pagesize of this NAND Flash is 0x%x.\n"
 				"nandwrite doesn't allow writes starting at this location.\n"
 				"Future versions of nanddump will fail here.\n",
-				meminfo.writesize);
+				mtd.min_io_size);
 	}
 	if (length)
 		end_addr = start_addr + length;
-	if (!length || end_addr > meminfo.size)
-		end_addr = meminfo.size;
+	if (!length || end_addr > mtd.size)
+		end_addr = mtd.size;
 
-	bs = meminfo.writesize;
+	bs = mtd.min_io_size;
 
 	/* Print informative message */
 	if (!quiet) {
 		fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
-				meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
+				mtd.eb_size, mtd.min_io_size, mtd.oob_size);
 		fprintf(stderr,
-				"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
-				(unsigned int)start_addr, (unsigned int)end_addr);
+				"Dumping data starting at 0x%08llx and ending at 0x%08llx...\n",
+				start_addr, end_addr);
 	}
 
 	/* Dump the flash contents */
@@ -387,12 +385,12 @@ int main(int argc, char * const argv[])
 		/* Check for bad block */
 		if (noskipbad) {
 			badblock = 0;
-		} else if (blockstart != (ofs & (~meminfo.erasesize + 1)) ||
+		} else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
 				firstblock) {
-			blockstart = ofs & (~meminfo.erasesize + 1);
+			blockstart = ofs & (~mtd.eb_size + 1);
 			firstblock = 0;
-			if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
-				perror("ioctl(MEMGETBADBLOCK)");
+			if ((badblock = mtd_is_bad(&mtd, fd, ofs / mtd.eb_size)) < 0) {
+				errmsg("libmtd: mtd_is_bad");
 				goto closeall;
 			}
 		}
@@ -403,8 +401,8 @@ int main(int argc, char * const argv[])
 			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
-			if (pread(fd, readbuf, bs, ofs) != bs) {
-				perror("pread");
+			if (mtd_read(&mtd, fd, ofs / mtd.eb_size, ofs % mtd.eb_size, readbuf, bs)) {
+				errmsg("mtd_read");
 				goto closeall;
 			}
 		}
@@ -417,11 +415,11 @@ int main(int argc, char * const argv[])
 			}
 			if (stat1.failed != stat2.failed)
 				fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
-						" at offset 0x%08lx\n",
+						" at offset 0x%08llx\n",
 						stat2.failed - stat1.failed, ofs);
 			if (stat1.corrected != stat2.corrected)
 				fprintf(stderr, "ECC: %d corrected bitflip(s) at"
-						" offset 0x%08lx\n",
+						" offset 0x%08llx\n",
 						stat2.corrected - stat1.corrected, ofs);
 			stat1 = stat2;
 		}
@@ -440,25 +438,24 @@ int main(int argc, char * const argv[])
 			continue;
 
 		if (badblock) {
-			memset(oobbuf, 0xff, meminfo.oobsize);
+			memset(oobbuf, 0xff, mtd.oob_size);
 		} else {
 			/* Read OOB data and exit on failure */
-			oob.start = ofs;
-			if (ioctl(fd, MEMREADOOB, &oob) != 0) {
-				perror("ioctl(MEMREADOOB)");
+			if (mtd_read_oob(mtd_desc, &mtd, fd, ofs, mtd.oob_size, oobbuf)) {
+				errmsg("libmtd: mtd_read_oob");
 				goto closeall;
 			}
 		}
 
 		/* Write out OOB data */
 		if (pretty_print) {
-			for (i = 0; i < meminfo.oobsize; i += PRETTY_ROW_SIZE) {
-				pretty_dump_to_buffer(oobbuf + i, meminfo.oobsize - i,
+			for (i = 0; i < mtd.oob_size; i += PRETTY_ROW_SIZE) {
+				pretty_dump_to_buffer(oobbuf + i, mtd.oob_size - i,
 						pretty_buf, PRETTY_BUF_LEN, false, canonical, 0);
 				write(ofd, pretty_buf, strlen(pretty_buf));
 			}
 		} else
-			write(ofd, oobbuf, meminfo.oobsize);
+			write(ofd, oobbuf, mtd.oob_size);
 	}
 
 	/* reset oobinfo */
-- 
1.7.0.4




From vapier.adi at gmail.com  Thu Oct 21 03:37:00 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 21 Oct 2010 03:37:00 -0400
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style, signed-ness, 
	printing fixups
In-Reply-To: <1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTikthtaMh0qjFVLu29ZbageANnd_JsbB7wLqiMSM@mail.gmail.com>

On Thu, Oct 21, 2010 at 03:19, Brian Norris wrote:
> There were some signed/unsigned integer comparisons. Their types were
> changed for safety. Also, "strtol" was improperly used for unsigned
> data types.

dont really like these being merged, but that's obviously Artem's call, not mine

> - ? ? ? while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
> + ? ? ? do {
> ? ? ? ? ? ? ? ?linebuf[lx++] = ' ';
> + ? ? ? } while (lx < (linebuflen - 1) && lx < (ascii_column - 1));

hmm, unrelated to your changes, but i'm pretty sure this can be
rewritten into a sprintf ...
  sprintf(linebuf + lx, "%*s", (linebuflen - 1) - lx, "")
and integrating the ascii_column stuff too.  or maybe that's too complicated.
-mike


From vapier.adi at gmail.com  Thu Oct 21 03:37:58 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 21 Oct 2010 03:37:58 -0400
Subject: [PATCH v2 0/2] mtd-utils fixups
In-Reply-To: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
References: <AANLkTikXF5CV8SFOC5Ygzw4fNBvgzbifQK2eeH7D1bbM@mail.gmail.com>
	<1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <AANLkTimcXhbGTaMN747SFi7XNimRok9NFzShpHMJqF4k@mail.gmail.com>

looks straight forward to me (other than the one note).  thanks !
-mike


From bigeasy at linutronix.de  Thu Oct 21 04:23:01 2010
From: bigeasy at linutronix.de (Sebastian Andrzej Siewior)
Date: Thu, 21 Oct 2010 10:23:01 +0200
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <1287581218.9272.67.camel@localhost>
References: <20101013163005.GB1889@silverbox.local>
	<1287581218.9272.67.camel@localhost>
Message-ID: <4CBFF865.9010706@linutronix.de>

Artem Bityutskiy wrote:
>> From a quick glance at the ubifs code, this might come out of the
>> garbage collector that is triggered on every sync() and writes
>> something even if nothing has changed.
>>
>> Is that really needed?
> 
> I briefly looked, and UBIFS is doing a lot of I/O in that case, which is
> unnecessary and should not be done, I'll need to investigate this.

 From what I've seen from the code there are two parts:
- writing "unwritten" data (the write back part I guess). Nothing is done
   here as long as no data is queued
- writing the journal. The first step seems to be to write a node "begin
   write" and the last one is "end write".

Since hjk sees only two erases I would guess that they are initiated by 
the "journal begin" & "end" requests.

Thanks for looking at this.

Sebastian


From dedekind1 at gmail.com  Thu Oct 21 04:32:11 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 11:32:11 +0300
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <4CBFF865.9010706@linutronix.de>
References: <20101013163005.GB1889@silverbox.local>
	<1287581218.9272.67.camel@localhost> <4CBFF865.9010706@linutronix.de>
Message-ID: <1287649931.2932.3.camel@localhost>

On Thu, 2010-10-21 at 10:23 +0200, Sebastian Andrzej Siewior wrote:
> Artem Bityutskiy wrote:
> >> From a quick glance at the ubifs code, this might come out of the
> >> garbage collector that is triggered on every sync() and writes
> >> something even if nothing has changed.
> >>
> >> Is that really needed?
> > 
> > I briefly looked, and UBIFS is doing a lot of I/O in that case, which is
> > unnecessary and should not be done, I'll need to investigate this.
> 
>  From what I've seen from the code there are two parts:
> - writing "unwritten" data (the write back part I guess). Nothing is done
>    here as long as no data is queued
> - writing the journal. The first step seems to be to write a node "begin
>    write" and the last one is "end write".
> 
> Since hjk sees only two erases I would guess that they are initiated by 
> the "journal begin" & "end" requests.

Yeah, the UBIFS must be writing the commit start and commit end nodes,
and then erasing the previous log LEB (all this is done in log.c). As
soon as I have time I'll look at this, I really do not have time right
now. And there is Matthiew's problem which is actually quite big, but
for some reasons affects only him :-)

May be it is just matter of looking at all journal heads and if they are
empty, do nothing and return from ubifs_commit().

Adrian, would you help with this, may be?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Oct 21 04:39:58 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 11:39:58 +0300
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for
	Lock/Unlock bug.
In-Reply-To: <1287498263-5561-1-git-send-email-phdm@macqel.be>
References: <1287498263-5561-1-git-send-email-phdm@macqel.be>
Message-ID: <1287650398.2932.5.camel@localhost>

On Tue, 2010-10-19 at 16:24 +0200, Philippe De Muyter wrote:
> Some flash chips have a small but annoying bug, documented in
>     "Numonyx Axcell P33/P30 256-Mbit Specification Update"
> 
>     It states :
>     When customer uses [...] block unlock, the block lock status might
>     be altered inadvertently. Lock status might be set to either 01h
>     or 03h unexpectedly (00h as expected data), which leads to
>     program/erase failure on certain blocks.
> 
>     A workaround is given, (summary : issue a "Read Lock Status" before
>     the "Lock" or "Unlock" command) which I have applied and tested
>     with success.
> 
> Signed-off-by: Philippe De Muyter <phdm at macqel.be>

Is this Numonyx-specific issue? Should there be some kind of "if
(numonyx)" statement?

May be Nicolas could validate the patch?

> ---
>  drivers/mtd/chips/cfi_cmdset_0001.c |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
> index 9e2b7e9..0d0ae41 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0001.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0001.c
> @@ -2047,6 +2047,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
>  {
>  	struct cfi_private *cfi = map->fldrv_priv;
>  	struct cfi_pri_intelext *extp = cfi->cmdset_priv;
> +	int ofs_factor = cfi->interleave * cfi->device_type;
>  	int udelay;
>  	int ret;
>  
> @@ -2062,6 +2063,14 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
>  	ENABLE_VPP(map);
>  	xip_disable(map, chip, adr);
>  
> +	/*
> +	 * Issue a "Read Lock Status" before the "Lock" or "Unlock" :
> +	 * see errata "Numonyx Axcell P33/P30 Specification Update" :)
> +	 */
> +	map_write(map, CMD(0x90), adr+(2*ofs_factor));
> +	chip->state = FL_JEDEC_QUERY;
> +	cfi_read_query(map, adr+(2*ofs_factor));
> +
>  	map_write(map, CMD(0x60), adr);
>  	if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) {
>  		map_write(map, CMD(0x01), adr);

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Thu Oct 21 04:57:28 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 11:57:28 +0300
Subject: [PATCH] mtd: OneNAND: S5PC110: Fix double call suspend &
	resume function
In-Reply-To: <20101020083102.GA30414@july>
References: <20101020083102.GA30414@july>
Message-ID: <1287651448.2932.7.camel@localhost>

On Wed, 2010-10-20 at 17:31 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> The suspend & resume called from mtd core. So no need to call at driver.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>

Pushed this one to my l2 tree, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From phdm at macqel.be  Thu Oct 21 05:33:43 2010
From: phdm at macqel.be (Philippe De Muyter)
Date: Thu, 21 Oct 2010 11:33:43 +0200
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for
	Lock/Unlock bug.
In-Reply-To: <1287650398.2932.5.camel@localhost>
References: <1287498263-5561-1-git-send-email-phdm@macqel.be>
	<1287650398.2932.5.camel@localhost>
Message-ID: <20101021093343.GA17631@frolo.macqel>

On Thu, Oct 21, 2010 at 11:39:58AM +0300, Artem Bityutskiy wrote:
> On Tue, 2010-10-19 at 16:24 +0200, Philippe De Muyter wrote:
> > Some flash chips have a small but annoying bug, documented in
> >     "Numonyx Axcell P33/P30 256-Mbit Specification Update"
> > 
> >     It states :
> >     When customer uses [...] block unlock, the block lock status might
> >     be altered inadvertently. Lock status might be set to either 01h
> >     or 03h unexpectedly (00h as expected data), which leads to
> >     program/erase failure on certain blocks.
> > 
> >     A workaround is given, (summary : issue a "Read Lock Status" before
> >     the "Lock" or "Unlock" command) which I have applied and tested
> >     with success.
> > 
> > Signed-off-by: Philippe De Muyter <phdm at macqel.be>
> 
> Is this Numonyx-specific issue? Should there be some kind of "if
> (numonyx)" statement?

This is clearly a bug specific to some Numonyx flashes.
My chips have Manufacturer ID: 0x89, Device ID: 0x881B, but there are
other chips in the same family.  The errata
http://www.numonyx.com/Documents/Specification%20Updates/509003_P3X_65nm_3V_256Mbit_Discrete.pdf does not list the ManufacturerIDs/DeviceIDs of the affected
chips.

Philippe

-- 
Philippe De Muyter  phdm at macqel dot be  Tel +32 27029044
Macq Electronique SA  rue de l'Aeronef 2  B-1140 Bruxelles  Fax +32 27029077


From dedekind1 at gmail.com  Thu Oct 21 06:29:43 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 13:29:43 +0300
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for
	Lock/Unlock bug.
In-Reply-To: <20101021093343.GA17631@frolo.macqel>
References: <1287498263-5561-1-git-send-email-phdm@macqel.be>
	<1287650398.2932.5.camel@localhost>
	<20101021093343.GA17631@frolo.macqel>
Message-ID: <1287656983.2932.14.camel@localhost>

On Thu, 2010-10-21 at 11:33 +0200, Philippe De Muyter wrote:
> On Thu, Oct 21, 2010 at 11:39:58AM +0300, Artem Bityutskiy wrote:
> > On Tue, 2010-10-19 at 16:24 +0200, Philippe De Muyter wrote:
> > > Some flash chips have a small but annoying bug, documented in
> > >     "Numonyx Axcell P33/P30 256-Mbit Specification Update"
> > > 
> > >     It states :
> > >     When customer uses [...] block unlock, the block lock status might
> > >     be altered inadvertently. Lock status might be set to either 01h
> > >     or 03h unexpectedly (00h as expected data), which leads to
> > >     program/erase failure on certain blocks.
> > > 
> > >     A workaround is given, (summary : issue a "Read Lock Status" before
> > >     the "Lock" or "Unlock" command) which I have applied and tested
> > >     with success.
> > > 
> > > Signed-off-by: Philippe De Muyter <phdm at macqel.be>
> > 
> > Is this Numonyx-specific issue? Should there be some kind of "if
> > (numonyx)" statement?
> 
> This is clearly a bug specific to some Numonyx flashes.
> My chips have Manufacturer ID: 0x89, Device ID: 0x881B, but there are
> other chips in the same family.  The errata
> http://www.numonyx.com/Documents/Specification%20Updates/509003_P3X_65nm_3V_256Mbit_Discrete.pdf does not list the ManufacturerIDs/DeviceIDs of the affected
> chips.

CCed Nicolas correctly.

Anyway, if this affects only subset of chips, it make sense to make this
quirk conditional, because this might affect boot speed, e.g., if some
systems unlock all blocks on boot-up.

Nicolas, the original patch was here, would you validate it please?
http://lists.infradead.org/pipermail/linux-mtd/2010-October/032783.html

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Thu Oct 21 06:33:33 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Thu, 21 Oct 2010 12:33:33 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
Message-ID: <AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>

2010/10/18 Guillaume LECERF <glecerf at gmail.com>:
> 2010/10/18 Wolfram Sang <w.sang at pengutronix.de>:
>>> ? ?The 39VF*-B-Version flashes in the cfi_nopri_fixup_table don't work
>>> well in the current code. ?Because of the mistaken use of
>>> command(0x30) in the 6th bus cycle, which should be 0x50. I think the
>>> 39VF*-B-Version flashes should be removed form the CFI probe mode. Or
>>> maybe the erase operation should be changed for the Compatibility.
>>
>> Or we put in a variable like the unlock-address?
>
> I'm OK with solution, that's what I try to implement atm, but I'm
> still looking for the right place to put this variable.

Hi.
Could you try the attached patches ?
Note: it's totally untested.

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: erase-command.patch
Type: application/octet-stream
Size: 2777 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101021/dff3b46e/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sst38vf640x.patch
Type: application/octet-stream
Size: 969 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101021/dff3b46e/attachment-0001.obj>

From dedekind1 at gmail.com  Thu Oct 21 06:37:32 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 13:37:32 +0300
Subject: [PATCH] drivers/mtd/devices/phram.c: Use KBUILD_MODNAME
In-Reply-To: <1287596362.1813.205.camel@Joe-Laptop>
References: <1287596362.1813.205.camel@Joe-Laptop>
Message-ID: <1287657452.2932.15.camel@localhost>

On Wed, 2010-10-20 at 10:39 -0700, Joe Perches wrote:
> Use the more standard #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> No change in output strings.
> 
> Signed-off-by: Joe Perches <joe at perches.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Thu Oct 21 06:40:41 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Thu, 21 Oct 2010 12:40:41 +0200
Subject: [PATCH] [MTD] cfi_cmdset_0002: code cleanups
In-Reply-To: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>
References: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>
Message-ID: <AANLkTi=kX7aAbY-5XNF0dKngXmAPXL-UisGGfjOimKdo@mail.gmail.com>

2010/10/16 Wolfram Sang <w.sang at pengutronix.de>:
> - remove disabled code (hasn't been touched since the beginning of git
> ?and should be reimplemented if really needed)
> - convert remaining c++-comments to plain c-style
>
> Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
> Cc: yidong zhang <zhangyd6 at gmail.com>
> Cc: Guillaume LECERF <glecerf at gmail.com>
> Cc: David Woodhouse <David.Woodhouse at intel.com>

Acked-by: Guillaume LECERF <glecerf at gmail.com>

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From dedekind1 at gmail.com  Thu Oct 21 10:01:54 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 17:01:54 +0300
Subject: [PATCH] [MTD] cfi_cmdset_0002: code cleanups
In-Reply-To: <AANLkTi=kX7aAbY-5XNF0dKngXmAPXL-UisGGfjOimKdo@mail.gmail.com>
References: <1287233782-21319-1-git-send-email-w.sang@pengutronix.de>
	<AANLkTi=kX7aAbY-5XNF0dKngXmAPXL-UisGGfjOimKdo@mail.gmail.com>
Message-ID: <1287669714.2932.20.camel@localhost>

On Thu, 2010-10-21 at 12:40 +0200, Guillaume LECERF wrote:
> 2010/10/16 Wolfram Sang <w.sang at pengutronix.de>:
> > - remove disabled code (hasn't been touched since the beginning of git
> >  and should be reimplemented if really needed)
> > - convert remaining c++-comments to plain c-style
> >
> > Signed-off-by: Wolfram Sang <w.sang at pengutronix.de>
> > Cc: yidong zhang <zhangyd6 at gmail.com>
> > Cc: Guillaume LECERF <glecerf at gmail.com>
> > Cc: David Woodhouse <David.Woodhouse at intel.com>
> 
> Acked-by: Guillaume LECERF <glecerf at gmail.com>

Added your ack to my tree as well.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From pratyush.anand at st.com  Thu Oct 21 10:18:28 2010
From: pratyush.anand at st.com (Pratyush ANAND)
Date: Thu, 21 Oct 2010 22:18:28 +0800
Subject: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
In-Reply-To: <20101019144725.977297f5.akpm@linux-foundation.org>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<c91308e26397dbe49f384c7d3cf168593e1fe8b0.1285933332.git.viresh.kumar@st.com>
	<20101019144725.977297f5.akpm@linux-foundation.org>
Message-ID: <0901B62280FF37468247D8348744254F449565AA97@EAPEX1MAIL1.st.com>



> -----Original Message-----
> From: Andrew Morton [mailto:akpm at linux-foundation.org]
> Sent: Wednesday, October 20, 2010 3:17 AM
> To: Viresh KUMAR
> Cc: linux-arm-kernel at lists.infradead.org; rtc-linux at googlegroups.com;
> a.zummo at towertech.it; dbrownell at users.sourceforge.net; linux-
> usb at vger.kernel.org; linux-input at vger.kernel.org;
> dmitry.torokhov at gmail.com; linux-mtd at lists.infradead.org;
> dwmw2 at infradead.org; linux-kernel at vger.kernel.org; Pratyush ANAND; Shiraz
> HASHIM; Vipin KUMAR; Deepak SIKRI; Armando VISCONTI; Vipul Kumar SAMAR;
> Rajeev KUMAR; Bhupesh SHARMA
> Subject: Re: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
>
> On Fri,  1 Oct 2010 17:26:05 +0530
> Viresh KUMAR <viresh.kumar at st.com> wrote:
>
> > From: Pratyush Anand <pratyush.anand at st.com>
> >
> > This is a configurable gadget. can be configured by sysfs interface. Any
> > IP available at PCIE bus can be programmed to be used by host
> > controller.It supoorts both INTX and MSI.
> > By default, gadget is configured for INTX and SYSRAM1 is mapped to BAR0
> > with size 0x1000
> >
> >
> > ...
> >
> > +static void enable_dbi_access(struct pcie_app_reg *app_reg)
>
> app_reg should have the __iomem tag.
>
Ok.
> > +{
> > +   /* Enable DBI access */
> > +   writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
> > +                   &app_reg->slv_armisc);
> > +   writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
> > +                   &app_reg->slv_awmisc);
> > +
> > +}
> > +
> > +static void disable_dbi_access(struct pcie_app_reg *app_reg)
>
> ditto
>
Ok.
> > +{
> > +   /* disable DBI access */
> > +   writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
> > +                   &app_reg->slv_armisc);
> > +   writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
> > +                   &app_reg->slv_awmisc);
> > +
> > +}
> > +
> > +static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
> > +           int where, int size, u32 *val)
> > +{
> > +   struct pcie_app_reg *app_reg
> > +           = (struct pcie_app_reg *) config->va_app_base;
>
> ditto
>
ok
> > +   u32 va_address;
> > +
> > +   /* Enable DBI access */
> > +   enable_dbi_access(app_reg);
> > +
> > +   va_address = (u32)config->va_dbi_base + (where & ~0x3);
> > +
> > +   *val = readl(va_address);
> > +
> > +   if (size == 1)
> > +           *val = (*val >> (8 * (where & 3))) & 0xff;
> > +   else if (size == 2)
> > +           *val = (*val >> (8 * (where & 3))) & 0xffff;
> > +
> > +   /* Disable DBI access */
> > +   disable_dbi_access(app_reg);
> > +}
> > +
> > +static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
> > +           int where, int size, u32 val)
> > +{
> > +   struct pcie_app_reg *app_reg
> > +           = (struct pcie_app_reg *) config->va_app_base;
>
> etc.
>
ok
> > +   u32 va_address;
> > +
> > +   /* Enable DBI access */
> > +   enable_dbi_access(app_reg);
> > +
> > +   va_address = (u32)config->va_dbi_base + (where & ~0x3);
> > +
> > +   if (size == 4)
> > +           writel(val, va_address);
> > +   else if (size == 2)
> > +           writew(val, va_address + (where & 2));
> > +   else if (size == 1)
> > +           writeb(val, va_address + (where & 3));
> > +
> > +   /* Disable DBI access */
> > +   disable_dbi_access(app_reg);
> > +}
> > +
> >
> > ...
> >
> > +/**
>
> This token is specifically used to introduce a kerneldoc comment, but
> this wasn't a kerneldoc comment.
>
> > + * Tell if a device supports a given PCI capability.
> > + * Returns the address of the requested capability structure within the
> > + * device's PCI configuration space or 0 in case the device does not
> > + * support it. Possible values for @cap:
> > + *
> > + * %PCI_CAP_ID_PM  Power Management
> > + * %PCI_CAP_ID_AGP Accelerated Graphics Port
> > + * %PCI_CAP_ID_VPD Vital Product Data
> > + * %PCI_CAP_ID_SLOTID      Slot Identification
> > + * %PCI_CAP_ID_MSI Message Signalled Interrupts
> > + * %PCI_CAP_ID_CHSWP       CompactPCI HotSwap
> > + * %PCI_CAP_ID_PCIX        PCI-X
> > + * %PCI_CAP_ID_EXP PCI Express
> > + */
> >
> > ...
> >
> > +
> > +static ssize_t pcie_gadget_show_link(struct device *dev,
> > +           struct device_attribute *attr, char *buf)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
>
> Check all the __iomems;
>
Ok.
> > +   if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
> > +           return sprintf(buf, "UP");
> > +   else
> > +           return sprintf(buf, "DOWN");
> > +}
> > +
> > +static ssize_t pcie_gadget_store_link(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
> > +   char link[10];
> > +
> > +   if (sscanf(buf, "%s", link) != 1)
>
> What happens if strlen(buf) >= 10?
>
Will return -EINVAL for strlen(buf) >= 0.
> > +           return -EINVAL;
> > +
> > +   if (!strcmp(link, "UP"))
> > +           writel(readl(&app_reg->app_ctrl_0) | (1 <<
> APP_LTSSM_ENABLE_ID),
> > +                   &app_reg->app_ctrl_0);
> > +   else
> > +           writel(readl(&app_reg->app_ctrl_0)
> > +                           & ~(1 << APP_LTSSM_ENABLE_ID),
> > +                           &app_reg->app_ctrl_0);
> > +   return count;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_store_int_type(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   char int_type[10];
> > +   u32 cap, vector, vec, flags;
> > +
> > +   if (sscanf(buf, "%s", int_type) != 1)
>
> ditto
Will return -EINVAL for strlen(buf) >= 0.
>
> > +           return -EINVAL;
> > +
> > +   if (!strcmp(int_type, "INTA"))
> > +           spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
> > +
> > +   else if (!strcmp(int_type, "MSI")) {
> > +           vector = config->requested_msi;
> > +           vec = 0;
> > +           while (vector > 1) {
> > +                   vector /= 2;
> > +                   vec++;
> > +           }
> > +           spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
> > +           cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
> > +           spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
> > +           flags &= ~PCI_MSI_FLAGS_QMASK;
> > +           flags |= vec << 1;
> > +           spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
> > +   }
>
> No checking for unrecognised input?
>
Will return -EINVAL for other inputs.

> > +   strcpy(config->int_type, int_type);
> > +
> > +   return count;
> > +}
> > +
> > +static DEVICE_ATTR(int_type, S_IWUSR | S_IRUGO,
> pcie_gadget_show_int_type,
> > +           pcie_gadget_store_int_type);
> > +
> > +static ssize_t pcie_gadget_show_no_of_msi(struct device *dev,
> > +           struct device_attribute *attr, char *buf)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
>
> __iomem
>
> > +   u32 cap, vector, vec, flags;
> > +
> > +   if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
> > +                   != (1 << CFG_MSI_EN_ID))
> > +           vector = 0;
> > +   else {
> > +           cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
> > +           spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
> > +           flags &= ~PCI_MSI_FLAGS_QSIZE;
> > +           vec = flags >> 4;
> > +           vector = 1;
> > +           while (vec--)
> > +                   vector *= 2;
> > +   }
> > +   config->configured_msi = vector;
> > +
> > +   return sprintf(buf, "%u", vector);
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_store_inta(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
> > +   int en;
> > +
> > +   if (sscanf(buf, "%d", &en) != 1)
>
> strict_strtoul() would be better.  It will reject input of the form
> "42foo".
>
Ok..will use strict_strtoul.
> > +           return -EINVAL;
> > +
> > +   if (en)
> > +           writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
> > +                           &app_reg->app_ctrl_0);
> > +   else
> > +           writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
> > +                           &app_reg->app_ctrl_0);
> > +
> > +   return count;
> > +}
> > +
> > +static DEVICE_ATTR(inta, S_IWUSR, NULL, pcie_gadget_store_inta);
> > +
> > +static ssize_t pcie_gadget_store_send_msi(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
> > +   int vector;
> > +   u32 ven_msi;
> > +
> > +   if (sscanf(buf, "%d", &vector) != 1)
>
> strict_strtoul().
>
Ok..will use strict_strtoul().
> > +           return -EINVAL;
> > +
> > +   if (!config->configured_msi)
> > +           return -EINVAL;
> > +
> > +   if (vector >= config->configured_msi)
> > +           return -EINVAL;
> > +
> > +   ven_msi = readl(&app_reg->ven_msi_1);
> > +   ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
> > +   ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
> > +   ven_msi &= ~VEN_MSI_TC_MASK;
> > +   ven_msi |= 0 << VEN_MSI_TC_ID;
> > +   ven_msi &= ~VEN_MSI_VECTOR_MASK;
> > +   ven_msi |= vector << VEN_MSI_VECTOR_ID;
> > +
> > +   /*generating interrupt for msi vector*/
> > +   ven_msi |= VEN_MSI_REQ_EN;
> > +   writel(ven_msi, &app_reg->ven_msi_1);
> > +   /*need to wait till this bit is cleared, it is not cleared
> > +    * autometically[Bug RTL] TBD*/
> > +   udelay(1);
> > +   ven_msi &= ~VEN_MSI_REQ_EN;
> > +   writel(ven_msi, &app_reg->ven_msi_1);
> > +
> > +   return count;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_store_vendor_id(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   u32 id;
> > +
> > +   if (sscanf(buf, "%x", &id) != 1)
>
> strict_strtoul can be used here as well?
>
Ok..will use strict_strtoul().
> > +           return -EINVAL;
> > +
> > +   spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
> > +
> > +   return count;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_store_device_id(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   u32 id;
> > +
> > +   if (sscanf(buf, "%x", &id) != 1)
>
> etc.
>
Ok..will use strict_strtoul().
> > +           return -EINVAL;
> > +
> > +   spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
> > +
> > +   return count;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_store_bar0_size(struct device *dev,
> > +           struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   u32 size, pos, pos1;
> > +   u32 no_of_bit = 0;
> > +
> > +   if (sscanf(buf, "%x", &size) != 1)
>
> etc.
>
Ok..will use strict_strtoul().
> > +           return -EINVAL;
> > +   /* as per PCIE specs, min bar size supported is 128 bytes. But
> > +    * our controller supports min as 256*/
> > +   if (size <= 0x100)
> > +           size = 0x100;
> > +   /* max bar size is 1MB*/
> > +   else if (size >= 0x100000)
> > +           size = 0x100000;
> > +   else {
> > +           pos = 0;
> > +           pos1 = 0;
> > +           while (pos < 21) {
> > +                   pos = find_next_bit((unsigned long *)&size, 21, pos);
> > +                   if (pos != 21)
> > +                           pos1 = pos + 1;
> > +                   pos++;
> > +                   no_of_bit++;
> > +           }
> > +           if (no_of_bit == 2)
> > +                   pos1--;
> > +
> > +           size = 1 << pos1;
> > +   }
> > +   config->bar0_size = size;
> > +   spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
> > +
> > +   return count;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_show_bar0_address(struct device *dev,
> > +           struct device_attribute *attr, char *buf)
> > +{
> > +   struct spear_pcie_gadget_config *config = dev_get_drvdata(dev);
> > +   struct pcie_app_reg *app_reg =
> > +           (struct pcie_app_reg *)config->va_app_base;
>
> etc
>
Ok..will use __iomem
> > +   u32 address = readl(&app_reg->pim0_mem_addr_start);
> > +
> > +   return sprintf(buf, "%x", address);
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pcie_gadget_show_help(struct device *dev,
> > +           struct device_attribute *attr, char *buf)
> > +{
> > +   char text[] = "\t\tlink read->ltssm status\n \
> > +           link write->arg1 = UP to enable ltsmm DOWN to disable\n \
> > +           int_type read->type of supported interrupt\n \
> > +           int_type write->arg1 = interrupt type to be configured and\n \
> > +           can be INTA, MSI or NO_INT\n \
> > +           (select MSI only when you have programmed no_of_msi)\n \
> > +           no_of_msi read->zero if MSI is not enabled by host\n \
> > +           and positive value is the number of MSI vector granted\n \
> > +           no_of_msi write->arg1 = number of MSI vector needed\n \
> > +           inta write->arg1 = 1 to assert INTA and 0 to de-assert\n \
> > +           send_msi write->arg1 = MSI vector to be send\n \
> > +           vendor_id read->programmed vendor id (hex)\n\
> > +           vendor_id write->arg1 = vendor id(hex) to be programmed\n \
> > +           device_id read->programmed device id(hex)\n \
> > +           device_id write->arg1 = device id(hex) to be programmed\n \
> > +           bar0_size read->size of bar0 in hex\n \
> > +           bar0_size write->arg1= size of bar0 in hex\n \
> > +           (default bar0 size is 1000 (hex) bytes)\n \
> > +           bar0_address read->address of bar0 mapped area in hex\n \
> > +           bar0_address write->arg1 = address of bar0 mapped area in
> hex\n\
> > +           (default mapping of bar0 is SYSRAM1(E0800000)\n \
> > +           (always program bar size before bar address)\n \
> > +           (kernel might modify bar size and address to align)\n \
> > +           (read back bar size and address after writing to check)\n \
> > +           bar0_rw_offset read->offset of bar0 for which bar0_data \n \
> > +           will return value\n \
> > +           bar0_rw_offset write->arg1 = offset of bar0 for which\n \
> > +           bar0_data will write value\n \
> > +           bar0_data read->data at bar0_rw_offset\n \
> > +           bar0_data write->arg1 = data to be written at\n \
> > +           bar0_rw_offset\n";
> > +
> > +   int size = (sizeof(text) < PAGE_SIZE) ? sizeof(text) : PAGE_SIZE;
> > +
> > +   return snprintf(buf, size, "%s", text);
> > +}
>
> What the heck is this??
>

This was just to provide help for different sysfs nodes. What could be the other
Way to do it? Should it be better to remove help node from here provide all the help
In a separate document?

> > +static DEVICE_ATTR(help, S_IRUGO, pcie_gadget_show_help, NULL);
> > +
> > +static struct attribute *pcie_gadget_attributes[] = {
> > +   &dev_attr_link.attr,
> > +   &dev_attr_int_type.attr,
> > +   &dev_attr_no_of_msi.attr,
> > +   &dev_attr_inta.attr,
> > +   &dev_attr_send_msi.attr,
> > +   &dev_attr_vendor_id.attr,
> > +   &dev_attr_device_id.attr,
> > +   &dev_attr_bar0_size.attr,
> > +   &dev_attr_bar0_address.attr,
> > +   &dev_attr_bar0_rw_offset.attr,
> > +   &dev_attr_bar0_data.attr,
> > +   &dev_attr_help.attr,
> > +   NULL
> > +};
> > +
> >
> > ...
> >
> > +static int __devinit spear_pcie_gadget_probe(struct platform_device
> *pdev)
> > +{
> > +   struct resource *res0, *res1;
> > +   struct spear_pcie_gadget_config *config;
> > +   unsigned int status = 0;
> > +   int irq;
> > +   struct clk *clk;
> > +
> > +   /* get resource for application registers*/
> > +
> > +   res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +   if (!res0) {
> > +           dev_err(&pdev->dev, "no resource defined\n");
> > +           return -EBUSY;
> > +   }
> > +   if (!request_mem_region(res0->start, resource_size(res0),
> > +                           pdev->name)) {
> > +           dev_err(&pdev->dev, "pcie gadget region already claimed\n");
> > +           return -EBUSY;
> > +   }
> > +   /* get resource for dbi registers*/
> > +
> > +   res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +   if (!res1) {
> > +           dev_err(&pdev->dev, "no resource defined\n");
> > +           goto err_rel_res0;
> > +   }
> > +   if (!request_mem_region(res1->start, resource_size(res1),
> > +                           pdev->name)) {
> > +           dev_err(&pdev->dev, "pcie gadget region already claimed\n");
> > +           goto err_rel_res0;
> > +   }
> > +
> > +   config = kzalloc(sizeof(*config), GFP_KERNEL);
> > +   if (!config) {
> > +           dev_err(&pdev->dev, "out of memory\n");
> > +           status = -ENOMEM;
> > +           goto err_rel_res;
> > +   }
> > +
> > +   config->va_app_base = ioremap(res0->start, resource_size(res0));
> > +   if (!config->va_app_base) {
> > +           dev_err(&pdev->dev, "ioremap fail\n");
> > +           status = -ENOMEM;
> > +           goto err_kzalloc;
> > +   }
> > +
> > +   config->base = (void *)res1->start;
>
> Is that __iomem?
>
Will use __iomem here too.

> > +   config->va_dbi_base = ioremap(res1->start, resource_size(res1));
> > +   if (!config->va_dbi_base) {
> > +           dev_err(&pdev->dev, "ioremap fail\n");
> > +           status = -ENOMEM;
> > +           goto err_iounmap_app;
> > +   }
> > +
> > +   dev_set_drvdata(&pdev->dev, config);
> > +
> > +   irq = platform_get_irq(pdev, 0);
> > +   if (irq < 0) {
> > +           dev_err(&pdev->dev, "no update irq?\n");
> > +           status = irq;
> > +           goto err_iounmap;
> > +   }
> > +
> > +   status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name,
> NULL);
> > +   if (status) {
> > +           dev_err(&pdev->dev, "pcie gadget interrupt IRQ%d already \
> > +                           claimed\n", irq);
> > +           goto err_get_irq;
> > +   }
> > +   /* Register sysfs hooks */
> > +   status = sysfs_create_group(&pdev->dev.kobj,
> &pcie_gadget_attr_group);
> > +   if (status)
> > +           goto err_irq;
> > +
> > +   /* init basic pcie application registers*/
> > +   /* do not enable clock if it is PCIE0.Ideally , all controller should
> > +    * have been independent from others with respect to clock. But PCIE1
> > +    * and 2 depends on PCIE0.So PCIE0 clk is provided during board
> init.*/
> > +   if (pdev->id == 1) {
> > +           /* Ideally CFG Clock should have been also enabled here. But
> > +            * it is done currently during board init routne*/
> > +           clk = clk_get_sys("pcie1", NULL);
> > +           if (!clk) {
> > +                   pr_err("%s:couldn't get clk for pcie1\n", __func__);
> > +                   goto err_irq;
> > +           }
> > +           if (clk_enable(clk)) {
> > +                   pr_err("%s:couldn't enable clk for pcie1\n", __func__);
> > +                   goto err_irq;
> > +           }
> > +   } else if (pdev->id == 2) {
> > +           /* Ideally CFG Clock should have been also enabled here. But
> > +            * it is done currently during board init routne*/
> > +           clk = clk_get_sys("pcie2", NULL);
> > +           if (!clk) {
> > +                   pr_err("%s:couldn't get clk for pcie2\n", __func__);
> > +                   goto err_irq;
> > +           }
> > +           if (clk_enable(clk)) {
> > +                   pr_err("%s:couldn't enable clk for pcie2\n", __func__);
> > +                   goto err_irq;
> > +           }
> > +   }
> > +   spear13xx_pcie_device_init(config);
> > +
> > +   return 0;
> > +err_irq:
> > +   free_irq(irq, NULL);
> > +err_get_irq:
> > +   dev_set_drvdata(&pdev->dev, NULL);
> > +err_iounmap:
> > +   iounmap(config->va_dbi_base);
> > +err_iounmap_app:
> > +   iounmap(config->va_app_base);
> > +err_kzalloc:
> > +   kfree(config);
> > +err_rel_res:
> > +   release_mem_region(res1->start, resource_size(res1));
> > +err_rel_res0:
> > +   release_mem_region(res0->start, resource_size(res0));
> > +   return status;
> > +}
> > +
> >
> > ...
> >
>
> The driver implements a large, complex userspace interface and afaict
> that interface wasn't documented anywhere.
>
> But the interface is the most important part of the driver!  It should
> be documented in a permanent fashion so that reviewers can understand
> and review your proposed interface.  They will want to do that before
> even looking at the code.
Ok..Will write Documentation/misc-devices/spear_pcie_gadget.txt.


From zhangyd6 at gmail.com  Thu Oct 21 22:53:42 2010
From: zhangyd6 at gmail.com (zhangyd)
Date: Thu, 21 Oct 2010 22:53:42 -0400
Subject: [PATCH] mtd: chips: add SST38VF640x nor-flashes
Message-ID: <1287716022-2792-1-git-send-email-zhangyd6@gmail.com>

Due to broken CFI, these flashes should be operated in jedec probe mode.
When you operate them in the CFI probe mode, you will get the wrong sector
size.And it will fail to set up the flash during the probe(CFI mode).
And i have tested it on my platform.

Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
---
 drivers/mtd/chips/jedec_probe.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index d72a5fb..21f07da 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -163,6 +163,7 @@
 #define SST49LF030A	0x001C
 #define SST49LF040A	0x0051
 #define SST49LF080A	0x005B
+#define SST38VF6401	0x536B
 #define SST36VF3203	0x7354
 
 /* Toshiba */
@@ -1557,6 +1558,18 @@ static const struct amd_flash_info jedec_table[] = {
 		}
 	}, {
 		.mfr_id		= CFI_MFR_SST,
+		.dev_id		= SST38VF6401,
+		.name		= "SST 38VF6401",
+		.devtypes	= CFI_DEVICETYPE_X16,
+		.uaddr		= MTD_UADDR_0x0AAA_0x0555,
+		.dev_size	= SIZE_8MiB,
+		.cmd_set	= P_ID_AMD_STD,
+		.nr_regions	= 1,
+		.regions	= {
+			ERASEINFO(0x10000,128),
+		}
+	}, {
+		.mfr_id		= CFI_MFR_SST,
 		.dev_id		= SST36VF3203,
 		.name		= "SST 36VF3203",
 		.devtypes	= CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8,
-- 
1.7.2.3



From glecerf at gmail.com  Thu Oct 21 11:24:11 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Thu, 21 Oct 2010 17:24:11 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
Message-ID: <AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>

2010/10/21 yidong zhang <zhangyd6 at gmail.com>:
>> Hi.
>> The patch use the fixup_sst39vf_rev_b() function which calls
>> fixup_old_sst_eraseregion().
>> It sets the NumEraseRegions to 1, thus CFI reports only the 1st erase
>> region, i.e. the one calculated with the sector information (8KByte).
>>
>> Did you actually tested it with a real chip ?
>
> Yes, i did test both SST39VF6401B and SST38VF6401 a moment ago; The
> SST39VF6401B works fine. But the SST38VF6401 couldn't work because of
> the sector-size.It was 64KByte when i displayed the erase size.

Could you send me your log with SST38VF6401 please ?
I need to investigate on this.

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From linux at dominikbrodowski.net  Thu Oct 21 11:35:23 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:23 +0200
Subject: [PATCH 07/22] pcmcia: move config_{base, index,
	regs} to struct pcmcia_device
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-7-git-send-email-linux@dominikbrodowski.net>

Several drivers prefer to explicitly set config_{base,index,regs},
formerly known as ConfigBase, ConfigIndex and Present. Instead of
passing these values inside config_req_t, store it in struct
pcmcia_device.

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-ide at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: laforge at gnumonks.org
CC: linux-mtd at lists.infradead.org
CC: alsa-devel at alsa-project.org
CC: linux-serial at vger.kernel.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan at profusion.mobi> (for drivers/bluetooth)
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/bluetooth/bluecard_cs.c                  |    2 +-
 drivers/char/pcmcia/ipwireless/main.c            |    2 +-
 drivers/char/pcmcia/synclink_cs.c                |    6 ++--
 drivers/ide/ide-cs.c                             |    3 +-
 drivers/isdn/hardware/avm/avm_cs.c               |    4 +-
 drivers/isdn/hisax/avma1_cs.c                    |    4 +-
 drivers/isdn/hisax/elsa_cs.c                     |    2 +-
 drivers/isdn/hisax/sedlbauer_cs.c                |    2 +-
 drivers/isdn/hisax/teles_cs.c                    |    2 +-
 drivers/mtd/maps/pcmciamtd.c                     |    2 +-
 drivers/net/pcmcia/3c574_cs.c                    |    2 +-
 drivers/net/pcmcia/3c589_cs.c                    |    2 +-
 drivers/net/pcmcia/axnet_cs.c                    |    6 ++--
 drivers/net/pcmcia/fmvj18x_cs.c                  |   22 ++++++------
 drivers/net/pcmcia/ibmtr_cs.c                    |    4 +-
 drivers/net/pcmcia/nmclan_cs.c                   |    4 +-
 drivers/net/pcmcia/pcnet_cs.c                    |    6 ++--
 drivers/net/pcmcia/smc91c92_cs.c                 |   10 +++---
 drivers/net/pcmcia/xirc2ps_cs.c                  |    2 +-
 drivers/net/wireless/airo_cs.c                   |    2 +-
 drivers/net/wireless/hostap/hostap_cs.c          |    2 +-
 drivers/net/wireless/ray_cs.c                    |    2 +-
 drivers/net/wireless/wl3501_cs.c                 |    2 +-
 drivers/parport/parport_cs.c                     |    2 +-
 drivers/pcmcia/cs_internal.h                     |    3 --
 drivers/pcmcia/ds.c                              |    8 ++--
 drivers/pcmcia/pcmcia_cis.c                      |    2 +-
 drivers/pcmcia/pcmcia_resource.c                 |   38 +++++++++++-----------
 drivers/scsi/pcmcia/aha152x_stub.c               |    2 +-
 drivers/scsi/pcmcia/fdomain_stub.c               |    2 +-
 drivers/scsi/pcmcia/nsp_cs.c                     |    2 +-
 drivers/scsi/pcmcia/qlogic_stub.c                |    2 +-
 drivers/serial/serial_cs.c                       |    6 ++--
 drivers/staging/comedi/drivers/cb_das16_cs.c     |    2 +-
 drivers/staging/comedi/drivers/das08_cs.c        |    2 +-
 drivers/staging/comedi/drivers/ni_daq_700.c      |    2 +-
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |    2 +-
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |    2 +-
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |    2 +-
 drivers/staging/wlags49_h2/wl_cs.c               |    4 +-
 drivers/usb/host/sl811_cs.c                      |    2 +-
 include/pcmcia/cs.h                              |   15 --------
 include/pcmcia/ds.h                              |   14 ++++++++
 sound/pcmcia/pdaudiocf/pdaudiocf.c               |    6 ++--
 sound/pcmcia/vx/vxpocket.c                       |    4 +-
 45 files changed, 107 insertions(+), 112 deletions(-)

diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 4cb2dfe..08f4818 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -885,7 +885,7 @@ static int bluecard_config(struct pcmcia_device *link)
 	bluecard_info_t *info = link->priv;
 	int i, n;
 
-	link->conf.ConfigIndex = 0x20;
+	link->config_index = 0x20;
 
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 64;
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 0f0be4d..05c4e68 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -92,7 +92,7 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 
 	/* 0x40 causes it to generate level mode interrupts. */
 	/* 0x04 enables IREQ pin. */
-	p_dev->conf.ConfigIndex = cfg->index | 0x44;
+	p_dev->config_index = cfg->index | 0x44;
 	p_dev->io_lines = 16;
 	ret = pcmcia_request_io(p_dev);
 	if (ret)
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index ba7ccf5..535aa08 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -594,8 +594,8 @@ static int mgslpc_config(struct pcmcia_device *link)
 	    goto failed;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.ConfigIndex = 8;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_index = 8;
+    link->config_regs = PRESENT_OPTION;
 
     ret = pcmcia_request_irq(link, mgslpc_isr);
     if (ret)
@@ -608,7 +608,7 @@ static int mgslpc_config(struct pcmcia_device *link)
     info->irq_level = link->irq;
 
     dev_info(&link->dev, "index 0x%02x:",
-	    link->conf.ConfigIndex);
+	    link->config_index);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	    printk(", irq %d", link->irq);
     if (link->resource[0])
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index cf7cb49..07e3787 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -227,8 +227,7 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-		pdev->conf.ConfigIndex = cfg->index;
+		pdev->config_index = cfg->index;
 		pdev->resource[0]->start = io->win[0].base;
 		if (!(io->flags & CISTPL_IO_16BIT)) {
 			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 938ca41..2d8bbbf 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -80,8 +80,8 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avmcs_config(p_dev);
 } /* avmcs_attach */
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 7d5ff20..e25f6c7 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -85,8 +85,8 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.ConfigIndex = 1;
-    p_dev->conf.Present = PRESENT_OPTION;
+    p_dev->config_index = 1;
+    p_dev->config_regs = PRESENT_OPTION;
 
     return avma1cs_config(p_dev);
 } /* avma1cs_attach */
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index df360c8..f276e84 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -211,7 +211,7 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
 
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x: ",
-	    link->conf.ConfigIndex);
+	    link->config_index);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	printk(", irq %d", link->irq);
     if (link->resource[0])
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 169061f..43d0a4e 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -253,7 +253,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x:",
-	   link->conf.ConfigIndex);
+	   link->config_index);
     if (link->vpp)
 	printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 46e72a1..614afc6 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -191,7 +191,7 @@ static int __devinit teles_cs_config(struct pcmcia_device *link)
 
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x:",
-	    link->conf.ConfigIndex);
+	    link->config_index);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	    printk(", irq %d", link->irq);
     if (link->resource[0])
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 663b48b..99c7257 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -575,7 +575,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 		link->vpp = 0;
 	}
 
-	link->conf.ConfigIndex = 0;
+	link->config_index = 0;
 	DEBUG(2, "Setting Configuration");
 	ret = pcmcia_request_configuration(link, &link->conf);
 	if (ret != 0) {
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 41ecb27..4b670b3 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -281,7 +281,7 @@ static int tc574_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 32;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.ConfigIndex = 1;
+	link->config_index = 1;
 
 	dev->netdev_ops = &el3_netdev_ops;
 	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 6888672..6549e2c 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -217,7 +217,7 @@ static int tc589_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.ConfigIndex = 1;
+    link->config_index = 1;
 
     dev->netdev_ops = &el3_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 4d4928a..2c273ce 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -230,7 +230,7 @@ static int get_prom(struct pcmcia_device *link)
     };
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
 	return 0;
 
     axnet_reset_8390(dev);
@@ -297,7 +297,7 @@ static int axnet_configcheck(struct pcmcia_device *p_dev,
 	if (cfg->index == 0 || cfg->io.nwin == 0)
 		return -ENODEV;
 
-	p_dev->conf.ConfigIndex = 0x05;
+	p_dev->config_index = 0x05;
 	/* For multifunction cards, by convention, we configure the
 	   network function with window 0, and serial with window 1 */
 	if (io->nwin > 1) {
@@ -325,7 +325,7 @@ static int axnet_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
 
     /* don't trust the CIS on this; Linksys got it wrong */
-    link->conf.Present = 0x63;
+    link->config_regs = 0x63;
     ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
     if (ret != 0)
 	goto failed;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index caf2b2e..23f5333 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -312,7 +312,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
 	ret = pcmcia_request_io(link);
 	if (ret == 0) {
 	    /* calculate ConfigIndex value */
-	    link->conf.ConfigIndex = 
+	    link->config_index =
 		((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
 	    return ret;
 	}
@@ -361,28 +361,28 @@ static int fmvj18x_config(struct pcmcia_device *link)
 		link->card_id == PRODID_TDK_NP9610 ||
 		link->card_id == PRODID_TDK_MN3200) {
 		/* MultiFunction Card */
-		link->conf.ConfigBase = 0x800;
-		link->conf.ConfigIndex = 0x47;
+		link->config_base = 0x800;
+		link->config_index = 0x47;
 		link->resource[1]->end = 8;
 	    }
 	    break;
 	case MANFID_NEC:
 	    cardtype = NEC; /* MultiFunction Card */
-	    link->conf.ConfigBase = 0x800;
-	    link->conf.ConfigIndex = 0x47;
+	    link->config_base = 0x800;
+	    link->config_index = 0x47;
 	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_KME:
 	    cardtype = KME; /* MultiFunction Card */
-	    link->conf.ConfigBase = 0x800;
-	    link->conf.ConfigIndex = 0x47;
+	    link->config_base = 0x800;
+	    link->config_index = 0x47;
 	    link->resource[1]->end = 8;
 	    break;
 	case MANFID_CONTEC:
 	    cardtype = CONTEC;
 	    break;
 	case MANFID_FUJITSU:
-	    if (link->conf.ConfigBase == 0x0fe0)
+	    if (link->config_base == 0x0fe0)
 		cardtype = MBH10302;
 	    else if (link->card_id == PRODID_FUJITSU_MBH10302) 
                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
@@ -402,10 +402,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
 	case MANFID_FUJITSU:
 	    if (link->card_id == PRODID_FUJITSU_MBH10304) {
 		cardtype = XXX10304;    /* MBH10304 with buggy CIS */
-	        link->conf.ConfigIndex = 0x20;
+		link->config_index = 0x20;
 	    } else {
 		cardtype = MBH10302;    /* NextCom NC5310, etc. */
-		link->conf.ConfigIndex = 1;
+		link->config_index = 1;
 	    }
 	    break;
 	case MANFID_UNGERMANN:
@@ -413,7 +413,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
 	    break;
 	default:
 	    cardtype = MBH10302;
-	    link->conf.ConfigIndex = 1;
+	    link->config_index = 1;
 	}
     }
 
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 1327f08..feedeeb 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -153,7 +153,7 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[0]->end = 4;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_regs = PRESENT_OPTION;
 
     info->dev = dev;
 
@@ -212,8 +212,8 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "ibmtr_config\n");
 
-    link->conf.ConfigIndex = 0x61;
     link->io_lines = 16;
+    link->config_index = 0x61;
 
     /* Determine if this is PRIMARY or ALTERNATE. */
 
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 90d1728..98c4a69 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -461,8 +461,8 @@ static int nmclan_probe(struct pcmcia_device *link)
     link->resource[0]->end = 32;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.ConfigIndex = 1;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_index = 1;
+    link->config_regs = PRESENT_OPTION;
 
     lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 6913576..68c4675 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -420,7 +420,7 @@ static hw_info_t *get_ax88190(struct pcmcia_device *link)
     int i, j;
 
     /* Not much of a test, but the alternatives are messy */
-    if (link->conf.ConfigBase != 0x03c0)
+    if (link->config_base != 0x03c0)
 	return NULL;
 
     outb_p(0x01, ioaddr + EN0_DCFG);	/* Set word-wide access. */
@@ -564,7 +564,7 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
 
 	if ((link->manf_id == MANFID_IBM) &&
 	    (link->card_id == PRODID_IBM_HOME_AND_AWAY))
-		link->conf.ConfigIndex |= 0x10;
+		link->config_index |= 0x10;
 
 	ret = pcmcia_request_configuration(link, &link->conf);
 	if (ret)
@@ -581,7 +581,7 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
 	} else
 		dev->if_port = 0;
 
-	if ((link->conf.ConfigBase == 0x03c0) &&
+	if ((link->config_base == 0x03c0) &&
 	    (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
 		dev_info(&link->dev,
 			"this is an AX88190 card - use axnet_cs instead.\n");
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 2c2a878..59f5034 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -411,9 +411,9 @@ static int mhz_3288_power(struct pcmcia_device *link)
     mdelay(200);
 
     /* Now read and write the COR... */
-    tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
+    tmp = readb(smc->base + link->config_base + CISREG_COR);
     udelay(5);
-    writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
+    writeb(tmp, smc->base + link->config_base + CISREG_COR);
 
     return 0;
 }
@@ -464,7 +464,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 
     smc->base = ioremap(link->resource[2]->start,
 		    resource_size(link->resource[2]));
-    offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
+    offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0;
     i = pcmcia_map_mem_page(link, link->resource[2], offset);
     if ((i == 0) &&
 	(smc->manfid == MANFID_MEGAHERTZ) &&
@@ -643,8 +643,8 @@ static int osi_config(struct pcmcia_device *link)
     link->resource[1]->end = 8;
 
     /* Enable Hard Decode, LAN, Modem */
-    link->conf.ConfigIndex = 0x23;
     link->io_lines = 16;
+    link->config_index = 0x23;
 
     for (i = j = 0; j < 4; j++) {
 	link->resource[1]->start = com[j];
@@ -654,7 +654,7 @@ static int osi_config(struct pcmcia_device *link)
     }
     if (i != 0) {
 	/* Fallback: turn off hard decode */
-	link->conf.ConfigIndex = 0x03;
+	link->config_index = 0x03;
 	link->resource[1]->end = 0;
 	i = pcmcia_request_io(link);
     }
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 1776f49..1c8ebf2 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -530,7 +530,7 @@ xirc2ps_probe(struct pcmcia_device *link)
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.ConfigIndex = 1;
+    link->config_index = 1;
 
     /* Fill in card specific entries */
     dev->netdev_ops = &netdev_ops;
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index ccb2fdd..40f9ed7 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -240,7 +240,7 @@ static int airo_config(struct pcmcia_device *link)
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x: ",
-	       link->conf.ConfigIndex);
+	       link->config_index);
 	if (link->vpp)
 		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	printk(", irq %d", link->irq);
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 0fe6f82..5704d3f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -601,7 +601,7 @@ static int prism2_config(struct pcmcia_device *link)
 
 	/* Finally, report what we've done */
 	printk(KERN_INFO "%s: index 0x%02x: ",
-	       dev_info, link->conf.ConfigIndex);
+	       dev_info, link->config_index);
 	if (link->vpp)
 		printk(", Vpp %d.%d", link->vpp / 10,
 		       link->vpp % 10);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 30cfd88..7fb66cc 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -319,7 +319,7 @@ static int ray_probe(struct pcmcia_device *p_dev)
 
 	/* General socket configuration */
 	p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-	p_dev->conf.ConfigIndex = 1;
+	p_dev->config_index = 1;
 
 	p_dev->priv = dev;
 
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 92a9ad5..3947cf8 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1889,7 +1889,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
 
 	/* General socket configuration */
 	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
-	p_dev->conf.ConfigIndex	= 1;
+	p_dev->config_index	= 1;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
 	if (!dev)
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index afd946e..8faf634 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -144,7 +144,7 @@ static int parport_config_check(struct pcmcia_device *p_dev,
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
 		if (epp_mode)
-			p_dev->conf.ConfigIndex |= FORCE_EPP_MODE;
+			p_dev->config_index |= FORCE_EPP_MODE;
 		p_dev->resource[0]->start = io->win[0].base;
 		p_dev->resource[0]->end = io->win[0].len;
 		if (io->nwin == 2) {
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index a0c5adb..42eef43 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -34,9 +34,6 @@ typedef struct config_t {
 	struct kref	ref;
 	unsigned int	state;
 	unsigned int	Attributes;
-	unsigned int	ConfigBase;
-	unsigned char	Option;
-	unsigned int	CardValues;
 
 	struct resource io[MAX_IO_WIN]; /* io ports */
 	struct resource mem[MAX_WIN];   /* mem areas */
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 55570d9..00db600 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -276,13 +276,13 @@ static int pcmcia_device_probe(struct device *dev)
 	ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
 				&cis_config);
 	if (!ret) {
-		p_dev->conf.ConfigBase = cis_config.base;
-		p_dev->conf.Present = cis_config.rmask[0];
+		p_dev->config_base = cis_config.base;
+		p_dev->config_regs = cis_config.rmask[0];
 	} else {
 		dev_printk(KERN_INFO, dev,
 			   "pcmcia: could not parse base and rmask0 of CIS\n");
-		p_dev->conf.ConfigBase = 0;
-		p_dev->conf.Present = 0;
+		p_dev->config_base = 0;
+		p_dev->config_regs = 0;
 	}
 
 	ret = p_drv->probe(p_dev);
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 0ac54da..ac47cc4 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -151,7 +151,7 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 	struct pcmcia_cfg_mem *cfg_mem = priv;
 
 	/* default values */
-	cfg_mem->p_dev->conf.ConfigIndex = cfg->index;
+	cfg_mem->p_dev->config_index = cfg->index;
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 		cfg_mem->dflt = *cfg;
 
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 6210e1c..a1fb0dc 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -168,7 +168,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
 		return -EACCES;
 	}
 
-	addr = (c->ConfigBase + where) >> 1;
+	addr = (p_dev->config_base + where) >> 1;
 
 	ret = accessf(s, 1, addr, 1, val);
 
@@ -443,6 +443,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	pccard_io_map iomap;
 	unsigned char status = 0;
 	unsigned char ext_status = 0;
+	unsigned char option = 0;
 
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
@@ -473,7 +474,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	if (req->Attributes & CONF_ENABLE_SPKR) {
 		s->socket.flags |= SS_SPKR_ENA;
 		status = CCSR_AUDIO_ENA;
-		if (!(req->Present & PRESENT_STATUS))
+		if (!(p_dev->config_regs & PRESENT_STATUS))
 			dev_warn(&p_dev->dev, "speaker requested, but "
 					      "PRESENT_STATUS not set!\n");
 	}
@@ -482,54 +483,53 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	else
 		s->socket.io_irq = 0;
 	if (req->Attributes & CONF_ENABLE_ESR) {
-		req->Present |= PRESENT_EXT_STATUS;
+		p_dev->config_regs |= PRESENT_EXT_STATUS;
 		ext_status = ESR_REQ_ATTN_ENA;
 	}
 	s->ops->set_socket(s, &s->socket);
 	s->lock_count++;
 
 	/* Set up CIS configuration registers */
-	base = c->ConfigBase = req->ConfigBase;
-	c->CardValues = req->Present;
-	if (req->Present & PRESENT_COPY) {
+	base = p_dev->config_base;
+	if (p_dev->config_regs & PRESENT_COPY) {
 		u16 tmp = 0;
 		dev_dbg(&p_dev->dev, "clearing CISREG_SCR\n");
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
 	}
-	if (req->Present & PRESENT_PIN_REPLACE) {
+	if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
 		u16 tmp = 0;
 		dev_dbg(&p_dev->dev, "clearing CISREG_PRR\n");
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
 	}
-	if (req->Present & PRESENT_OPTION) {
+	if (p_dev->config_regs & PRESENT_OPTION) {
 		if (s->functions == 1) {
-			c->Option = req->ConfigIndex & COR_CONFIG_MASK;
+			option = p_dev->config_index & COR_CONFIG_MASK;
 		} else {
-			c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
-			c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
-			if (req->Present & PRESENT_IOBASE_0)
-				c->Option |= COR_ADDR_DECODE;
+			option = p_dev->config_index & COR_MFC_CONFIG_MASK;
+			option |= COR_FUNC_ENA|COR_IREQ_ENA;
+			if (p_dev->config_regs & PRESENT_IOBASE_0)
+				option |= COR_ADDR_DECODE;
 		}
 		if ((req->Attributes & CONF_ENABLE_IRQ) &&
 			!(req->Attributes & CONF_ENABLE_PULSE_IRQ))
-			c->Option |= COR_LEVEL_REQ;
-		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
+			option |= COR_LEVEL_REQ;
+		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
 		mdelay(40);
 	}
-	if (req->Present & PRESENT_STATUS)
+	if (p_dev->config_regs & PRESENT_STATUS)
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
 
-	if (req->Present & PRESENT_EXT_STATUS)
+	if (p_dev->config_regs & PRESENT_EXT_STATUS)
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
 					&ext_status);
 
-	if (req->Present & PRESENT_IOBASE_0) {
+	if (p_dev->config_regs & PRESENT_IOBASE_0) {
 		u8 b = c->io[0].start & 0xff;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
 		b = (c->io[0].start >> 8) & 0xff;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
 	}
-	if (req->Present & PRESENT_IOSIZE) {
+	if (p_dev->config_regs & PRESENT_IOSIZE) {
 		u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
 	}
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 3c0046e..c368249 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -103,7 +103,7 @@ static int aha152x_probe(struct pcmcia_device *link)
     link->resource[0]->end = 0x20;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.Present = PRESENT_OPTION;
+    link->config_regs = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
 } /* aha152x_attach */
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 8ff7603..bb909e1 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -86,7 +86,7 @@ static int fdomain_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 0x10;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_regs = PRESENT_OPTION;
 
 	return fdomain_config(link);
 } /* fdomain_attach */
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index c0cf2df..a5648e9 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1745,7 +1745,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
 
 	/* Finally, report what we've done */
 	printk(KERN_INFO "nsp_cs: index 0x%02x: ",
-	       link->conf.ConfigIndex);
+	       link->config_index);
 	if (link->vpp) {
 		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	}
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 77f46a2..5e2cbe0 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -159,7 +159,7 @@ static int qlogic_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 16;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_regs = PRESENT_OPTION;
 
 	return qlogic_config(link);
 }				/* qlogic_attach */
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 38baede..ee19f2d 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -495,7 +495,7 @@ static int simple_config(struct pcmcia_device *link)
 
 found_port:
 	if (info->multi && (info->manfid == MANFID_3COM))
-		link->conf.ConfigIndex &= ~(0x08);
+		link->config_index &= ~(0x08);
 
 	/*
 	 * Apply any configuration quirks.
@@ -591,8 +591,8 @@ static int multi_config(struct pcmcia_device *link)
 				info->prodid == PRODID_POSSIO_GCC)) {
 		int err;
 
-		if (link->conf.ConfigIndex == 1 ||
-		    link->conf.ConfigIndex == 3) {
+		if (link->config_index == 1 ||
+		    link->config_index == 3) {
 			err = setup_serial(link, info, base2,
 					link->irq);
 			base2 = link->resource[0]->start;;
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 11271b6..034cbfc 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -772,7 +772,7 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 319aad4..e37ea79 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -268,7 +268,7 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index d269bbd..8107e40 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -607,7 +607,7 @@ static void dio700_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index fcaa829..4f9daa3 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -358,7 +358,7 @@ static void dio24_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index a936c11..2e27a30 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -336,7 +336,7 @@ static void labpc_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index cd818fb..a2a32de 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1137,7 +1137,7 @@ static void daqp_cs_config(struct pcmcia_device *link)
 		goto failed;
 
 	/* Finally, report what we've done */
-	dev_info(&link->dev, "index 0x%02x", link->conf.ConfigIndex);
+	dev_info(&link->dev, "index 0x%02x", link->config_index);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %u", link->irq);
 	if (link->resource[0])
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index b2efff6..778800f 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -148,8 +148,8 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 	link->resource[0]->end  = HCF_NUM_IO_PORTS;
 	link->resource[0]->flags= IO_DATA_PATH_WIDTH_16;
 	link->conf.Attributes   = CONF_ENABLE_IRQ;
-	link->conf.ConfigIndex  = 5;
-	link->conf.Present      = PRESENT_OPTION;
+	link->config_index      = 5;
+	link->config_regs       = PRESENT_OPTION;
 
 	link->priv = dev;
 	lp = wl_priv(dev);
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 78bad51..5904053 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -200,7 +200,7 @@ static int sl811_cs_config(struct pcmcia_device *link)
 		goto failed;
 
 	dev_info(&link->dev, "index 0x%02x: ",
-		link->conf.ConfigIndex);
+		link->config_index);
 	if (link->vpp)
 		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	printk(", irq %d", link->irq);
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 674edbc..47b6092 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -22,9 +22,6 @@
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int	Attributes;
-    u_int	ConfigBase;
-    u_char	ConfigIndex;
-    u_int	Present;
 } config_req_t;
 
 /* Attributes for RequestConfiguration */
@@ -35,16 +32,4 @@ typedef struct config_req_t {
 #define CONF_ENABLE_ESR		0x10
 #define CONF_VALID_CLIENT	0x100
 
-/* Configuration registers present */
-#define PRESENT_OPTION		0x001
-#define PRESENT_STATUS		0x002
-#define PRESENT_PIN_REPLACE	0x004
-#define PRESENT_COPY		0x008
-#define PRESENT_EXT_STATUS	0x010
-#define PRESENT_IOBASE_0	0x020
-#define PRESENT_IOBASE_1	0x040
-#define PRESENT_IOBASE_2	0x080
-#define PRESENT_IOBASE_3	0x100
-#define PRESENT_IOSIZE		0x200
-
 #endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 6137fbc..bc28f96 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -97,6 +97,9 @@ struct pcmcia_device {
 	unsigned int		vpp;
 
 	unsigned int		io_lines; /* number of I/O lines */
+	unsigned int		config_base;
+	unsigned int		config_index;
+	unsigned int		config_regs;	/* PRESENT_ flags below */
 
 	/* Is the device suspended? */
 	u16			suspended:1;
@@ -250,6 +253,17 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
 					0x0c -> 2
 					0x10 -> 3 */
 
+/* config_reg{ister}s present for this PCMCIA device */
+#define PRESENT_OPTION		0x001
+#define PRESENT_STATUS		0x002
+#define PRESENT_PIN_REPLACE	0x004
+#define PRESENT_COPY		0x008
+#define PRESENT_EXT_STATUS	0x010
+#define PRESENT_IOBASE_0	0x020
+#define PRESENT_IOBASE_1	0x040
+#define PRESENT_IOBASE_2	0x080
+#define PRESENT_IOBASE_3	0x100
+#define PRESENT_IOSIZE		0x200
 
 #endif /* __KERNEL__ */
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 2e1282d..4df07fc 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -143,8 +143,8 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-	link->conf.ConfigIndex = 1;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_index = 1;
+	link->config_regs = PRESENT_OPTION;
 
 	return pdacf_config(link);
 }
@@ -216,7 +216,7 @@ static int pdacf_config(struct pcmcia_device *link)
 	int ret;
 
 	snd_printdd(KERN_DEBUG "pdacf_config called\n");
-	link->conf.ConfigIndex = 0x5;
+	link->config_index = 0x5;
 
 	ret = pcmcia_request_io(link);
 	if (ret)
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index a48b3ee..16186ad 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -163,8 +163,8 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.ConfigIndex = 1;
-	link->conf.Present = PRESENT_OPTION;
+	link->config_index = 1;
+	link->config_regs = PRESENT_OPTION;
 
 	*chip_ret = vxp;
 	return 0;
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:26 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:26 +0200
Subject: [PATCH 10/22] pcmcia: introduce autoconfiguration feature
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-10-git-send-email-linux@dominikbrodowski.net>

Introduce an autoconfiguration feature to set certain values in
pcmcia_loop_config(), instead of copying the same code over and over
in each PCMCIA driver. At first, introduce the following options:

CONF_AUTO_CHECK_VCC	check or matching Vcc entry
CONF_AUTO_SET_VPP	set Vpp
CONF_AUTO_AUDIO		enable the speaker line

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-ide at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: laforge at gnumonks.org
CC: linux-mtd at lists.infradead.org
CC: alsa-devel at alsa-project.org
CC: linux-serial at vger.kernel.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan at profusion.mobi> (for drivers/bluetooth)
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/ata/pata_pcmcia.c                        |   23 +----
 drivers/bluetooth/bt3c_cs.c                      |    7 +-
 drivers/bluetooth/btuart_cs.c                    |    7 +-
 drivers/bluetooth/dtl1_cs.c                      |    1 -
 drivers/char/pcmcia/cm4000_cs.c                  |    1 -
 drivers/char/pcmcia/cm4040_cs.c                  |    1 -
 drivers/char/pcmcia/ipwireless/main.c            |    1 -
 drivers/char/pcmcia/synclink_cs.c                |    1 -
 drivers/ide/ide-cs.c                             |   23 +----
 drivers/isdn/hardware/avm/avm_cs.c               |    1 -
 drivers/isdn/hisax/avma1_cs.c                    |    1 -
 drivers/isdn/hisax/elsa_cs.c                     |    1 -
 drivers/isdn/hisax/sedlbauer_cs.c                |   25 +-----
 drivers/isdn/hisax/teles_cs.c                    |    1 -
 drivers/net/pcmcia/axnet_cs.c                    |    1 -
 drivers/net/pcmcia/fmvj18x_cs.c                  |    1 -
 drivers/net/pcmcia/pcnet_cs.c                    |    1 -
 drivers/net/pcmcia/smc91c92_cs.c                 |    2 -
 drivers/net/pcmcia/xirc2ps_cs.c                  |    5 +-
 drivers/net/wireless/airo_cs.c                   |   17 +---
 drivers/net/wireless/atmel_cs.c                  |   17 +---
 drivers/net/wireless/hostap/hostap_cs.c          |   27 +-----
 drivers/net/wireless/libertas/if_cs.c            |    1 -
 drivers/net/wireless/orinoco/orinoco_cs.c        |   31 +------
 drivers/net/wireless/orinoco/spectrum_cs.c       |   24 +----
 drivers/parport/parport_cs.c                     |    1 -
 drivers/pcmcia/pcmcia_cis.c                      |   36 ++++++-
 drivers/scsi/pcmcia/aha152x_stub.c               |    1 -
 drivers/scsi/pcmcia/fdomain_stub.c               |    1 -
 drivers/scsi/pcmcia/nsp_cs.c                     |  110 ++++++++-------------
 drivers/scsi/pcmcia/qlogic_stub.c                |    1 -
 drivers/scsi/pcmcia/sym53c500_cs.c               |    1 -
 drivers/serial/serial_cs.c                       |   10 +--
 drivers/staging/comedi/drivers/cb_das16_cs.c     |    1 -
 drivers/staging/comedi/drivers/das08_cs.c        |    1 -
 drivers/staging/comedi/drivers/ni_daq_700.c      |   10 +--
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |   10 +--
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |   11 +--
 drivers/staging/comedi/drivers/ni_mio_cs.c       |    1 -
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |    1 -
 drivers/telephony/ixj_pcmcia.c                   |    1 -
 drivers/usb/host/sl811_cs.c                      |   24 +----
 include/pcmcia/ds.h                              |    7 +-
 43 files changed, 120 insertions(+), 329 deletions(-)

diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 76da55d..954f43c 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -169,34 +169,16 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
 
 struct pcmcia_config_check {
 	unsigned long ctl_base;
-	int skip_vcc;
 	int is_kme;
 };
 
 static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 				   cistpl_cftable_entry_t *cfg,
 				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
 				   void *priv_data)
 {
 	struct pcmcia_config_check *stk = priv_data;
 
-	/* Check for matching Vcc, unless we're desperate */
-	if (!stk->skip_vcc) {
-		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
@@ -249,6 +231,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	pdev->config_flags |= CONF_ENABLE_IRQ;
+	pdev->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
 	/* See if we have a manufacturer identifier. Use it to set is_kme for
 	   vendor quirks */
@@ -262,10 +245,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	if (!stk)
 		goto out1;
 	stk->is_kme = is_kme;
-	stk->skip_vcc = io_base = ctl_base = 0;
+	io_base = ctl_base = 0;
 
 	if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
-		stk->skip_vcc = 1;
+		pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
 		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
 			goto failed; /* No suitable config found */
 	}
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 3db9588..97338a3 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -659,7 +659,7 @@ static int bt3c_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 8;
 
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
 
 	return bt3c_config(link);
 }
@@ -676,15 +676,11 @@ static void bt3c_detach(struct pcmcia_device *link)
 static int bt3c_check_config(struct pcmcia_device *p_dev,
 			     cistpl_cftable_entry_t *cf,
 			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
 			     void *priv_data)
 {
 	unsigned long try = (unsigned long) priv_data;
-
 	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
 		p_dev->resource[0]->start = cf->io.win[0].base;
@@ -697,7 +693,6 @@ static int bt3c_check_config(struct pcmcia_device *p_dev,
 static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
 				      cistpl_cftable_entry_t *cf,
 				      cistpl_cftable_entry_t *dflt,
-				      unsigned int vcc,
 				      void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index c5c4359..8a6864f 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -588,7 +588,7 @@ static int btuart_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 8;
 
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
 
 	return btuart_config(link);
 }
@@ -605,15 +605,11 @@ static void btuart_detach(struct pcmcia_device *link)
 static int btuart_check_config(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cf,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	int *try = priv_data;
-
 	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
 		p_dev->resource[0]->start = cf->io.win[0].base;
@@ -626,7 +622,6 @@ static int btuart_check_config(struct pcmcia_device *p_dev,
 static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
 					cistpl_cftable_entry_t *cf,
 					cistpl_cftable_entry_t *dflt,
-					unsigned int vcc,
 					void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 38206df..4620cc3 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -592,7 +592,6 @@ static void dtl1_detach(struct pcmcia_device *link)
 static int dtl1_confcheck(struct pcmcia_device *p_dev,
 			  cistpl_cftable_entry_t *cf,
 			  cistpl_cftable_entry_t *dflt,
-			  unsigned int vcc,
 			  void *priv_data)
 {
 	if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 75caa8c..0b2f3b9 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1744,7 +1744,6 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
 static int cm4000_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	if (!cfg->io.nwin)
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 0c87b80..acf88d5 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -518,7 +518,6 @@ static void cm4040_reader_release(struct pcmcia_device *link)
 static int cm4040_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	int rc;
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index cd21b2b..1b7f092 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -78,7 +78,6 @@ static void signalled_reboot_callback(void *callback_data)
 static int ipwireless_probe(struct pcmcia_device *p_dev,
 			    cistpl_cftable_entry_t *cfg,
 			    cistpl_cftable_entry_t *dflt,
-			    unsigned int vcc,
 			    void *priv_data)
 {
 	struct ipw_dev *ipw = priv_data;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 99feaed..c701434 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -564,7 +564,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
 static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
 			  cistpl_cftable_entry_t *cfg,
 			  cistpl_cftable_entry_t *dflt,
-			  unsigned int vcc,
 			  void *priv_data)
 {
 	if (!cfg->io.nwin)
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 87ad049..25b8a10 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -99,6 +99,7 @@ static int ide_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
     return ide_config(link);
 } /* ide_attach */
@@ -195,34 +196,16 @@ out_release:
 
 struct pcmcia_config_check {
 	unsigned long ctl_base;
-	int skip_vcc;
 	int is_kme;
 };
 
 static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 				   cistpl_cftable_entry_t *cfg,
 				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
 				   void *priv_data)
 {
 	struct pcmcia_config_check *stk = priv_data;
 
-	/* Check for matching Vcc, unless we're desperate */
-	if (!stk->skip_vcc) {
-		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
-				return -ENODEV;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
@@ -271,10 +254,10 @@ static int ide_config(struct pcmcia_device *link)
     if (!stk)
 	    goto err_mem;
     stk->is_kme = is_kme;
-    stk->skip_vcc = io_base = ctl_base = 0;
+    io_base = ctl_base = 0;
 
     if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
-	    stk->skip_vcc = 1;
+	    link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
 		    goto failed; /* No suitable config found */
     }
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 6ea5cd2..9dbab9c 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -110,7 +110,6 @@ static void avmcs_detach(struct pcmcia_device *link)
 static int avmcs_configcheck(struct pcmcia_device *p_dev,
 			     cistpl_cftable_entry_t *cf,
 			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
 			     void *priv_data)
 {
 	if (cf->io.nwin <= 0)
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 5dd47ad..2f2b000 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -117,7 +117,6 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
 static int avma1cs_configcheck(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cf,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	if (cf->io.nwin <= 0)
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 368c8a2..0a65280 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -163,7 +163,6 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
 static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cf,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	int j;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 791e23a..b69eccf 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -164,33 +164,11 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
 static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 				  cistpl_cftable_entry_t *cfg,
 				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
 				  void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-	} else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-	}
-
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -223,6 +201,9 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+	    CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
+
     /*
       In this loop, we scan the CIS for configuration table entries,
       each of which describes a valid card configuration, including
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 2ae71e3..6605480 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -145,7 +145,6 @@ static void __devexit teles_detach(struct pcmcia_device *link)
 static int teles_cs_configcheck(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cf,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	int j;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index f361d28..17f1040 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -287,7 +287,6 @@ static int try_io_port(struct pcmcia_device *link)
 static int axnet_configcheck(struct pcmcia_device *p_dev,
 			     cistpl_cftable_entry_t *cfg,
 			     cistpl_cftable_entry_t *dflt,
-			     unsigned int vcc,
 			     void *priv_data)
 {
 	int i;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index f6865ad..c1479e3 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -322,7 +322,6 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
 static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
 			   cistpl_cftable_entry_t *cfg,
 			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
 			   void *priv_data)
 {
 	return 0; /* strange, but that's what the code did already before... */
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 4a3b6a4..12b028c 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -503,7 +503,6 @@ static int try_io_port(struct pcmcia_device *link)
 static int pcnet_confcheck(struct pcmcia_device *p_dev,
 			   cistpl_cftable_entry_t *cfg,
 			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
 			   void *priv_data)
 {
 	int *priv = priv_data;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 8c16ba6..e127d2b 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -420,7 +420,6 @@ static int mhz_3288_power(struct pcmcia_device *link)
 static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cf,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	int k;
@@ -590,7 +589,6 @@ static int mot_setup(struct pcmcia_device *link)
 static int smc_configcheck(struct pcmcia_device *p_dev,
 			   cistpl_cftable_entry_t *cf,
 			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
 			   void *priv_data)
 {
 	p_dev->resource[0]->start = cf->io.win[0].base;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 7a4a99b..2bc2eb8 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -668,7 +668,6 @@ static int
 xirc2ps_config_modem(struct pcmcia_device *p_dev,
 		     cistpl_cftable_entry_t *cf,
 		     cistpl_cftable_entry_t *dflt,
-		     unsigned int vcc,
 		     void *priv_data)
 {
 	unsigned int ioaddr;
@@ -688,7 +687,6 @@ static int
 xirc2ps_config_check(struct pcmcia_device *p_dev,
 		     cistpl_cftable_entry_t *cf,
 		     cistpl_cftable_entry_t *dflt,
-		     unsigned int vcc,
 		     void *priv_data)
 {
 	int *pass = priv_data;
@@ -826,7 +824,8 @@ xirc2ps_config(struct pcmcia_device * link)
 	     * the Mako if (on the first pass) the COR bit 5 is set.
 	     */
 	    for (pass=0; pass < 2; pass++)
-		    if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
+		    if (!pcmcia_loop_config(link, xirc2ps_config_check,
+						    &pass))
 			    goto port_found;
 	    /* if special option:
 	     * try to configure as Ethernet only.
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 5939d0c..63bf662 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -140,25 +140,11 @@ static void airo_detach(struct pcmcia_device *link)
 static int airo_cs_config_check(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -193,6 +179,9 @@ static int airo_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "airo_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_AUDIO;
+
 	/*
 	 * In this loop, we scan the CIS for configuration table
 	 * entries, each of which describes a valid card
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 080266e..812decd 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -157,25 +157,11 @@ static int card_present(void *arg)
 static int atmel_config_check(struct pcmcia_device *p_dev,
 			      cistpl_cftable_entry_t *cfg,
 			      cistpl_cftable_entry_t *dflt,
-			      unsigned int vcc,
 			      void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -207,6 +193,9 @@ static int atmel_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "atmel_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_AUDIO;
+
 	/*
 	  In this loop, we scan the CIS for configuration table entries,
 	  each of which describes a valid card configuration, including
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 5b0b582..d4f19af 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -472,7 +472,6 @@ static void prism2_detach(struct pcmcia_device *link)
 static int prism2_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	if (cfg->index == 0)
@@ -481,28 +480,6 @@ static int prism2_config_check(struct pcmcia_device *p_dev,
 	PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
 	       "(default 0x%02X)\n", cfg->index, dflt->index);
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] /
-		    10000 && !ignore_cis_vcc) {
-			PDEBUG(DEBUG_EXTRA, "  Vcc mismatch - skipping"
-			       " this entry\n");
-			return -ENODEV;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] /
-		    10000 && !ignore_cis_vcc) {
-			PDEBUG(DEBUG_EXTRA, "  Vcc (default) mismatch "
-			       "- skipping this entry\n");
-			return -ENODEV;
-		}
-	}
-
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
 		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
@@ -553,6 +530,10 @@ static int prism2_config(struct pcmcia_device *link)
 	}
 
 	/* Look for an appropriate configuration table entry in the CIS */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
+		CONF_AUTO_CHECK_VCC;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, prism2_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 6020c19..031f3e6 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -797,7 +797,6 @@ static void if_cs_release(struct pcmcia_device *p_dev)
 static int if_cs_ioprobe(struct pcmcia_device *p_dev,
 			 cistpl_cftable_entry_t *cfg,
 			 cistpl_cftable_entry_t *dflt,
-			 unsigned int vcc,
 			 void *priv_data)
 {
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 00316a1..b921738 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -145,39 +145,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
 static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
 				   cistpl_cftable_entry_t *cfg,
 				   cistpl_cftable_entry_t *dflt,
-				   unsigned int vcc,
 				   void *priv_data)
 {
 	if (cfg->index == 0)
 		goto next_entry;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/* Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	}
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
 	/* Do we need to allocate an interrupt? */
 	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
@@ -230,6 +202,9 @@ orinoco_cs_config(struct pcmcia_device *link)
 	 * and most client drivers will only use the CIS to fill in
 	 * implementation-defined details.
 	 */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index ca2c6c0..f462c78 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -207,32 +207,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
 static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
 				    cistpl_cftable_entry_t *cfg,
 				    cistpl_cftable_entry_t *dflt,
-				    unsigned int vcc,
 				    void *priv_data)
 {
 	if (cfg->index == 0)
 		goto next_entry;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/* Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-		if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-			DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
-			      __func__, vcc,
-			      dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
-			if (!ignore_cis_vcc)
-				goto next_entry;
-		}
-	}
-
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
 		p_dev->vpp =
 			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
@@ -292,6 +271,9 @@ spectrum_cs_config(struct pcmcia_device *link)
 	 * and most client drivers will only use the CIS to fill in
 	 * implementation-defined details.
 	 */
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	if (ignore_cis_vcc)
+		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
 	if (ret) {
 		if (!ignore_cis_vcc)
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 63b3d3c..8c2a473 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -136,7 +136,6 @@ static void parport_detach(struct pcmcia_device *link)
 static int parport_config_check(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index ce8b94a..160da06 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -131,7 +131,6 @@ struct pcmcia_cfg_mem {
 	int (*conf_check) (struct pcmcia_device *p_dev,
 			   cistpl_cftable_entry_t *cfg,
 			   cistpl_cftable_entry_t *dflt,
-			   unsigned int vcc,
 			   void *priv_data);
 	cisparse_t parse;
 	cistpl_cftable_entry_t dflt;
@@ -146,16 +145,46 @@ struct pcmcia_cfg_mem {
  */
 static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 {
-	cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
 	struct pcmcia_cfg_mem *cfg_mem = priv;
+	struct pcmcia_device *p_dev = cfg_mem->p_dev;
+	cistpl_cftable_entry_t *cfg = &parse->cftable_entry;
+	cistpl_cftable_entry_t *dflt = &cfg_mem->dflt;
+	unsigned int flags = p_dev->config_flags;
+	unsigned int vcc = p_dev->socket->socket.Vcc;
+
+	dev_dbg(&p_dev->dev, "testing configuration %x, autoconf %x\n",
+		cfg->index, flags);
 
 	/* default values */
 	cfg_mem->p_dev->config_index = cfg->index;
 	if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
 		cfg_mem->dflt = *cfg;
 
+	/* check for matching Vcc? */
+	if (flags & CONF_AUTO_CHECK_VCC) {
+		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
+				return -ENODEV;
+		} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000)
+				return -ENODEV;
+		}
+	}
+
+	/* set Vpp? */
+	if (flags & CONF_AUTO_SET_VPP) {
+		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+			p_dev->vpp =
+				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+	}
+
+	/* enable audio? */
+	if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
+
 	return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
-				   cfg_mem->p_dev->socket->socket.Vcc,
 				   cfg_mem->priv_data);
 }
 
@@ -176,7 +205,6 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
 						 cistpl_cftable_entry_t *cfg,
 						 cistpl_cftable_entry_t *dflt,
-						 unsigned int vcc,
 						 void *priv_data),
 		       void *priv_data)
 {
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index e1f7485..0b5fc2f 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -124,7 +124,6 @@ static void aha152x_detach(struct pcmcia_device *link)
 static int aha152x_config_check(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	p_dev->io_lines = 10;
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index ae263b1..3b9f311 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -106,7 +106,6 @@ static void fdomain_detach(struct pcmcia_device *link)
 static int fdomain_config_check(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	p_dev->io_lines = 10;
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index d0546c0..344d499 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1597,7 +1597,6 @@ static void nsp_cs_detach(struct pcmcia_device *link)
 static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	nsp_hw_data		*data = priv_data;
@@ -1605,77 +1604,49 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-			return -ENODEV;
-		else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-			if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
-				return -ENODEV;
-		}
-
-		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->vpp =
-				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		} else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->vpp =
-				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-		}
-
-		/* Do we need to allocate an interrupt? */
-		p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-		/* IO window settings */
-		p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-		if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-			p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-			p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			p_dev->resource[0]->flags |=
-				pcmcia_io_cfg_data_width(io->flags);
-			p_dev->resource[0]->start = io->win[0].base;
-			p_dev->resource[0]->end = io->win[0].len;
-			if (io->nwin > 1) {
-				p_dev->resource[1]->flags =
-					p_dev->resource[0]->flags;
-				p_dev->resource[1]->start = io->win[1].base;
-				p_dev->resource[1]->end = io->win[1].len;
-			}
-			/* This reserves IO space but doesn't actually enable it */
-			if (pcmcia_request_io(p_dev) != 0)
-				goto next_entry;
+	/* IO window settings */
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
+	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		p_dev->resource[0]->start = io->win[0].base;
+		p_dev->resource[0]->end = io->win[0].len;
+		if (io->nwin > 1) {
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1].base;
+			p_dev->resource[1]->end = io->win[1].len;
 		}
+		/* This reserves IO space but doesn't actually enable it */
+		if (pcmcia_request_io(p_dev) != 0)
+			goto next_entry;
+	}
 
-		if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-			cistpl_mem_t	*mem =
-				(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-			p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
-						WIN_MEMORY_TYPE_CM |
-						WIN_ENABLE);
-			p_dev->resource[2]->start = mem->win[0].host_addr;
-			p_dev->resource[2]->end = mem->win[0].len;
-			if (p_dev->resource[2]->end < 0x1000)
-				p_dev->resource[2]->end = 0x1000;
-			if (pcmcia_request_window(p_dev, p_dev->resource[2],
-							0) != 0)
-				goto next_entry;
-			if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
-					mem->win[0].card_addr) != 0)
-				goto next_entry;
-
-			data->MmioAddress = (unsigned long)
-				ioremap_nocache(p_dev->resource[2]->start,
+	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+		cistpl_mem_t	*mem =
+			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+		p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
+					WIN_MEMORY_TYPE_CM |
+					WIN_ENABLE);
+		p_dev->resource[2]->start = mem->win[0].host_addr;
+		p_dev->resource[2]->end = mem->win[0].len;
+		if (p_dev->resource[2]->end < 0x1000)
+			p_dev->resource[2]->end = 0x1000;
+		if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
+			goto next_entry;
+		if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
+						mem->win[0].card_addr) != 0)
+			goto next_entry;
+
+		data->MmioAddress = (unsigned long)
+			ioremap_nocache(p_dev->resource[2]->start,
 					resource_size(p_dev->resource[2]));
-			data->MmioLength  = resource_size(p_dev->resource[2]);
-		}
-		/* If we got this far, we're cool! */
-		return 0;
+		data->MmioLength  = resource_size(p_dev->resource[2]);
 	}
+	/* If we got this far, we're cool! */
+	return 0;
 
 next_entry:
 	nsp_dbg(NSP_DEBUG_INIT, "next");
@@ -1692,6 +1663,9 @@ static int nsp_cs_config(struct pcmcia_device *link)
 
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
+
 	ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
 	if (ret)
 		goto cs_failed;
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 7d3f49c..468fd12 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -179,7 +179,6 @@ static void qlogic_detach(struct pcmcia_device *link)
 static int qlogic_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	p_dev->io_lines = 10;
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 600630e..7a0bb9a 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -686,7 +686,6 @@ static struct scsi_host_template sym53c500_driver_template = {
 static int SYM53C500_config_check(struct pcmcia_device *p_dev,
 				  cistpl_cftable_entry_t *cfg,
 				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
 				  void *priv_data)
 {
 	p_dev->io_lines = 10;
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 47b1869..a796a93 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -427,16 +427,11 @@ static int pfc_config(struct pcmcia_device *p_dev)
 static int simple_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cf,
 			       cistpl_cftable_entry_t *dflt,
-			       unsigned int vcc,
 			       void *priv_data)
 {
 	static const int size_table[2] = { 8, 16 };
 	int *try = priv_data;
 
-	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
 	p_dev->io_lines = ((*try & 0x1) == 0) ?
 			16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
@@ -452,7 +447,6 @@ static int simple_config_check(struct pcmcia_device *p_dev,
 static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
 					cistpl_cftable_entry_t *cf,
 					cistpl_cftable_entry_t *dflt,
-					unsigned int vcc,
 					void *priv_data)
 {
 	static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
@@ -479,6 +473,7 @@ static int simple_config(struct pcmcia_device *link)
 
 	/* First pass: look for a config entry that looks normal.
 	 * Two tries: without IO aliases, then with aliases */
+	link->config_flags |= CONF_AUTO_SET_VPP;
 	for (try = 0; try < 4; try++)
 		if (!pcmcia_loop_config(link, simple_config_check, &try))
 			goto found_port;
@@ -511,7 +506,6 @@ found_port:
 static int multi_config_check(struct pcmcia_device *p_dev,
 			      cistpl_cftable_entry_t *cf,
 			      cistpl_cftable_entry_t *dflt,
-			      unsigned int vcc,
 			      void *priv_data)
 {
 	int *base2 = priv_data;
@@ -532,7 +526,6 @@ static int multi_config_check(struct pcmcia_device *p_dev,
 static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
 				       cistpl_cftable_entry_t *cf,
 				       cistpl_cftable_entry_t *dflt,
-				       unsigned int vcc,
 				       void *priv_data)
 {
 	int *base2 = priv_data;
@@ -621,7 +614,6 @@ static int multi_config(struct pcmcia_device *link)
 static int serial_check_for_multi(struct pcmcia_device *p_dev,
 				  cistpl_cftable_entry_t *cf,
 				  cistpl_cftable_entry_t *dflt,
-				  unsigned int vcc,
 				  void *priv_data)
 {
 	struct serial_info *info = p_dev->priv;
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index ee91c89..678fbf6 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -712,7 +712,6 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
 static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index f8f3de5..12a96b7 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -194,7 +194,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
 static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 803683b..f22dc0f 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -532,19 +532,11 @@ static void dio700_cs_detach(struct pcmcia_device *link)
 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -578,6 +570,8 @@ static void dio700_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "dio700_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
+
 	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 6512f7a..6dc2b06 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -284,19 +284,11 @@ static void dio24_cs_detach(struct pcmcia_device *link)
 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -329,6 +321,8 @@ static void dio24_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "dio24_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
+
 	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 255cf40..6eacbd7 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -263,19 +263,11 @@ static void labpc_cs_detach(struct pcmcia_device *link)
 static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Does this card need audio output? */
-	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->config_flags |= CONF_ENABLE_SPKR;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -307,6 +299,9 @@ static void labpc_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "labpc_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
+		CONF_AUTO_AUDIO;
+
 	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index b88f52d..da4e2a2 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -302,7 +302,6 @@ static int mio_cs_resume(struct pcmcia_device *link)
 static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	int base, ret;
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index b8940d7..03a72d7 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1071,7 +1071,6 @@ static void daqp_cs_detach(struct pcmcia_device *link)
 static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
 				cistpl_cftable_entry_t *cfg,
 				cistpl_cftable_entry_t *dflt,
-				unsigned int vcc,
 				void *priv_data)
 {
 	if (cfg->index == 0)
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index e23270d..670a76b 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -112,7 +112,6 @@ failed:
 static int ixj_config_check(struct pcmcia_device *p_dev,
 			    cistpl_cftable_entry_t *cfg,
 			    cistpl_cftable_entry_t *dflt,
-			    unsigned int vcc,
 			    void *priv_data)
 {
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 744c2cd..d960629 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -134,32 +134,11 @@ static void sl811_cs_release(struct pcmcia_device * link)
 static int sl811_cs_config_check(struct pcmcia_device *p_dev,
 				 cistpl_cftable_entry_t *cfg,
 				 cistpl_cftable_entry_t *dflt,
-				 unsigned int vcc,
 				 void *priv_data)
 {
 	if (cfg->index == 0)
 		return -ENODEV;
 
-	/* Use power settings for Vcc and Vpp if present */
-	/*  Note that the CIS values need to be rescaled */
-	if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-			return -ENODEV;
-	} else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-		if (dflt->vcc.param[CISTPL_POWER_VNOM]/10000 != vcc)
-			return -ENODEV;
-		}
-
-	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
-
-	/* we need an interrupt */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
@@ -184,6 +163,9 @@ static int sl811_cs_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "sl811_cs_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ |	CONF_AUTO_SET_VPP |
+		CONF_AUTO_CHECK_VCC;
+
 	if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
 		goto failed;
 
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 50b03fd..0577e5f 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -177,7 +177,6 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
 						 cistpl_cftable_entry_t *cf,
 						 cistpl_cftable_entry_t *dflt,
-						 unsigned int vcc,
 						 void *priv_data),
 		       void *priv_data);
 
@@ -270,6 +269,12 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
 #define CONF_ENABLE_PULSE_IRQ   0x04
 #define CONF_ENABLE_ESR         0x08
 
+/* flags used by pcmcia_loop_config() autoconfiguration */
+#define CONF_AUTO_CHECK_VCC	0x10 /* check for matching Vcc? */
+#define CONF_AUTO_SET_VPP	0x20 /* set Vpp? */
+#define CONF_AUTO_AUDIO		0x40 /* enable audio line? */
+
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DS_H */
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:18 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:18 +0200
Subject: [PATCH 02/22] pcmcia: split up modify_configuration() into two fixup
	functions
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-2-git-send-email-linux@dominikbrodowski.net>

pcmcia_modify_configuration() was only used by two drivers to fix up
one issue each: setting the Vpp to a different value, and reducing
the IO width to 8 bit. Introduce two explicitly named functions
handling these things, and remove one further typedef.

CC: netdev at vger.kernel.org
CC: linux-mtd at lists.infradead.org
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/mtd/maps/pcmciamtd.c     |    8 +--
 drivers/net/pcmcia/smc91c92_cs.c |    5 +-
 drivers/pcmcia/pcmcia_resource.c |  130 +++++++++++++++++++-------------------
 include/pcmcia/cs.h              |   13 ----
 include/pcmcia/ds.h              |    4 +-
 5 files changed, 69 insertions(+), 91 deletions(-)

diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index fb3c538..31ce404 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -316,15 +316,9 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	struct pcmcia_device *link = dev->p_dev;
-	modconf_t mod;
-	int ret;
-
-	mod.Attributes = CONF_VPP1_CHANGE_VALID | CONF_VPP2_CHANGE_VALID;
-	mod.Vcc = 0;
-	mod.Vpp1 = mod.Vpp2 = on ? dev->vpp : 0;
 
 	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
-	ret = pcmcia_modify_configuration(link, &mod);
+	pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
 }
 
 
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index acc6807..395e586 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -816,13 +816,10 @@ static int check_sig(struct pcmcia_device *link)
     }
 
     if (width) {
-	    modconf_t mod = {
-		    .Attributes = CONF_IO_CHANGE_WIDTH,
-	    };
 	    printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
 
 	    smc91c92_suspend(link);
-	    pcmcia_modify_configuration(link, &mod);
+	    pcmcia_fixup_iowidth(link);
 	    smc91c92_resume(link);
 	    return check_sig(link);
     }
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index bf16a1c..14b1a95 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -226,92 +226,90 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
 
-/** pcmcia_modify_configuration
+/**
+ * pcmcia_fixup_iowidth() - reduce io width to 8bit
  *
- * Modify a locked socket configuration
+ * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
+ * IO width to 8bit after having called pcmcia_request_configuration()
+ * previously.
  */
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
-				modconf_t *mod)
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
 {
-	struct pcmcia_socket *s;
-	config_t *c;
-	int ret;
-
-	s = p_dev->socket;
+	struct pcmcia_socket *s = p_dev->socket;
+	pccard_io_map io_off = { 0, 0, 0, 0, 1 };
+	pccard_io_map io_on;
+	int i, ret = 0;
 
 	mutex_lock(&s->ops_mutex);
-	c = p_dev->function_config;
 
-	if (!(s->state & SOCKET_PRESENT)) {
-		dev_dbg(&p_dev->dev, "No card present\n");
-		ret = -ENODEV;
-		goto unlock;
-	}
-	if (!(c->state & CONFIG_LOCKED)) {
-		dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
+	dev_dbg(&p_dev->dev, "fixup iowidth to 8bit\n");
+
+	if (!(s->state & SOCKET_PRESENT) ||
+		!(p_dev->function_config->state & CONFIG_LOCKED)) {
+		dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
 		ret = -EACCES;
 		goto unlock;
 	}
 
-	if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
-		dev_dbg(&p_dev->dev,
-			"changing Vcc or IRQ is not allowed at this time\n");
-		ret = -EINVAL;
-		goto unlock;
-	}
+	io_on.speed = io_speed;
+	for (i = 0; i < MAX_IO_WIN; i++) {
+		if (!s->io[i].res)
+			continue;
+		io_off.map = i;
+		io_on.map = i;
 
-	/* We only allow changing Vpp1 and Vpp2 to the same value */
-	if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
-	    (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-		if (mod->Vpp1 != mod->Vpp2) {
-			dev_dbg(&p_dev->dev,
-				"Vpp1 and Vpp2 must be the same\n");
-			ret = -EINVAL;
-			goto unlock;
-		}
-		s->socket.Vpp = mod->Vpp1;
-		if (s->ops->set_socket(s, &s->socket)) {
-			dev_printk(KERN_WARNING, &p_dev->dev,
-				   "Unable to set VPP\n");
-			ret = -EIO;
-			goto unlock;
-		}
-	} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
-		   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
-		dev_dbg(&p_dev->dev,
-			"changing Vcc is not allowed at this time\n");
-		ret = -EINVAL;
-		goto unlock;
+		io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
+		io_on.start = s->io[i].res->start;
+		io_on.stop = s->io[i].res->end;
+
+		s->ops->set_io_map(s, &io_off);
+		mdelay(40);
+		s->ops->set_io_map(s, &io_on);
 	}
+unlock:
+	mutex_unlock(&s->ops_mutex);
 
-	if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
-		pccard_io_map io_off = { 0, 0, 0, 0, 1 };
-		pccard_io_map io_on;
-		int i;
+	return ret;
+}
+EXPORT_SYMBOL(pcmcia_fixup_iowidth);
 
-		io_on.speed = io_speed;
-		for (i = 0; i < MAX_IO_WIN; i++) {
-			if (!s->io[i].res)
-				continue;
-			io_off.map = i;
-			io_on.map = i;
 
-			io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
-			io_on.start = s->io[i].res->start;
-			io_on.stop = s->io[i].res->end;
+/**
+ * pcmcia_fixup_vpp() - set Vpp to a new voltage level
+ *
+ * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
+ * a new voltage level between calls to pcmcia_request_configuration()
+ * and pcmcia_disable_device().
+ */
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
+{
+	struct pcmcia_socket *s = p_dev->socket;
+	int ret = 0;
 
-			s->ops->set_io_map(s, &io_off);
-			mdelay(40);
-			s->ops->set_io_map(s, &io_on);
-		}
+	mutex_lock(&s->ops_mutex);
+
+	dev_dbg(&p_dev->dev, "fixup Vpp to %d\n", new_vpp);
+
+	if (!(s->state & SOCKET_PRESENT) ||
+		!(p_dev->function_config->state & CONFIG_LOCKED)) {
+		dev_dbg(&p_dev->dev, "No card? Config not locked?\n");
+		ret = -EACCES;
+		goto unlock;
 	}
-	ret = 0;
+
+	s->socket.Vpp = new_vpp;
+	if (s->ops->set_socket(s, &s->socket)) {
+		dev_warn(&p_dev->dev, "Unable to set VPP\n");
+		ret = -EIO;
+		goto unlock;
+	}
+
 unlock:
 	mutex_unlock(&s->ops_mutex);
 
 	return ret;
-} /* modify_configuration */
-EXPORT_SYMBOL(pcmcia_modify_configuration);
+}
+EXPORT_SYMBOL(pcmcia_fixup_vpp);
 
 
 int pcmcia_release_configuration(struct pcmcia_device *p_dev)
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 63cb9bb..e13d0cd 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -19,19 +19,6 @@
 #include <linux/interrupt.h>
 #endif
 
-/* ModifyConfiguration */
-typedef struct modconf_t {
-    u_int	Attributes;
-    u_int	Vcc, Vpp1, Vpp2;
-} modconf_t;
-
-/* Attributes for ModifyConfiguration */
-#define CONF_IRQ_CHANGE_VALID	0x0100
-#define CONF_VCC_CHANGE_VALID	0x0200
-#define CONF_VPP1_CHANGE_VALID	0x0400
-#define CONF_VPP2_CHANGE_VALID	0x0800
-#define CONF_IO_CHANGE_WIDTH	0x1000
-
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int	Attributes;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 6f7cb38..8e307b9 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -212,7 +212,9 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
 int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int offset);
 
-int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
+int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp);
+int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev);
+
 void pcmcia_disable_device(struct pcmcia_device *p_dev);
 
 /* IO ports */
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:24 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:24 +0200
Subject: [PATCH 08/22] pcmcia: convert pcmcia_request_configuration to
	pcmcia_enable_device
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-8-git-send-email-linux@dominikbrodowski.net>

pcmcia_enable_device() now replaces pcmcia_request_configuration().
Instead of config_req_t, all necessary flags are either passed as
a parameter to pcmcia_enable_device(), or (in rare circumstances)
set in struct pcmcia_device -> flags.

With the last remaining user of include/pcmcia/cs.h gone, remove
all references.

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-ide at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: laforge at gnumonks.org
CC: linux-mtd at lists.infradead.org
CC: alsa-devel at alsa-project.org
CC: linux-serial at vger.kernel.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan at profusion.mobi> (for drivers/bluetooth)
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt          |    6 ++++
 drivers/ata/pata_pcmcia.c                        |    5 +--
 drivers/bluetooth/bluecard_cs.c                  |    5 +--
 drivers/bluetooth/bt3c_cs.c                      |    5 +--
 drivers/bluetooth/btuart_cs.c                    |    5 +--
 drivers/bluetooth/dtl1_cs.c                      |    5 +--
 drivers/char/pcmcia/cm4000_cs.c                  |    3 +-
 drivers/char/pcmcia/cm4040_cs.c                  |    5 +--
 drivers/char/pcmcia/ipwireless/main.c            |    6 +--
 drivers/char/pcmcia/ipwireless/main.h            |    1 -
 drivers/char/pcmcia/ipwireless/tty.h             |    1 -
 drivers/char/pcmcia/synclink_cs.c                |   10 ++----
 drivers/ide/ide-cs.c                             |    6 ++--
 drivers/isdn/hardware/avm/avm_cs.c               |    5 +--
 drivers/isdn/hisax/avma1_cs.c                    |    5 +--
 drivers/isdn/hisax/elsa_cs.c                     |    8 +----
 drivers/isdn/hisax/sedlbauer_cs.c                |   12 ++-----
 drivers/isdn/hisax/teles_cs.c                    |    8 ++---
 drivers/mmc/host/sdricoh_cs.c                    |    1 -
 drivers/mtd/maps/pcmciamtd.c                     |    6 +---
 drivers/net/pcmcia/3c574_cs.c                    |    5 +--
 drivers/net/pcmcia/3c589_cs.c                    |    5 +--
 drivers/net/pcmcia/axnet_cs.c                    |   10 +++---
 drivers/net/pcmcia/com20020_cs.c                 |    5 +--
 drivers/net/pcmcia/fmvj18x_cs.c                  |    5 +--
 drivers/net/pcmcia/ibmtr_cs.c                    |    5 +--
 drivers/net/pcmcia/nmclan_cs.c                   |    5 +--
 drivers/net/pcmcia/pcnet_cs.c                    |    7 ++--
 drivers/net/pcmcia/smc91c92_cs.c                 |    9 ++---
 drivers/net/pcmcia/xirc2ps_cs.c                  |   12 ++++----
 drivers/net/wireless/airo_cs.c                   |   16 ++--------
 drivers/net/wireless/atmel_cs.c                  |   16 ++--------
 drivers/net/wireless/b43/pcmcia.c                |    5 +--
 drivers/net/wireless/hostap/hostap_cs.c          |   10 ++----
 drivers/net/wireless/libertas/if_cs.c            |   10 ++----
 drivers/net/wireless/orinoco/orinoco_cs.c        |   12 +------
 drivers/net/wireless/orinoco/spectrum_cs.c       |   12 +------
 drivers/net/wireless/ray_cs.c                    |    5 +--
 drivers/net/wireless/wl3501_cs.c                 |    5 +--
 drivers/parport/parport_cs.c                     |    5 +--
 drivers/pcmcia/au1000_generic.h                  |    1 -
 drivers/pcmcia/au1000_pb1x00.c                   |    1 -
 drivers/pcmcia/cistpl.c                          |    1 -
 drivers/pcmcia/cs.c                              |    1 -
 drivers/pcmcia/cs_internal.h                     |    5 ---
 drivers/pcmcia/ds.c                              |    3 +-
 drivers/pcmcia/i82092.c                          |    1 -
 drivers/pcmcia/i82365.c                          |    1 -
 drivers/pcmcia/m32r_cfc.c                        |    1 -
 drivers/pcmcia/m32r_pcc.c                        |    1 -
 drivers/pcmcia/m8xx_pcmcia.c                     |    1 -
 drivers/pcmcia/pcmcia_cis.c                      |    1 -
 drivers/pcmcia/pcmcia_resource.c                 |   33 ++++++++++----------
 drivers/pcmcia/pd6729.c                          |    1 -
 drivers/pcmcia/rsrc_iodyn.c                      |    1 -
 drivers/pcmcia/rsrc_mgr.c                        |    1 -
 drivers/pcmcia/rsrc_nonstatic.c                  |    1 -
 drivers/pcmcia/sa1100_generic.c                  |    1 -
 drivers/pcmcia/soc_common.h                      |    1 -
 drivers/pcmcia/socket_sysfs.c                    |    1 -
 drivers/pcmcia/tcic.c                            |    1 -
 drivers/pcmcia/xxs1500_ss.c                      |    1 -
 drivers/pcmcia/yenta_socket.c                    |    1 -
 drivers/scsi/pcmcia/aha152x_stub.c               |    5 +--
 drivers/scsi/pcmcia/fdomain_stub.c               |    5 +--
 drivers/scsi/pcmcia/nsp_cs.c                     |   13 +++-----
 drivers/scsi/pcmcia/qlogic_stub.c                |    7 ++--
 drivers/scsi/pcmcia/sym53c500_cs.c               |    5 +--
 drivers/serial/serial_cs.c                       |   11 +++----
 drivers/ssb/main.c                               |    1 -
 drivers/ssb/pcmcia.c                             |    1 -
 drivers/ssb/scan.c                               |    1 -
 drivers/staging/comedi/drivers/cb_das16_cs.c     |   11 ++-----
 drivers/staging/comedi/drivers/das08_cs.c        |   17 ++---------
 drivers/staging/comedi/drivers/ni_daq_700.c      |   19 ++---------
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |   19 ++---------
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |   20 +++---------
 drivers/staging/comedi/drivers/ni_mio_cs.c       |    5 +--
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |   17 ++---------
 drivers/staging/wlags49_h2/wl_cs.c               |    7 ++--
 drivers/staging/wlags49_h2/wl_internal.h         |    1 -
 drivers/telephony/ixj_pcmcia.c                   |    3 +-
 drivers/usb/host/sl811_cs.c                      |    7 +---
 include/pcmcia/cs.h                              |   35 ----------------------
 include/pcmcia/ds.h                              |   17 +++++++----
 include/pcmcia/ss.h                              |    1 -
 sound/pcmcia/pdaudiocf/pdaudiocf.c               |    5 ++-
 sound/pcmcia/pdaudiocf/pdaudiocf.h               |    1 -
 sound/pcmcia/vx/vxpocket.c                       |    6 ++--
 sound/pcmcia/vx/vxpocket.h                       |    1 -
 90 files changed, 179 insertions(+), 395 deletions(-)
 delete mode 100644 include/pcmcia/cs.h

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 86e0f49..62a029f 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,10 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
+   pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
+   as it mirrors pcmcia_disable_device(). Configuration settings are now
+   stored in struct pcmcia_device, e.g. in the fields config_flags,
+   config_index, config_base, vpp.
+
 * pcmcia_request_window changes (as of 2.6.36)
    Instead of win_req_t, drivers are now requested to fill out
    struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four ioport
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index c2679c0..76da55d 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -34,7 +34,6 @@
 #include <linux/ata.h>
 #include <linux/libata.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -249,7 +248,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	/* Set up attributes in order to probe card and get resources */
 	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	pdev->conf.Attributes = CONF_ENABLE_IRQ;
+	pdev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* See if we have a manufacturer identifier. Use it to set is_kme for
 	   vendor quirks */
@@ -275,7 +274,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	if (!pdev->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(pdev, &pdev->conf);
+	ret = pcmcia_enable_device(pdev);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 08f4818..c9dd5b7 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -39,7 +39,6 @@
 #include <linux/skbuff.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -865,7 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return bluecard_config(link);
 }
@@ -905,7 +904,7 @@ static int bluecard_config(struct pcmcia_device *link)
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index fb01807..3db9588 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -45,7 +45,6 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -660,7 +659,7 @@ static int bt3c_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 8;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return bt3c_config(link);
 }
@@ -741,7 +740,7 @@ found_port:
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 897c7c7..c5c4359 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -589,7 +588,7 @@ static int btuart_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 8;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return btuart_config(link);
 }
@@ -670,7 +669,7 @@ found_port:
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index b4c9a2e..38206df 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -41,7 +41,6 @@
 #include <asm/system.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -575,7 +574,7 @@ static int dtl1_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	link->resource[0]->end = 8;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return dtl1_config(link);
 }
@@ -619,7 +618,7 @@ static int dtl1_config(struct pcmcia_device *link)
 	if (i != 0)
 		goto failed;
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		goto failed;
 
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index d2accd6..75caa8c 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -34,7 +34,6 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -1767,7 +1766,7 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
 	if (pcmcia_loop_config(link, cm4000_config_check, NULL))
 		goto cs_release;
 
-	if (pcmcia_request_configuration(link, &link->conf))
+	if (pcmcia_enable_device(link))
 		goto cs_release;
 
 	dev = link->priv;
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index a32eba0..0c87b80 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -29,7 +29,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -547,10 +546,10 @@ static int reader_config(struct pcmcia_device *link, int devno)
 	if (pcmcia_loop_config(link, cm4040_config_check, NULL))
 		goto cs_release;
 
-	fail_rc = pcmcia_request_configuration(link, &link->conf);
+	fail_rc = pcmcia_enable_device(link);
 	if (fail_rc != 0) {
 		dev_printk(KERN_INFO, &link->dev,
-			   "pcmcia_request_configuration failed 0x%x\n",
+			   "pcmcia_enable_device failed 0x%x\n",
 			   fail_rc);
 		goto cs_release;
 	}
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 05c4e68..cd21b2b 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -32,7 +32,6 @@
 #include <pcmcia/device_id.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/ds.h>
-#include <pcmcia/cs.h>
 
 static struct pcmcia_device_id ipw_ids[] = {
 	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
@@ -172,7 +171,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
 	if (ret != 0)
 		return ret;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
@@ -210,8 +209,7 @@ static int config_ipwireless(struct ipw_dev *ipw)
 	 * Do the RequestConfiguration last, because it enables interrupts.
 	 * Then we don't get any interrupts before we're ready for them.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
-
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto exit;
 
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index 9040219..f2cbb11 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
index 3e163d4..747b2d6 100644
--- a/drivers/char/pcmcia/ipwireless/tty.h
+++ b/drivers/char/pcmcia/ipwireless/tty.h
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 535aa08..99feaed 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -70,7 +70,6 @@
 #include <linux/workqueue.h>
 #include <linux/hdlc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -550,8 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
 
     /* Initialize the struct pcmcia_device structure */
 
-    link->conf.Attributes = 0;
-
     ret = mgslpc_config(link);
     if (ret)
 	    return ret;
@@ -593,14 +590,14 @@ static int mgslpc_config(struct pcmcia_device *link)
     if (ret != 0)
 	    goto failed;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 8;
     link->config_regs = PRESENT_OPTION;
 
     ret = pcmcia_request_irq(link, mgslpc_isr);
     if (ret)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -609,8 +606,7 @@ static int mgslpc_config(struct pcmcia_device *link)
 
     dev_info(&link->dev, "index 0x%02x:",
 	    link->config_index);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	    printk(", irq %d", link->irq);
+    printk(", irq %d", link->irq);
     if (link->resource[0])
 	    printk(", io %pR", link->resource[0]);
     printk("\n");
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 07e3787..87ad049 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -43,7 +43,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -99,7 +98,7 @@ static int ide_probe(struct pcmcia_device *link)
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     return ide_config(link);
 } /* ide_attach */
@@ -284,7 +283,8 @@ static int ide_config(struct pcmcia_device *link)
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 2d8bbbf..6ea5cd2 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -79,7 +78,7 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
     p_dev->config_index = 1;
     p_dev->config_regs = PRESENT_OPTION;
 
@@ -149,7 +148,7 @@ static int avmcs_config(struct pcmcia_device *link)
 	/*
          * configure the PCMCIA socket
 	  */
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0) {
 	    pcmcia_disable_device(link);
 	    break;
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index e25f6c7..5dd47ad 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -20,7 +20,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include "hisax_cfg.h"
@@ -84,7 +83,7 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
     p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
 
     /* General socket configuration */
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
     p_dev->config_index = 1;
     p_dev->config_regs = PRESENT_OPTION;
 
@@ -160,7 +159,7 @@ static int __devinit avma1cs_config(struct pcmcia_device *link)
 	/*
 	 * configure the PCMCIA socket
 	 */
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0) {
 	    pcmcia_disable_device(link);
 	    break;
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index f276e84..368c8a2 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -129,8 +128,6 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
     link->resource[0]->end = 8;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
-
     return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
@@ -205,15 +202,14 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
     if (!link->irq)
 	goto failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
 	goto failed;
 
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x: ",
 	    link->config_index);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	printk(", irq %d", link->irq);
+    printk(", irq %d", link->irq);
     if (link->resource[0])
 	printk(" & %pR", link->resource[0]);
     if (link->resource[1])
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 43d0a4e..791e23a 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -46,7 +46,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -132,8 +131,6 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
     link->resource[0]->end = 8;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
-    link->conf.Attributes = 0;
-
     return sedlbauer_config(link);
 } /* sedlbauer_attach */
 
@@ -175,7 +172,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
@@ -192,7 +189,7 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
 		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -247,7 +244,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
        the I/O windows and the interrupt mapping, and putting the
        card and host interface into "Memory and IO" mode.
     */
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
@@ -256,8 +253,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
 	   link->config_index);
     if (link->vpp)
 	printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	printk(", irq %d", link->irq);
+    printk(", irq %d", link->irq);
     if (link->resource[0])
 	printk(" & %pR", link->resource[0]);
     if (link->resource[1])
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 614afc6..2ae71e3 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -27,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -109,7 +108,7 @@ static int __devinit teles_probe(struct pcmcia_device *link)
     link->resource[0]->end = 96;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     return teles_cs_config(link);
 } /* teles_attach */
@@ -185,15 +184,14 @@ static int __devinit teles_cs_config(struct pcmcia_device *link)
     if (!link->irq)
         goto cs_failed;
 
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i != 0)
       goto cs_failed;
 
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x:",
 	    link->config_index);
-    if (link->conf.Attributes & CONF_ENABLE_IRQ)
-	    printk(", irq %d", link->irq);
+    printk(", irq %d", link->irq);
     if (link->resource[0])
 	printk(" & %pR", link->resource[0]);
     if (link->resource[1])
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c
index 7aa65bb..7a7273b 100644
--- a/drivers/mmc/host/sdricoh_cs.c
+++ b/drivers/mmc/host/sdricoh_cs.c
@@ -30,7 +30,6 @@
 #include <linux/ioport.h>
 #include <linux/scatterlist.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 99c7257..388db9e 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -568,7 +567,6 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 	dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
 
 	dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
-	link->conf.Attributes = 0;
 	if(setvpp == 2) {
 		link->vpp = dev->vpp;
 	} else {
@@ -577,7 +575,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 
 	link->config_index = 0;
 	DEBUG(2, "Setting Configuration");
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0) {
 		if (dev->win_base) {
 			iounmap(dev->win_base);
@@ -718,8 +716,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
 	dev->p_dev = link;
 	link->priv = dev;
 
-	link->conf.Attributes = 0;
-
 	return pcmciamtd_config(link);
 }
 
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 4b670b3..8abce76 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -87,7 +87,6 @@ earlier 3Com products.
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -280,7 +279,7 @@ static int tc574_probe(struct pcmcia_device *link)
 	spin_lock_init(&lp->window_lock);
 	link->resource[0]->end = 32;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->config_index = 1;
 
 	dev->netdev_ops = &el3_netdev_ops;
@@ -351,7 +350,7 @@ static int tc574_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 6549e2c..34195c4 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -41,7 +41,6 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -216,7 +215,7 @@ static int tc589_probe(struct pcmcia_device *link)
     link->resource[0]->end = 16;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 1;
 
     dev->netdev_ops = &el3_netdev_ops;
@@ -293,7 +292,7 @@ static int tc589_config(struct pcmcia_device *link)
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 2c273ce..f361d28 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -39,7 +39,6 @@
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -166,7 +165,7 @@ static int axnet_probe(struct pcmcia_device *link)
     info = PRIV(dev);
     info->p_dev = link;
     link->priv = dev;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &axnet_netdev_ops;
 
@@ -332,11 +331,12 @@ static int axnet_config(struct pcmcia_device *link)
 
     if (!link->irq)
 	    goto failed;
-    
+
+    link->config_flags |= CONF_ENABLE_IRQ;
     if (resource_size(link->resource[1]) == 8)
-	link->conf.Attributes |= CONF_ENABLE_SPKR;
+	link->config_flags |= CONF_ENABLE_SPKR;
     
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index a58eafe..039731b 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -43,7 +43,6 @@
 #include <linux/arcdevice.h>
 #include <linux/com20020.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -160,7 +159,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)
 
     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     p_dev->resource[0]->end = 16;
-    p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+    p_dev->config_flags |= CONF_ENABLE_IRQ;
 
     info->dev = dev;
     p_dev->priv = info;
@@ -281,7 +280,7 @@ static int com20020_config(struct pcmcia_device *link)
 
     dev->irq = link->irq;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 23f5333..f6865ad 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -49,7 +49,6 @@
 #include <linux/ioport.h>
 #include <linux/crc32.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -252,7 +251,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -431,7 +430,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
     ret = pcmcia_request_irq(link, fjn_interrupt);
     if (ret)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index feedeeb..b298a3d 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -57,7 +57,6 @@
 #include <linux/trdevice.h>
 #include <linux/ibmtr.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -152,7 +151,7 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[0]->end = 4;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_regs = PRESENT_OPTION;
 
     info->dev = dev;
@@ -269,7 +268,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
 		    resource_size(link->resource[3]));
     ti->sram_phys = link->resource[3]->start;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 98c4a69..51bf76d 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -146,7 +146,6 @@ Include Files
 #include <linux/ioport.h>
 #include <linux/bitops.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
@@ -460,7 +459,7 @@ static int nmclan_probe(struct pcmcia_device *link)
     spin_lock_init(&lp->bank_lock);
     link->resource[0]->end = 32;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 1;
     link->config_regs = PRESENT_OPTION;
 
@@ -649,7 +648,7 @@ static int nmclan_config(struct pcmcia_device *link)
   ret = pcmcia_request_exclusive_irq(link, mace_interrupt);
   if (ret)
 	  goto failed;
-  ret = pcmcia_request_configuration(link, &link->conf);
+  ret = pcmcia_enable_device(link);
   if (ret)
 	  goto failed;
 
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 68c4675..4a3b6a4 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -42,7 +42,6 @@
 #include <linux/mii.h>
 #include "../8390.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -260,7 +259,7 @@ static int pcnet_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = dev;
 
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     dev->netdev_ops = &pcnet_netdev_ops;
 
@@ -560,13 +559,13 @@ static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
 		return NULL;
 
 	if (resource_size(link->resource[1]) == 8)
-		link->conf.Attributes |= CONF_ENABLE_SPKR;
+		link->config_flags |= CONF_ENABLE_SPKR;
 
 	if ((link->manf_id == MANFID_IBM) &&
 	    (link->card_id == PRODID_IBM_HOME_AND_AWAY))
 		link->config_index |= 0x10;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		return NULL;
 
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 59f5034..8c16ba6 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -44,7 +44,6 @@
 #include <linux/jiffies.h>
 #include <linux/firmware.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -326,7 +325,7 @@ static int smc91c92_probe(struct pcmcia_device *link)
     spin_lock_init(&smc->lock);
     link->resource[0]->end = 16;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
@@ -444,7 +443,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     unsigned int offset;
     int i;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
+    link->config_flags |= CONF_ENABLE_SPKR;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->end = 8;
 
@@ -637,7 +636,7 @@ static int osi_config(struct pcmcia_device *link)
     static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
-    link->conf.Attributes |= CONF_ENABLE_SPKR;
+    link->config_flags |= CONF_ENABLE_SPKR;
     link->resource[0]->end = 64;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->end = 8;
@@ -862,7 +861,7 @@ static int smc91c92_config(struct pcmcia_device *link)
     i = pcmcia_request_irq(link, smc_interrupt);
     if (i)
 	    goto config_failed;
-    i = pcmcia_request_configuration(link, &link->conf);
+    i = pcmcia_enable_device(link);
     if (i)
 	    goto config_failed;
 
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 1c8ebf2..7a4a99b 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -82,7 +82,6 @@
 #include <linux/bitops.h>
 #include <linux/mii.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -529,7 +528,7 @@ xirc2ps_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     /* General socket configuration */
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 1;
 
     /* Fill in card specific entries */
@@ -811,9 +810,6 @@ xirc2ps_config(struct pcmcia_device * link)
     if (local->modem) {
 	int pass;
 
-	if (do_sound)
-	    link->conf.Attributes |= CONF_ENABLE_SPKR;
-
 	link->resource[1]->end = 8;
 	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	if (local->dingo) {
@@ -863,7 +859,11 @@ xirc2ps_config(struct pcmcia_device * link)
      * This actually configures the PCMCIA socket -- setting up
      * the I/O windows and the interrupt mapping.
      */
-    if ((err=pcmcia_request_configuration(link, &link->conf)))
+    link->config_flags |= CONF_ENABLE_IRQ;
+    if (do_sound)
+	    link->config_flags |= CONF_ENABLE_SPKR;
+
+    if ((err = pcmcia_enable_device(link)))
 	goto config_error;
 
     if (local->dingo) {
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 40f9ed7..5939d0c 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -32,7 +32,6 @@
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -96,15 +95,6 @@ static int airo_probe(struct pcmcia_device *p_dev)
 
 	dev_dbg(&p_dev->dev, "airo_attach()\n");
 
-	/*
-	  General socket configuration defaults can go here.  In this
-	  client, we assume very little, and rely on the CIS for almost
-	  everything.  In most clients, many details (i.e., number, sizes,
-	  and attributes of IO windows) are fixed by the nature of the
-	  device, and can be hard-wired here.
-	*/
-	p_dev->conf.Attributes = 0;
-
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
@@ -158,7 +148,7 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
@@ -167,7 +157,7 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
 		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -229,7 +219,7 @@ static int airo_config(struct pcmcia_device *link)
 	  the I/O windows and the interrupt mapping, and putting the
 	  card and host interface into "Memory and IO" mode.
 	*/
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 	((local_info_t *)link->priv)->eth_dev =
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 8b75158..080266e 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -42,7 +42,6 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -106,15 +105,6 @@ static int atmel_probe(struct pcmcia_device *p_dev)
 
 	dev_dbg(&p_dev->dev, "atmel_attach()\n");
 
-	/*
-	  General socket configuration defaults can go here.  In this
-	  client, we assume very little, and rely on the CIS for almost
-	  everything.  In most clients, many details (i.e., number, sizes,
-	  and attributes of IO windows) are fixed by the nature of the
-	  device, and can be hard-wired here.
-	*/
-	p_dev->conf.Attributes = 0;
-
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
@@ -175,7 +165,7 @@ static int atmel_config_check(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
@@ -184,7 +174,7 @@ static int atmel_config_check(struct pcmcia_device *p_dev,
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
 		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -242,7 +232,7 @@ static int atmel_config(struct pcmcia_device *link)
 	  the I/O windows and the interrupt mapping, and putting the
 	  card and host interface into "Memory and IO" mode.
 	*/
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 138b26f..61abab1 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -26,7 +26,6 @@
 #include <linux/ssb/ssb.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -72,7 +71,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 
 	err = -ENODEV;
 
-	dev->conf.Attributes = CONF_ENABLE_IRQ;
+	dev->config_flags |= CONF_ENABLE_IRQ;
 
 	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
@@ -89,7 +88,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	if (!dev->irq)
 		goto err_disable;
 
-	res = pcmcia_request_configuration(dev, &dev->conf);
+	res = pcmcia_enable_device(dev);
 	if (res != 0)
 		goto err_disable;
 
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 5704d3f..5b0b582 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -12,7 +12,6 @@
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -484,7 +483,7 @@ static int prism2_config_check(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
@@ -510,7 +509,7 @@ static int prism2_config_check(struct pcmcia_device *p_dev,
 		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
@@ -590,7 +589,7 @@ static int prism2_config(struct pcmcia_device *link)
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed_unlock;
 
@@ -605,8 +604,7 @@ static int prism2_config(struct pcmcia_device *link)
 	if (link->vpp)
 		printk(", Vpp %d.%d", link->vpp / 10,
 		       link->vpp % 10);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
+	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 814b7fa..6020c19 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -28,7 +28,6 @@
 #include <linux/firmware.h>
 #include <linux/netdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -806,7 +805,7 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev,
 	p_dev->resource[0]->end = cfg->io.win[0].len;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	if (cfg->io.nwin != 1) {
@@ -835,14 +834,11 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	card->p_dev = p_dev;
 	p_dev->priv = card;
 
-	p_dev->conf.Attributes = 0;
-
 	if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
 		lbs_pr_err("error in pcmcia_loop_config\n");
 		goto out1;
 	}
 
-
 	/*
 	 * Allocate an interrupt line.  Note that this does not assign
 	 * a handler to the interrupt, unless the 'Handler' member of
@@ -865,9 +861,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+	ret = pcmcia_enable_device(p_dev);
 	if (ret) {
-		lbs_pr_err("error in pcmcia_request_configuration\n");
+		lbs_pr_err("error in pcmcia_enable_device\n");
 		goto out2;
 	}
 
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 1147d6b..00316a1 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -117,13 +116,6 @@ orinoco_cs_probe(struct pcmcia_device *link)
 	card->p_dev = link;
 	link->priv = priv;
 
-	/* General socket configuration defaults can go here.  In this
-	 * client, we assume very little, and rely on the CIS for
-	 * almost everything.  In most clients, many details (i.e.,
-	 * number, sizes, and attributes of IO windows) are fixed by
-	 * the nature of the device, and can be hard-wired here. */
-	link->conf.Attributes = 0;
-
 	return orinoco_cs_config(link);
 }				/* orinoco_cs_attach */
 
@@ -187,7 +179,7 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
 			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -266,7 +258,7 @@ orinoco_cs_config(struct pcmcia_device *link)
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 20b08ab..ca2c6c0 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -25,7 +25,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -179,13 +178,6 @@ spectrum_cs_probe(struct pcmcia_device *link)
 	card->p_dev = link;
 	link->priv = priv;
 
-	/* General socket configuration defaults can go here.  In this
-	 * client, we assume very little, and rely on the CIS for
-	 * almost everything.  In most clients, many details (i.e.,
-	 * number, sizes, and attributes of IO windows) are fixed by
-	 * the nature of the device, and can be hard-wired here. */
-	link->conf.Attributes = 0;
-
 	return spectrum_cs_config(link);
 }				/* spectrum_cs_attach */
 
@@ -249,7 +241,7 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
 			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -329,7 +321,7 @@ spectrum_cs_config(struct pcmcia_device *link)
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 7fb66cc..1457f34 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -46,7 +46,6 @@
 #include <linux/ethtool.h>
 #include <linux/ieee80211.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -318,7 +317,7 @@ static int ray_probe(struct pcmcia_device *p_dev)
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
-	p_dev->conf.Attributes = CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 	p_dev->config_index = 1;
 
 	p_dev->priv = dev;
@@ -413,7 +412,7 @@ static int ray_config(struct pcmcia_device *link)
 	/* This actually configures the PCMCIA socket -- setting up
 	   the I/O windows and the interrupt mapping.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 3947cf8..101b6ff 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -48,7 +48,6 @@
 
 #include <net/iw_handler.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -1888,7 +1887,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
 	p_dev->resource[0]->flags	= IO_DATA_PATH_WIDTH_8;
 
 	/* General socket configuration */
-	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
+	p_dev->config_flags	= CONF_ENABLE_IRQ;
 	p_dev->config_index	= 1;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
@@ -1954,7 +1953,7 @@ static int wl3501_config(struct pcmcia_device *link)
 	/* This actually configures the PCMCIA socket -- setting up the I/O
 	 * windows and the interrupt mapping.  */
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 8faf634..63b3d3c 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -48,7 +48,6 @@
 #include <linux/parport.h>
 #include <linux/parport_pc.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/cisreg.h>
@@ -103,7 +102,7 @@ static int parport_probe(struct pcmcia_device *link)
 
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
 
     return parport_config(link);
 } /* parport_attach */
@@ -172,7 +171,7 @@ static int parport_config(struct pcmcia_device *link)
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index 67530ce..5c36bda 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -23,7 +23,6 @@
 
 /* include the world */
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index 807f2d7..b239664 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -31,7 +31,6 @@
 #include <linux/proc_fs.h>
 #include <linux/types.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 91414a0..884a984 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -28,7 +28,6 @@
 #include <asm/unaligned.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 2ec8ac9..d8189d4 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -33,7 +33,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 42eef43..7f1953f 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -33,14 +33,9 @@
 typedef struct config_t {
 	struct kref	ref;
 	unsigned int	state;
-	unsigned int	Attributes;
 
 	struct resource io[MAX_IO_WIN]; /* io ports */
 	struct resource mem[MAX_WIN];   /* mem areas */
-
-	struct {
-		u_int	Attributes;
-	} irq;
 } config_t;
 
 
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 00db600..dd43bd3 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -26,7 +26,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ss.h>
@@ -1178,7 +1177,7 @@ static int pcmcia_dev_resume(struct device *dev)
 
 	if (p_dev->device_no == p_dev->func) {
 		dev_dbg(dev, "requesting configuration\n");
-		ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
+		ret = pcmcia_enable_device(p_dev);
 		if (ret)
 			goto out;
 	}
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 05d0879..fc7906e 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -16,7 +16,6 @@
 #include <linux/device.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 61746bd..72a033a 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -51,7 +51,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <linux/isapnp.h>
 
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 24de499..2adb010 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -27,7 +27,6 @@
 #include <asm/system.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #undef MAX_IO_WIN	/* FIXME */
 #define MAX_IO_WIN 1
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index 8e47238..1511ff7 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -28,7 +28,6 @@
 #include <asm/addrspace.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 /* XXX: should be moved into asm/irq.h */
 #define PCC0_IRQ 24
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index f0ecad9..99d4f23 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -59,7 +59,6 @@
 #include <asm/irq.h>
 #include <asm/fs_pd.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index ac47cc4..ce8b94a 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -22,7 +22,6 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ds.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index a1fb0dc..28de5e6 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -230,7 +229,7 @@ EXPORT_SYMBOL(pcmcia_map_mem_page);
  * pcmcia_fixup_iowidth() - reduce io width to 8bit
  *
  * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
- * IO width to 8bit after having called pcmcia_request_configuration()
+ * IO width to 8bit after having called pcmcia_enable_device()
  * previously.
  */
 int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
@@ -278,7 +277,7 @@ EXPORT_SYMBOL(pcmcia_fixup_iowidth);
  * pcmcia_fixup_vpp() - set Vpp to a new voltage level
  *
  * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
- * a new voltage level between calls to pcmcia_request_configuration()
+ * a new voltage level between calls to pcmcia_enable_device()
  * and pcmcia_disable_device().
  */
 int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
@@ -432,18 +431,21 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 } /* pcmcia_release_window */
 EXPORT_SYMBOL(pcmcia_release_window);
 
-
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-				 config_req_t *req)
+/**
+ * pcmcia_enable_device() - set up and activate a PCMCIA device
+ *
+ */
+int pcmcia_enable_device(struct pcmcia_device *p_dev)
 {
 	int i;
-	u_int base;
+	unsigned int base;
 	struct pcmcia_socket *s = p_dev->socket;
 	config_t *c;
 	pccard_io_map iomap;
 	unsigned char status = 0;
 	unsigned char ext_status = 0;
 	unsigned char option = 0;
+	unsigned int flags = p_dev->config_flags;
 
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
@@ -466,23 +468,20 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	}
 
 	/* Pick memory or I/O card, DMA mode, interrupt */
-	c->Attributes = req->Attributes;
 	if (p_dev->_io)
 		s->socket.flags |= SS_IOCARD;
-	if (req->Attributes & CONF_ENABLE_DMA)
-		s->socket.flags |= SS_DMA_MODE;
-	if (req->Attributes & CONF_ENABLE_SPKR) {
+	if (flags & CONF_ENABLE_SPKR) {
 		s->socket.flags |= SS_SPKR_ENA;
 		status = CCSR_AUDIO_ENA;
 		if (!(p_dev->config_regs & PRESENT_STATUS))
 			dev_warn(&p_dev->dev, "speaker requested, but "
 					      "PRESENT_STATUS not set!\n");
 	}
-	if (req->Attributes & CONF_ENABLE_IRQ)
+	if (flags & CONF_ENABLE_IRQ)
 		s->socket.io_irq = s->pcmcia_irq;
 	else
 		s->socket.io_irq = 0;
-	if (req->Attributes & CONF_ENABLE_ESR) {
+	if (flags & CONF_ENABLE_ESR) {
 		p_dev->config_regs |= PRESENT_EXT_STATUS;
 		ext_status = ESR_REQ_ATTN_ENA;
 	}
@@ -510,8 +509,8 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 			if (p_dev->config_regs & PRESENT_IOBASE_0)
 				option |= COR_ADDR_DECODE;
 		}
-		if ((req->Attributes & CONF_ENABLE_IRQ) &&
-			!(req->Attributes & CONF_ENABLE_PULSE_IRQ))
+		if ((flags & CONF_ENABLE_IRQ) &&
+			!(flags & CONF_ENABLE_PULSE_IRQ))
 			option |= COR_LEVEL_REQ;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
 		mdelay(40);
@@ -560,8 +559,8 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	p_dev->_locked = 1;
 	mutex_unlock(&s->ops_mutex);
 	return 0;
-} /* pcmcia_request_configuration */
-EXPORT_SYMBOL(pcmcia_request_configuration);
+} /* pcmcia_enable_device */
+EXPORT_SYMBOL(pcmcia_enable_device);
 
 
 /**
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index deef665..8cbfa06 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include <asm/system.h>
 
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c
index 8510c35..523eb69 100644
--- a/drivers/pcmcia/rsrc_iodyn.c
+++ b/drivers/pcmcia/rsrc_iodyn.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 4e80421..aa628ed 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -17,7 +17,6 @@
 #include <linux/kernel.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 96f348b..b187555 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -29,7 +29,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index e098514..945857f 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
 #include <asm/hardware/scoop.h>
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h
index 3fba3a6..bbcd538 100644
--- a/drivers/pcmcia/soc_common.h
+++ b/drivers/pcmcia/soc_common.h
@@ -11,7 +11,6 @@
 
 /* include the world */
 #include <linux/cpufreq.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index cb0d3ac..71aeed9 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -27,7 +27,6 @@
 #include <asm/irq.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index be0d841..310160b 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -49,7 +49,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include "tcic.h"
 
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index fa88c36..3b67a1b 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cistpl.h>
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 414d9a6..408dbaa 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -20,7 +20,6 @@
 #include <linux/slab.h>
 
 #include <pcmcia/ss.h>
-#include <pcmcia/cs.h>
 
 #include "yenta_socket.h"
 #include "i82365.h"
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index c368249..e1f7485 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -49,7 +49,6 @@
 #include <scsi/scsi_host.h>
 #include "aha152x.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -102,7 +101,7 @@ static int aha152x_probe(struct pcmcia_device *link)
 
     link->resource[0]->end = 0x20;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_regs = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
@@ -159,7 +158,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)
     if (!link->irq)
 	    goto failed;
 
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
     
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index bb909e1..ae263b1 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -46,7 +46,6 @@
 #include <scsi/scsi_host.h>
 #include "fdomain.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -85,7 +84,7 @@ static int fdomain_probe(struct pcmcia_device *link)
 	link->priv = info;
 	link->resource[0]->end = 0x10;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->config_regs = PRESENT_OPTION;
 
 	return fdomain_config(link);
@@ -131,7 +130,7 @@ static int fdomain_config(struct pcmcia_device *link)
 
     if (!link->irq)
 	    goto failed;
-    ret = pcmcia_request_configuration(link, &link->conf);
+    ret = pcmcia_enable_device(link);
     if (ret)
 	    goto failed;
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index a5648e9..d0546c0 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -47,7 +47,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -1562,7 +1561,7 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 	link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
 
 	/* General socket configuration */
-	link->conf.Attributes	 = CONF_ENABLE_IRQ;
+	link->config_flags	 |= CONF_ENABLE_IRQ;
 
 	ret = nsp_cs_config(link);
 
@@ -1608,7 +1607,7 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
@@ -1629,7 +1628,7 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 		}
 
 		/* Do we need to allocate an interrupt? */
-		p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+		p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 		/* IO window settings */
 		p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -1700,7 +1699,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
 	if (pcmcia_request_irq(link, nspintr))
 		goto cs_failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto cs_failed;
 
@@ -1749,9 +1748,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
 	if (link->vpp) {
 		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	}
-	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-		printk(", irq %d", link->irq);
-	}
+	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 5e2cbe0..7d3f49c 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -48,7 +48,6 @@
 #include <scsi/scsi_host.h>
 #include "../qlogicfas408.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -158,7 +157,7 @@ static int qlogic_probe(struct pcmcia_device *link)
 	link->priv = info;
 	link->resource[0]->end = 16;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->config_regs = PRESENT_OPTION;
 
 	return qlogic_config(link);
@@ -208,7 +207,7 @@ static int qlogic_config(struct pcmcia_device * link)
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -263,7 +262,7 @@ static int qlogic_resume(struct pcmcia_device *link)
 {
 	scsi_info_t *info = link->priv;
 
-	pcmcia_request_configuration(link, &link->conf);
+	pcmcia_enable_device(link);
 	if ((info->manf_id == MANFID_MACNICA) ||
 	    (info->manf_id == MANFID_PIONEER) ||
 	    (info->manf_id == 0x0098)) {
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 9aaf974..600630e 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -71,7 +71,6 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 #include <pcmcia/ciscode.h>
@@ -721,7 +720,7 @@ SYM53C500_config(struct pcmcia_device *link)
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -861,7 +860,7 @@ SYM53C500_probe(struct pcmcia_device *link)
 	link->priv = info;
 	link->resource[0]->end = 16;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	return SYM53C500_config(link);
 } /* SYM53C500_attach */
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index ee19f2d..47b1869 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
@@ -184,7 +183,7 @@ static void quirk_config_socket(struct pcmcia_device *link)
 	struct serial_info *info = link->priv;
 
 	if (info->multi)
-		link->conf.Attributes |= CONF_ENABLE_ESR;
+		link->config_flags |= CONF_ENABLE_ESR;
 }
 
 static const struct serial_quirk quirks[] = {
@@ -333,9 +332,9 @@ static int serial_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	if (do_sound)
-		link->conf.Attributes |= CONF_ENABLE_SPKR;
+		link->config_flags |= CONF_ENABLE_SPKR;
 
 	return serial_config(link);
 }
@@ -503,7 +502,7 @@ found_port:
 	if (info->quirk && info->quirk->config)
 		info->quirk->config(link);
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		return -1;
 	return setup_serial(link, info, link->resource[0]->start, link->irq);
@@ -579,7 +578,7 @@ static int multi_config(struct pcmcia_device *link)
 	if (info->quirk && info->quirk->config)
 		info->quirk->config(link);
 
-	i = pcmcia_request_configuration(link, &link->conf);
+	i = pcmcia_enable_device(link);
 	if (i != 0)
 		return -ENODEV;
 
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 7892ac1..c68b3dc 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -20,7 +20,6 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index 526682d..c7345db 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -13,7 +13,6 @@
 #include <linux/io.h>
 #include <linux/etherdevice.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 9738cad..ee079ab 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -17,7 +17,6 @@
 #include <linux/pci.h>
 #include <linux/io.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 034cbfc..ee91c89 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -37,7 +37,6 @@ Status: experimental
 #include <linux/delay.h>
 #include <linux/pci.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -692,9 +691,6 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/* Initialize the pcmcia_device structure */
-	link->conf.Attributes = 0;
-
 	cur_dev = link;
 
 	das16cs_pcmcia_config(link);
@@ -723,7 +719,7 @@ static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		return -EINVAL;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -767,14 +763,13 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
+	printk(", irq %u", link->irq);
 	if (link->resource[0])
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index e37ea79..f8f3de5 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -48,7 +48,6 @@ Command support does not exist, but could be added for this board.
 #include "das08.h"
 
 /* pcmcia includes */
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -162,15 +161,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-
 	cur_dev = link;
 
 	das08_pcmcia_config(link);
@@ -211,7 +201,7 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		return -ENODEV;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -263,14 +253,13 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
+	printk(", irq %u", link->irq);
 	if (link->resource[0])
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 8107e40..803683b 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -47,7 +47,6 @@ IRQ is assigned but not used.
 
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -491,15 +490,6 @@ static int dio700_cs_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-
 	pcmcia_cur_dev = link;
 
 	dio700_config(link);
@@ -550,10 +540,10 @@ static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -602,14 +592,13 @@ static void dio700_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
+	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 4f9daa3..6512f7a 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -48,7 +48,6 @@ the PCMCIA interface.
 
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -243,15 +242,6 @@ static int dio24_cs_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-
 	pcmcia_cur_dev = link;
 
 	dio24_config(link);
@@ -302,10 +292,10 @@ static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -353,14 +343,13 @@ static void dio24_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
+	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 2e27a30..255cf40 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -71,7 +71,6 @@ NI manuals:
 #include "comedi_fc.h"
 #include "ni_labpc.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -219,15 +218,6 @@ static int labpc_cs_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-
 	pcmcia_cur_dev = link;
 
 	labpc_config(link);
@@ -281,10 +271,10 @@ static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
 
 	/* Does this card need audio output? */
 	if (cfg->flags & CISTPL_CFTABLE_AUDIO)
-		p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -331,14 +321,14 @@ static void labpc_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq);
+	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index be7e021..b88f52d 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -48,7 +48,6 @@ See the notes in the ni_atmio.o driver.
 #include "ni_stc.h"
 #include "8255.h"
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -265,7 +264,7 @@ static int cs_attach(struct pcmcia_device *link)
 {
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	link->resource[0]->end = 16;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 
 	cur_dev = link;
 
@@ -336,7 +335,7 @@ static void mio_cs_config(struct pcmcia_device *link)
 	if (!link->irq)
 		dev_info(&link->dev, "no IRQ available\n");
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 }
 
 static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index a2a32de..b8940d7 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -50,7 +50,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308
 #include "../comedidev.h"
 #include <linux/semaphore.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -1031,15 +1030,6 @@ static int daqp_cs_attach(struct pcmcia_device *link)
 	local->link = link;
 	link->priv = local;
 
-	/*
-	   General socket configuration defaults can go here.  In this
-	   client, we assume very little, and rely on the CIS for almost
-	   everything.  In most clients, many details (i.e., number, sizes,
-	   and attributes of IO windows) are fixed by the nature of the
-	   device, and can be hard-wired here.
-	 */
-	link->conf.Attributes = 0;
-
 	daqp_cs_config(link);
 
 	return 0;
@@ -1088,7 +1078,7 @@ static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
 		return -ENODEV;
 
 	/* Do we need to allocate an interrupt? */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -1132,14 +1122,13 @@ static void daqp_cs_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x", link->config_index);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %u", link->irq);
+	printk(", irq %u", link->irq);
 	if (link->resource[0])
 		printk(" & %pR", link->resource[0]);
 	if (link->resource[1])
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index 778800f..62a70af 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -83,7 +83,6 @@
 #include <linux/if_arp.h>
 #include <linux/ioport.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
@@ -147,7 +146,7 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 
 	link->resource[0]->end  = HCF_NUM_IO_PORTS;
 	link->resource[0]->flags= IO_DATA_PATH_WIDTH_16;
-	link->conf.Attributes   = CONF_ENABLE_IRQ;
+	link->config_flags     |= CONF_ENABLE_IRQ;
 	link->config_index      = 5;
 	link->config_regs       = PRESENT_OPTION;
 
@@ -301,7 +300,7 @@ void wl_adapter_insert(struct pcmcia_device *link)
 	dev     = link->priv;
 
 	/* Do we need to allocate an interrupt? */
-	link->conf.Attributes |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->io_lines = 6;
 
 	ret = pcmcia_request_io(link);
@@ -312,7 +311,7 @@ void wl_adapter_insert(struct pcmcia_device *link)
 	if (ret != 0)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret != 0)
 		goto failed;
 
diff --git a/drivers/staging/wlags49_h2/wl_internal.h b/drivers/staging/wlags49_h2/wl_internal.h
index 02f0a20..cd129b3 100644
--- a/drivers/staging/wlags49_h2/wl_internal.h
+++ b/drivers/staging/wlags49_h2/wl_internal.h
@@ -69,7 +69,6 @@
  ******************************************************************************/
 #include <linux/version.h>
 #ifdef BUS_PCMCIA
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ciscode.h>
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 5ccc6d0..e23270d 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -8,7 +8,6 @@
 #include <linux/errno.h>	/* error codes */
 #include <linux/slab.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
@@ -143,7 +142,7 @@ static int ixj_config(struct pcmcia_device * link)
 	if (pcmcia_loop_config(link, ixj_config_check, &dflt))
 		goto failed;
 
-	if (pcmcia_request_configuration(link, &link->conf))
+	if (pcmcia_enable_device(link))
 		goto failed;
 
 	/*
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 5904053..744c2cd 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -20,7 +20,6 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -159,7 +158,7 @@ static int sl811_cs_config_check(struct pcmcia_device *p_dev,
 			dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 	/* we need an interrupt */
-	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+	p_dev->config_flags |= CONF_ENABLE_IRQ;
 
 	/* IO window settings */
 	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
@@ -195,7 +194,7 @@ static int sl811_cs_config(struct pcmcia_device *link)
 	if (!link->irq)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
@@ -227,8 +226,6 @@ static int sl811_cs_probe(struct pcmcia_device *link)
 	local->p_dev = link;
 	link->priv = local;
 
-	link->conf.Attributes = 0;
-
 	return sl811_cs_config(link);
 }
 
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
deleted file mode 100644
index 47b6092..0000000
--- a/include/pcmcia/cs.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * cs.h
- *
- * 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.
- *
- * The initial developer of the original code is David A. Hinds
- * <dahinds at users.sourceforge.net>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * (C) 1999             David A. Hinds
- */
-
-#ifndef _LINUX_CS_H
-#define _LINUX_CS_H
-
-#ifdef __KERNEL__
-#include <linux/interrupt.h>
-#endif
-
-/* For RequestConfiguration */
-typedef struct config_req_t {
-    u_int	Attributes;
-} config_req_t;
-
-/* Attributes for RequestConfiguration */
-#define CONF_ENABLE_IRQ		0x01
-#define CONF_ENABLE_DMA		0x02
-#define CONF_ENABLE_SPKR	0x04
-#define CONF_ENABLE_PULSE_IRQ	0x08
-#define CONF_ENABLE_ESR		0x10
-#define CONF_VALID_CLIENT	0x100
-
-#endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index bc28f96..50b03fd 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -24,9 +24,11 @@
 
 #ifdef __KERNEL__
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <pcmcia/ss.h>
 #include <asm/atomic.h>
 
+
 /*
  * PCMCIA device drivers (16-bit cards only; 32-bit cards require CardBus
  * a.k.a. PCI drivers
@@ -88,18 +90,16 @@ struct pcmcia_device {
 
 	struct list_head	socket_device_list;
 
-	/* deprecated, will be cleaned up soon */
-	config_req_t		conf;
-
 	/* device setup */
 	unsigned int		irq;
 	struct resource		*resource[PCMCIA_NUM_RESOURCES];
 	unsigned int		vpp;
 
-	unsigned int		io_lines; /* number of I/O lines */
+	unsigned int		config_flags;	/* CONF_ENABLE_ flags below */
 	unsigned int		config_base;
 	unsigned int		config_index;
 	unsigned int		config_regs;	/* PRESENT_ flags below */
+	unsigned int		io_lines;	/* number of I/O lines */
 
 	/* Is the device suspended? */
 	u16			suspended:1;
@@ -207,8 +207,7 @@ pcmcia_request_exclusive_irq(struct pcmcia_device *p_dev,
 int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
 				irq_handler_t handler);
 
-int pcmcia_request_configuration(struct pcmcia_device *p_dev,
-				 config_req_t *req);
+int pcmcia_enable_device(struct pcmcia_device *p_dev);
 
 int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int speed);
@@ -265,6 +264,12 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
 #define PRESENT_IOBASE_3	0x100
 #define PRESENT_IOSIZE		0x200
 
+/* flags to be passed to pcmcia_enable_device() */
+#define CONF_ENABLE_IRQ         0x01
+#define CONF_ENABLE_SPKR        0x02
+#define CONF_ENABLE_PULSE_IRQ   0x04
+#define CONF_ENABLE_ESR         0x08
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DS_H */
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 626b63c..731cde0 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -19,7 +19,6 @@
 #include <linux/sched.h>	/* task_struct, completion */
 #include <linux/mutex.h>
 
-#include <pcmcia/cs.h>
 #ifdef CONFIG_CARDBUS
 #include <linux/pci.h>
 #endif
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 4df07fc..2476d5f 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -142,7 +142,7 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->resource[0]->end = 16;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
+	link->config_flags = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 	link->config_index = 1;
 	link->config_regs = PRESENT_OPTION;
 
@@ -217,6 +217,7 @@ static int pdacf_config(struct pcmcia_device *link)
 
 	snd_printdd(KERN_DEBUG "pdacf_config called\n");
 	link->config_index = 0x5;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 
 	ret = pcmcia_request_io(link);
 	if (ret)
@@ -226,7 +227,7 @@ static int pdacf_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
index 5cc3e45..bd26e09 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h
@@ -24,7 +24,6 @@
 #include <sound/pcm.h>
 #include <asm/io.h>
 #include <linux/interrupt.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 16186ad..017a8d6 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -2,7 +2,7 @@
  * Driver for Digigram VXpocket V2/440 soundcards
  *
  * Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de>
- *
+
  *   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
@@ -162,7 +162,7 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->resource[0]->end = 16;
 
-	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ;
 	link->config_index = 1;
 	link->config_regs = PRESENT_OPTION;
 
@@ -233,7 +233,7 @@ static int vxpocket_config(struct pcmcia_device *link)
 	if (ret)
 		goto failed;
 
-	ret = pcmcia_request_configuration(link, &link->conf);
+	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
 
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index d911066..13d658c 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -23,7 +23,6 @@
 
 #include <sound/vx_core.h>
 
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:27 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:27 +0200
Subject: [PATCH 11/22] pcmcia: use autoconfiguration feature for ioports and
	iomem
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-11-git-send-email-linux@dominikbrodowski.net>

When CONF_AUTO_SET_IO or CONF_AUTO_SET_IOMEM are set, the corresponding
fields in struct pcmcia_device *p_dev->resource[0,1,2] are set
accordinly. Drivers wishing to override certain settings may do so in
the callback function, but they no longer need to parse the CIS entries
stored in cistpl_cftable_entry_t themselves.

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-ide at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: laforge at gnumonks.org
CC: linux-mtd at lists.infradead.org
CC: linux-bluetooth at vger.kernel.org
CC: alsa-devel at alsa-project.org
CC: linux-serial at vger.kernel.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt          |   12 ++
 drivers/ata/pata_pcmcia.c                        |   81 +++++---------
 drivers/bluetooth/bt3c_cs.c                      |   53 +++++-----
 drivers/bluetooth/btuart_cs.c                    |   51 +++++----
 drivers/bluetooth/dtl1_cs.c                      |   18 +--
 drivers/char/pcmcia/cm4000_cs.c                  |   15 +--
 drivers/char/pcmcia/cm4040_cs.c                  |   22 +---
 drivers/char/pcmcia/ipwireless/main.c            |   26 +---
 drivers/char/pcmcia/synclink_cs.c                |   16 +--
 drivers/ide/ide-cs.c                             |   82 ++++---------
 drivers/isdn/hardware/avm/avm_cs.c               |   19 +---
 drivers/isdn/hisax/avma1_cs.c                    |   22 +---
 drivers/isdn/hisax/elsa_cs.c                     |   23 +---
 drivers/isdn/hisax/sedlbauer_cs.c                |   38 +-----
 drivers/isdn/hisax/teles_cs.c                    |   16 +--
 drivers/net/pcmcia/axnet_cs.c                    |   32 +----
 drivers/net/pcmcia/fmvj18x_cs.c                  |    5 +-
 drivers/net/pcmcia/pcnet_cs.c                    |   38 ++-----
 drivers/net/pcmcia/smc91c92_cs.c                 |   39 +++----
 drivers/net/pcmcia/xirc2ps_cs.c                  |   69 ++++++-----
 drivers/net/wireless/airo_cs.c                   |   34 +-----
 drivers/net/wireless/atmel_cs.c                  |   28 +----
 drivers/net/wireless/hostap/hostap_cs.c          |   43 +-------
 drivers/net/wireless/libertas/if_cs.c            |   16 +--
 drivers/net/wireless/orinoco/orinoco_cs.c        |   41 +------
 drivers/net/wireless/orinoco/spectrum_cs.c       |   45 +-------
 drivers/parport/parport_cs.c                     |   34 ++----
 drivers/pcmcia/pcmcia_cis.c                      |   78 +++++++++++--
 drivers/scsi/pcmcia/aha152x_stub.c               |   34 +++---
 drivers/scsi/pcmcia/fdomain_stub.c               |   13 +--
 drivers/scsi/pcmcia/nsp_cs.c                     |   47 ++------
 drivers/scsi/pcmcia/qlogic_stub.c                |   13 +--
 drivers/scsi/pcmcia/sym53c500_cs.c               |   13 +--
 drivers/serial/serial_cs.c                       |  132 +++++++++++-----------
 drivers/staging/comedi/drivers/cb_das16_cs.c     |   31 +-----
 drivers/staging/comedi/drivers/das08_cs.c        |   33 +-----
 drivers/staging/comedi/drivers/ni_daq_700.c      |   32 +-----
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |   32 +-----
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |   32 +-----
 drivers/staging/comedi/drivers/ni_mio_cs.c       |   14 +--
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |   32 +-----
 drivers/telephony/ixj_pcmcia.c                   |   32 ++----
 drivers/usb/host/sl811_cs.c                      |   28 +----
 include/pcmcia/ds.h                              |   30 ++----
 44 files changed, 517 insertions(+), 1027 deletions(-)

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 62a029f..dd04361 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,16 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_loop_config() and autoconfiguration (as of 2.6.36)
+   If struct pcmcia_device *p_dev->config_flags is set accordingly,
+   pcmcia_loop_config() now sets up certain configuration values
+   automatically, though the driver may still override the settings
+   in the callback function. The following autoconfiguration options
+   are provided at the moment:
+	CONF_AUTO_CHECK_VCC : check for matching Vcc
+	CONF_AUTO_SET_VPP   : set Vpp
+	CONF_AUTO_AUDIO     : auto-enable audio line, if required
+	CONF_AUTO_SET_IO    : set ioport resources (->resource[0,1])
+	CONF_AUTO_SET_IOMEM : set first iomem resource (->resource[2])
+
 * pcmcia_request_configuration -> pcmcia_enable_device (as of 2.6.36)
    pcmcia_request_configuration() got renamed to pcmcia_enable_device(),
    as it mirrors pcmcia_disable_device(). Configuration settings are now
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 954f43c..88cb03c 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -167,45 +167,26 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {
 };
 
 
-struct pcmcia_config_check {
-	unsigned long ctl_base;
-	int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-	struct pcmcia_config_check *stk = priv_data;
-
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		pdev->resource[0]->start = io->win[0].base;
-		if (!(io->flags & CISTPL_IO_16BIT)) {
-			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		}
-		if (io->nwin == 2) {
-			pdev->resource[0]->end = 8;
-			pdev->resource[1]->start = io->win[1].base;
-			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[1]->start;
-		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->resource[0]->end = io->win[0].len;
-			pdev->resource[1]->end = 0;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[0]->start + 0x0e;
-		} else
+	int *is_kme = priv_data;
+
+	if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+		pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	}
+	pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	if (pdev->resource[1]->end) {
+		pdev->resource[0]->end = 8;
+		pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+	} else {
+		if (pdev->resource[0]->end < 16)
 			return -ENODEV;
-		/* If we've got this far, we're done */
-		return 0;
 	}
-	return -ENODEV;
+
+	return pcmcia_request_io(pdev);
 }
 
 /**
@@ -220,7 +201,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 {
 	struct ata_host *host;
 	struct ata_port *ap;
-	struct pcmcia_config_check *stk = NULL;
 	int is_kme = 0, ret = -ENOMEM, p;
 	unsigned long io_base, ctl_base;
 	void __iomem *io_addr, *ctl_addr;
@@ -228,10 +208,8 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	struct ata_port_operations *ops = &pcmcia_port_ops;
 
 	/* Set up attributes in order to probe card and get resources */
-	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	pdev->config_flags |= CONF_ENABLE_IRQ;
-	pdev->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	pdev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+		CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
 	/* See if we have a manufacturer identifier. Use it to set is_kme for
 	   vendor quirks */
@@ -239,21 +217,17 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 		  ((pdev->card_id == PRODID_KME_KXLC005_A) ||
 		   (pdev->card_id == PRODID_KME_KXLC005_B)));
 
-	/* Allocate resoure probing structures */
-
-	stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-	if (!stk)
-		goto out1;
-	stk->is_kme = is_kme;
-	io_base = ctl_base = 0;
-
-	if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk)) {
+	if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme)) {
 		pdev->config_flags &= ~CONF_AUTO_CHECK_VCC;
-		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, stk))
+		if (pcmcia_loop_config(pdev, pcmcia_check_one_config, &is_kme))
 			goto failed; /* No suitable config found */
 	}
 	io_base = pdev->resource[0]->start;
-	ctl_base = stk->ctl_base;
+	if (pdev->resource[1]->end)
+		ctl_base = pdev->resource[1]->start;
+	else
+		ctl_base = pdev->resource[0]->start + 0x0e;
+
 	if (!pdev->irq)
 		goto failed;
 
@@ -310,13 +284,10 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 		goto failed;
 
 	pdev->priv = host;
-	kfree(stk);
 	return 0;
 
 failed:
-	kfree(stk);
 	pcmcia_disable_device(pdev);
-out1:
 	return ret;
 }
 
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 97338a3..8b8be35 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -656,10 +656,8 @@ static int bt3c_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_SET_IO;
 
 	return bt3c_config(link);
 }
@@ -673,38 +671,41 @@ static void bt3c_detach(struct pcmcia_device *link)
 	kfree(info);
 }
 
-static int bt3c_check_config(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cf,
-			     cistpl_cftable_entry_t *dflt,
-			     void *priv_data)
+static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
-	unsigned long try = (unsigned long) priv_data;
-	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+	int *try = priv_data;
 
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-	    (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	if (try == 0)
+		p_dev->io_lines = 16;
+
+	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+		return -EINVAL;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
-				      cistpl_cftable_entry_t *cf,
-				      cistpl_cftable_entry_t *dflt,
 				      void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 8a6864f..9f9bb69 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -585,10 +585,8 @@ static int btuart_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
+		CONF_AUTO_SET_IO;
 
 	return btuart_config(link);
 }
@@ -602,38 +600,41 @@ static void btuart_detach(struct pcmcia_device *link)
 	kfree(info);
 }
 
-static int btuart_check_config(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *try = priv_data;
-	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-	    (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	if (try == 0)
+		p_dev->io_lines = 16;
+
+	if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))
+		return -EINVAL;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
-					cistpl_cftable_entry_t *cf,
-					cistpl_cftable_entry_t *dflt,
 					void *priv_data)
 {
 	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 4620cc3..12cd177 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -571,10 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link)
 	info->p_dev = link;
 	link->priv = info;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return dtl1_config(link);
 }
@@ -589,17 +586,14 @@ static void dtl1_detach(struct pcmcia_device *link)
 	kfree(info);
 }
 
-static int dtl1_confcheck(struct pcmcia_device *p_dev,
-			  cistpl_cftable_entry_t *cf,
-			  cistpl_cftable_entry_t *dflt,
-			  void *priv_data)
+static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cf->io.nwin != 1) || (cf->io.win[0].len <= 8))
+	if ((p_dev->resource[1]->end) || (p_dev->resource[1]->end < 8))
 		return -ENODEV;
 
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;	/*yo */
-	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
 	return pcmcia_request_io(p_dev);
 }
 
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 0b2f3b9..79de9cc 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1741,19 +1741,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
 
 /*==== Interface to PCMCIA Layer =======================================*/
 
-static int cm4000_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
 	return pcmcia_request_io(p_dev);
 }
 
@@ -1761,6 +1750,8 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
 {
 	struct cm4000_dev *dev;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
+
 	/* read the config-tuples */
 	if (pcmcia_loop_config(link, cm4000_config_check, NULL))
 		goto cs_release;
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index acf88d5..bf012d2 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -515,25 +515,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
 	return;
 }
 
-static int cm4040_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int rc;
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	/* Get the IOaddr */
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-	rc = pcmcia_request_io(p_dev);
-
-	dev_printk(KERN_INFO, &p_dev->dev,
-		   "pcmcia_request_io returned 0x%x\n", rc);
-	return rc;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -542,6 +526,8 @@ static int reader_config(struct pcmcia_device *link, int devno)
 	struct reader_dev *dev;
 	int fail_rc;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
+
 	if (pcmcia_loop_config(link, cm4040_config_check, NULL))
 		goto cs_release;
 
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 1b7f092..594c23b 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -75,22 +75,18 @@ static void signalled_reboot_callback(void *callback_data)
 	schedule_work(&ipw->work_reboot);
 }
 
-static int ipwireless_probe(struct pcmcia_device *p_dev,
-			    cistpl_cftable_entry_t *cfg,
-			    cistpl_cftable_entry_t *dflt,
-			    void *priv_data)
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
 {
 	struct ipw_dev *ipw = priv_data;
 	struct resource *io_resource;
 	int ret;
 
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
 
 	/* 0x40 causes it to generate level mode interrupts. */
 	/* 0x04 enables IREQ pin. */
-	p_dev->config_index = cfg->index | 0x44;
+	p_dev->config_index |= 0x44;
 	p_dev->io_lines = 16;
 	ret = pcmcia_request_io(p_dev);
 	if (ret)
@@ -100,26 +96,18 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 				resource_size(p_dev->resource[0]),
 				IPWIRELESS_PCCARD_NAME);
 
-	if (cfg->mem.nwin == 0)
-		return 0;
-
 	p_dev->resource[2]->flags |=
 		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	p_dev->resource[2]->start = cfg->mem.win[0].host_addr;
-	p_dev->resource[2]->end = cfg->mem.win[0].len;
-	if (p_dev->resource[2]->end < 0x1000)
-		p_dev->resource[2]->end = 0x1000;
 
 	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
 	if (ret != 0)
 		goto exit1;
 
-	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2],
-				cfg->mem.win[0].card_addr);
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
 	if (ret != 0)
 		goto exit2;
 
-	ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
+	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
 
 	ipw->attr_memory = ioremap(p_dev->resource[2]->start,
 				resource_size(p_dev->resource[2]));
@@ -165,13 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
 	int ret = 0;
 
 	ipw->is_v2_card = 0;
+	link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
+		CONF_ENABLE_IRQ;
 
 	ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
 	if (ret != 0)
 		return ret;
 
-	link->config_flags |= CONF_ENABLE_IRQ;
-
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
 	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index c701434..a343b8f 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -561,19 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link)
 /* Card has been inserted.
  */
 
-static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
-			  cistpl_cftable_entry_t *cfg,
-			  cistpl_cftable_entry_t *dflt,
-			  void *priv_data)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (!cfg->io.nwin)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
 	return pcmcia_request_io(p_dev);
 }
 
@@ -585,11 +574,12 @@ static int mgslpc_config(struct pcmcia_device *link)
     if (debug_level >= DEBUG_LEVEL_INFO)
 	    printk("mgslpc_config(0x%p)\n", link);
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
     if (ret != 0)
 	    goto failed;
 
-    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 8;
     link->config_regs = PRESENT_OPTION;
 
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 25b8a10..c389d9a 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -96,10 +96,8 @@ static int ide_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->config_flags |= CONF_ENABLE_IRQ;
-    link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO |
+	    CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
 
     return ide_config(link);
 } /* ide_attach */
@@ -194,52 +192,31 @@ out_release:
 
 ======================================================================*/
 
-struct pcmcia_config_check {
-	unsigned long ctl_base;
-	int is_kme;
-};
-
-static int pcmcia_check_one_config(struct pcmcia_device *pdev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   void *priv_data)
+static int pcmcia_check_one_config(struct pcmcia_device *pdev, void *priv_data)
 {
-	struct pcmcia_config_check *stk = priv_data;
-
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		pdev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		pdev->config_index = cfg->index;
-		pdev->resource[0]->start = io->win[0].base;
-		if (!(io->flags & CISTPL_IO_16BIT)) {
-			pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-			pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		}
-		if (io->nwin == 2) {
-			pdev->resource[0]->end = 8;
-			pdev->resource[1]->start = io->win[1].base;
-			pdev->resource[1]->end = (stk->is_kme) ? 2 : 1;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[1]->start;
-		} else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
-			pdev->resource[0]->end = io->win[0].len;
-			pdev->resource[1]->end = 0;
-			if (pcmcia_request_io(pdev) != 0)
-				return -ENODEV;
-			stk->ctl_base = pdev->resource[0]->start + 0x0e;
-		} else
+	int *is_kme = priv_data;
+
+	if (!(pdev->resource[0]->flags & IO_DATA_PATH_WIDTH_8)) {
+		pdev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+	}
+	pdev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	if (pdev->resource[1]->end) {
+		pdev->resource[0]->end = 8;
+		pdev->resource[1]->end = (*is_kme) ? 2 : 1;
+	} else {
+		if (pdev->resource[0]->end < 16)
 			return -ENODEV;
-		/* If we've got this far, we're done */
-		return 0;
 	}
-	return -ENODEV;
+
+	return pcmcia_request_io(pdev);
 }
 
 static int ide_config(struct pcmcia_device *link)
 {
     ide_info_t *info = link->priv;
-    struct pcmcia_config_check *stk = NULL;
     int ret = 0, is_kme = 0;
     unsigned long io_base, ctl_base;
     struct ide_host *host;
@@ -250,19 +227,16 @@ static int ide_config(struct pcmcia_device *link)
 	      ((link->card_id == PRODID_KME_KXLC005_A) ||
 	       (link->card_id == PRODID_KME_KXLC005_B)));
 
-    stk = kzalloc(sizeof(*stk), GFP_KERNEL);
-    if (!stk)
-	    goto err_mem;
-    stk->is_kme = is_kme;
-    io_base = ctl_base = 0;
-
-    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+    if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme)) {
 	    link->config_flags &= ~CONF_AUTO_CHECK_VCC;
-	    if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+	    if (pcmcia_loop_config(link, pcmcia_check_one_config, &is_kme))
 		    goto failed; /* No suitable config found */
     }
     io_base = link->resource[0]->start;
-    ctl_base = stk->ctl_base;
+    if (link->resource[1]->end)
+	    ctl_base = link->resource[1]->start;
+    else
+	    ctl_base = link->resource[0]->start + 0x0e;
 
     if (!link->irq)
 	    goto failed;
@@ -294,15 +268,9 @@ static int ide_config(struct pcmcia_device *link)
 	    'a' + host->ports[0]->index * 2,
 	    link->vpp / 10, link->vpp % 10);
 
-    kfree(stk);
     return 0;
 
-err_mem:
-    printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");
-    goto failed;
-
 failed:
-    kfree(stk);
     ide_release(link);
     return -ENODEV;
 } /* ide_config */
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 9dbab9c..403a995 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -72,13 +72,8 @@ static void avmcs_detach(struct pcmcia_device *p_dev);
 
 static int avmcs_probe(struct pcmcia_device *p_dev)
 {
-
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-
     /* General socket configuration */
-    p_dev->config_flags |= CONF_ENABLE_IRQ;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     p_dev->config_index = 1;
     p_dev->config_regs = PRESENT_OPTION;
 
@@ -107,16 +102,12 @@ static void avmcs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int avmcs_configcheck(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cf,
-			     cistpl_cftable_entry_t *dflt,
-			     void *priv_data)
+static int avmcs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cf->io.nwin <= 0)
-		return -ENODEV;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;
 	return pcmcia_request_io(p_dev);
 }
 
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 2f2b000..cb09f0c 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -76,14 +76,8 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 {
     dev_dbg(&p_dev->dev, "avma1cs_attach()\n");
 
-    /* The io structure describes IO port mapping */
-    p_dev->resource[0]->end = 16;
-    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    p_dev->resource[1]->end = 16;
-    p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-
     /* General socket configuration */
-    p_dev->config_flags |= CONF_ENABLE_IRQ;
+    p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     p_dev->config_index = 1;
     p_dev->config_regs = PRESENT_OPTION;
 
@@ -114,17 +108,13 @@ static void __devexit avma1cs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int avma1cs_configcheck(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cf->io.nwin <= 0)
-		return -ENODEV;
-
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->resource[0]->end = cf->io.win[0].len;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	p_dev->io_lines = 5;
+
 	return pcmcia_request_io(p_dev);
 }
 
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index 0a65280..f203a52 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -118,16 +118,6 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
 
     local->cardnr = -1;
 
-    /*
-      General socket configuration defaults can go here.  In this
-      client, we assume very little, and rely on the CIS for almost
-      everything.  In most clients, many details (i.e., number, sizes,
-      and attributes of IO windows) are fixed by the nature of the
-      device, and can be hard-wired here.
-    */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
     return elsa_cs_config(link);
 } /* elsa_cs_attach */
 
@@ -160,18 +150,17 @@ static void __devexit elsa_cs_detach(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int j;
 
 	p_dev->io_lines = 3;
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+	if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
 		printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-		p_dev->resource[0]->start = cf->io.win[0].base;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
@@ -194,6 +183,8 @@ static int __devinit elsa_cs_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);
     dev = link->priv;
 
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
     if (i != 0)
 	goto failed;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index b69eccf..a88c88f 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -128,8 +128,6 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
     /* from old sedl_cs 
     */
     /* The io structure describes IO port mapping */
-    link->resource[0]->end = 8;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
     return sedlbauer_config(link);
 } /* sedlbauer_attach */
@@ -161,35 +159,13 @@ static void __devexit sedlbauer_detach(struct pcmcia_device *link)
     device available to the system.
     
 ======================================================================*/
-static int sedlbauer_config_check(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cfg,
-				  cistpl_cftable_entry_t *dflt,
-				  void *priv_data)
+static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		p_dev->io_lines = 3;
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	return 0;
+	p_dev->io_lines = 3;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -202,7 +178,7 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
     dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
 
     link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
-	    CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
+	    CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
     /*
       In this loop, we scan the CIS for configuration table entries,
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 6605480..05a5631 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -105,10 +105,7 @@ static int __devinit teles_probe(struct pcmcia_device *link)
       and attributes of IO windows) are fixed by the nature of the
       device, and can be hard-wired here.
     */
-    link->resource[0]->end = 96;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return teles_cs_config(link);
 } /* teles_attach */
@@ -142,18 +139,17 @@ static void __devexit teles_detach(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static int teles_cs_configcheck(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cf,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int j;
 
 	p_dev->io_lines = 5;
+	p_dev->resource[0]->end = 96;
+	p_dev->resource[0]->flags &= IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
-	if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+	if ((p_dev->resource[0]->end) && p_dev->resource[0]->start) {
 		printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-		p_dev->resource[0]->start = cf->io.win[0].base;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	} else {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 17f1040..9d9d997 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -284,34 +284,16 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
-static int axnet_configcheck(struct pcmcia_device *p_dev,
-			     cistpl_cftable_entry_t *cfg,
-			     cistpl_cftable_entry_t *dflt,
-			     void *priv_data)
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int i;
-	cistpl_io_t *io = &cfg->io;
-
-	if (cfg->index == 0 || cfg->io.nwin == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
 	p_dev->config_index = 0x05;
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-		i = (io->win[1].len > io->win[0].len);
-		p_dev->resource[1]->start = io->win[1-i].base;
-		p_dev->resource[1]->end = io->win[1-i].len;
-	} else {
-		i = p_dev->resource[1]->end = 0;
-	}
-	p_dev->resource[0]->start = io->win[i].base;
-	p_dev->resource[0]->end = io->win[i].len;
-	p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-		return try_io_port(p_dev);
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+		return -ENODEV;
 
-	return -ENODEV;
+	return try_io_port(p_dev);
 }
 
 static int axnet_config(struct pcmcia_device *link)
@@ -324,6 +306,7 @@ static int axnet_config(struct pcmcia_device *link)
 
     /* don't trust the CIS on this; Linksys got it wrong */
     link->config_regs = 0x63;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
     if (ret != 0)
 	goto failed;
@@ -331,7 +314,6 @@ static int axnet_config(struct pcmcia_device *link)
     if (!link->irq)
 	    goto failed;
 
-    link->config_flags |= CONF_ENABLE_IRQ;
     if (resource_size(link->resource[1]) == 8)
 	link->config_flags |= CONF_ENABLE_SPKR;
     
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index c1479e3..792ab38 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -319,10 +319,7 @@ static int ungermann_try_io_port(struct pcmcia_device *link)
     return ret;	/* RequestIO failed */
 }
 
-static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   void *priv_data)
+static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
 	return 0; /* strange, but that's what the code did already before... */
 }
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index 12b028c..ffe2587 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -259,7 +259,7 @@ static int pcnet_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = dev;
 
-    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     dev->netdev_ops = &pcnet_netdev_ops;
 
@@ -500,42 +500,22 @@ static int try_io_port(struct pcmcia_device *link)
     }
 }
 
-static int pcnet_confcheck(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   void *priv_data)
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *priv = priv_data;
 	int try = (*priv & 0x1);
-	int i;
-	cistpl_io_t *io = &cfg->io;
 
-	if (cfg->index == 0 || cfg->io.nwin == 0)
-		return -EINVAL;
+	*priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
 
-	/* For multifunction cards, by convention, we configure the
-	   network function with window 0, and serial with window 1 */
-	if (io->nwin > 1) {
-		i = (io->win[1].len > io->win[0].len);
-		p_dev->resource[1]->start = io->win[1-i].base;
-		p_dev->resource[1]->end = io->win[1-i].len;
-	} else {
-		i = p_dev->resource[1]->end = 0;
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	*priv &= ((cfg->mem.nwin == 1) &&
-		  (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
+	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+		return -EINVAL;
 
-	p_dev->resource[0]->start = io->win[i].base;
-	p_dev->resource[0]->end = io->win[i].len;
-	if (!try)
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-	else
+	if (try)
 		p_dev->io_lines = 16;
-	if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
-		return try_io_port(p_dev);
-
-	return -EINVAL;
+	return try_io_port(p_dev);
 }
 
 static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index e127d2b..a8cef28 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -323,9 +323,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     spin_lock_init(&smc->lock);
-    link->resource[0]->end = 16;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->config_flags |= CONF_ENABLE_IRQ;
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
@@ -417,18 +414,21 @@ static int mhz_3288_power(struct pcmcia_device *link)
     return 0;
 }
 
-static int mhz_mfc_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cf,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int k;
-	p_dev->resource[1]->start = cf->io.win[0].base;
+	p_dev->io_lines = 16;
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	for (k = 0; k < 0x400; k += 0x10) {
 		if (k & 0x80)
 			continue;
 		p_dev->resource[0]->start = k ^ 0x300;
-		p_dev->io_lines = 16;
 		if (!pcmcia_request_io(p_dev))
 			return 0;
 	}
@@ -442,9 +442,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     unsigned int offset;
     int i;
 
-    link->config_flags |= CONF_ENABLE_SPKR;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->end = 8;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ |
+	    CONF_AUTO_SET_IO;
 
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
@@ -586,13 +585,12 @@ static int mot_setup(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int smc_configcheck(struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cf,
-			   cistpl_cftable_entry_t *dflt,
-			   void *priv_data)
+static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data)
 {
-	p_dev->resource[0]->start = cf->io.win[0].base;
-	p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
 	return pcmcia_request_io(p_dev);
 }
 
@@ -601,7 +599,8 @@ static int smc_config(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     int i;
 
-    link->resource[0]->end = 16;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
     i = pcmcia_loop_config(link, smc_configcheck, NULL);
     if (!i)
 	    dev->base_addr = link->resource[0]->start;
@@ -634,7 +633,7 @@ static int osi_config(struct pcmcia_device *link)
     static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
-    link->config_flags |= CONF_ENABLE_SPKR;
+    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ;
     link->resource[0]->end = 64;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->end = 8;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 2bc2eb8..cecc074 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -528,7 +528,6 @@ xirc2ps_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     /* General socket configuration */
-    link->config_flags |= CONF_ENABLE_IRQ;
     link->config_index = 1;
 
     /* Fill in card specific entries */
@@ -665,42 +664,53 @@ has_ce2_string(struct pcmcia_device * p_dev)
 }
 
 static int
-xirc2ps_config_modem(struct pcmcia_device *p_dev,
-		     cistpl_cftable_entry_t *cf,
-		     cistpl_cftable_entry_t *dflt,
-		     void *priv_data)
+xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data)
 {
 	unsigned int ioaddr;
 
-	if (cf->io.nwin > 0  &&  (cf->io.win[0].base & 0xf) == 8) {
-		for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
-			p_dev->resource[1]->start = cf->io.win[0].base;
-			p_dev->resource[0]->start = ioaddr;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if ((p_dev->resource[0]->start & 0xf) == 8)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 16;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 10;
+
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+		p_dev->resource[0]->start = ioaddr;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
 
 static int
-xirc2ps_config_check(struct pcmcia_device *p_dev,
-		     cistpl_cftable_entry_t *cf,
-		     cistpl_cftable_entry_t *dflt,
-		     void *priv_data)
+xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int *pass = priv_data;
+	resource_size_t tmp = p_dev->resource[1]->start;
 
-	if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
-		p_dev->resource[1]->start = cf->io.win[0].base;
-		p_dev->resource[0]->start = p_dev->resource[1]->start
-			+ (*pass ? (cf->index & 0x20 ? -24:8)
-			   : (cf->index & 0x20 ?   8:-24));
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8)
+		: (p_dev->config_index & 0x20 ?   8 : -24));
+
+	if ((p_dev->resource[0]->start & 0xf) == 8)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 18;
+	p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 10;
 
+	p_dev->resource[1]->start = p_dev->resource[0]->start;
+	p_dev->resource[0]->start = tmp;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -803,21 +813,16 @@ xirc2ps_config(struct pcmcia_device * link)
 	goto failure;
     }
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-    link->io_lines = 10;
     if (local->modem) {
 	int pass;
+	link->config_flags |= CONF_AUTO_SET_IO;
 
-	link->resource[1]->end = 8;
-	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	if (local->dingo) {
 	    /* Take the Modem IO port from the CIS and scan for a free
 	     * Ethernet port */
-	    link->resource[0]->end = 16; /* no Mako stuff anymore */
 	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
 		    goto port_found;
 	} else {
-	    link->resource[0]->end = 18;
 	    /* We do 2 passes here: The first one uses the regular mapping and
 	     * the second tries again, thereby considering that the 32 ports are
 	     * mirrored every 32 bytes. Actually we use a mirrored port for
@@ -833,7 +838,9 @@ xirc2ps_config(struct pcmcia_device * link)
 	}
 	printk(KNOT_XIRC "no ports available\n");
     } else {
+	link->io_lines = 10;
 	link->resource[0]->end = 16;
+	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
 	    link->resource[0]->start = ioaddr;
 	    if (!(err = pcmcia_request_io(link)))
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 63bf662..77682f2 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -137,36 +137,12 @@ static void airo_detach(struct pcmcia_device *link)
 
   ======================================================================*/
 
-static int airo_cs_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int airo_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
-	if (pcmcia_request_io(p_dev) != 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -180,7 +156,7 @@ static int airo_config(struct pcmcia_device *link)
 	dev_dbg(&link->dev, "airo_config\n");
 
 	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
-		CONF_AUTO_AUDIO;
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
 	/*
 	 * In this loop, we scan the CIS for configuration table
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 812decd..2029380 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -154,31 +154,11 @@ static int card_present(void *arg)
 	return 0;
 }
 
-static int atmel_config_check(struct pcmcia_device *p_dev,
-			      cistpl_cftable_entry_t *cfg,
-			      cistpl_cftable_entry_t *dflt,
-			      void *priv_data)
+static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -194,7 +174,7 @@ static int atmel_config(struct pcmcia_device *link)
 	dev_dbg(&link->dev, "atmel_config\n");
 
 	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
-		CONF_AUTO_AUDIO;
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
 	/*
 	  In this loop, we scan the CIS for configuration table entries,
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index d4f19af..e57b201 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -469,46 +469,11 @@ static void prism2_detach(struct pcmcia_device *link)
 /* run after a CARD_INSERTION event is received to configure the PCMCIA
  * socket and make the device available to the system */
 
-static int prism2_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int prism2_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X "
-	       "(default 0x%02X)\n", cfg->index, dflt->index);
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d "
-	       "dflt->io.nwin=%d\n",
-	       cfg->io.nwin, dflt->io.nwin);
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -531,7 +496,7 @@ static int prism2_config(struct pcmcia_device *link)
 
 	/* Look for an appropriate configuration table entry in the CIS */
 	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO |
-		CONF_AUTO_CHECK_VCC;
+		CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 	if (ignore_cis_vcc)
 		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, prism2_config_check, NULL);
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 031f3e6..2c6f28a 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -794,20 +794,12 @@ static void if_cs_release(struct pcmcia_device *p_dev)
  * insertion event.
  */
 
-static int if_cs_ioprobe(struct pcmcia_device *p_dev,
-			 cistpl_cftable_entry_t *cfg,
-			 cistpl_cftable_entry_t *dflt,
-			 void *priv_data)
+static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
 {
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	if (cfg->io.nwin != 1) {
+	if (p_dev->resource[1]->end) {
 		lbs_pr_err("wrong CIS (check number of IO windows)\n");
 		return -ENODEV;
 	}
@@ -833,6 +825,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	card->p_dev = p_dev;
 	p_dev->priv = card;
 
+	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
 		lbs_pr_err("error in pcmcia_loop_config\n");
 		goto out1;
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index b921738..263dfe9 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -142,42 +142,12 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
  * device available to the system.
  */
 
-static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
-				   cistpl_cftable_entry_t *cfg,
-				   cistpl_cftable_entry_t *dflt,
-				   void *priv_data)
+static int orinoco_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		goto next_entry;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			goto next_entry;
-	}
-	return 0;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-next_entry:
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -202,7 +172,8 @@ orinoco_cs_config(struct pcmcia_device *link)
 	 * and most client drivers will only use the CIS to fill in
 	 * implementation-defined details.
 	 */
-	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 	if (ignore_cis_vcc)
 		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index f462c78..7844650 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -205,48 +205,12 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
  */
 
 static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
-				    cistpl_cftable_entry_t *cfg,
-				    cistpl_cftable_entry_t *dflt,
 				    void *priv_data)
 {
-	if (cfg->index == 0)
-		goto next_entry;
-
-	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->vpp =
-			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			goto next_entry;
-	}
-	return 0;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-next_entry:
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 };
 
 static int
@@ -271,7 +235,8 @@ spectrum_cs_config(struct pcmcia_device *link)
 	 * and most client drivers will only use the CIS to fill in
 	 * implementation-defined details.
 	 */
-	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC;
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC |
+		CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
 	if (ignore_cis_vcc)
 		link->config_flags &= ~CONF_AUTO_CHECK_VCC;
 	ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 8c2a473..3730184 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -100,9 +100,7 @@ static int parport_probe(struct pcmcia_device *link)
     link->priv = info;
     info->p_dev = link;
 
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
     return parport_config(link);
 } /* parport_attach */
@@ -133,27 +131,14 @@ static void parport_detach(struct pcmcia_device *link)
 
 ======================================================================*/
 
-static int parport_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int parport_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		if (epp_mode)
-			p_dev->config_index |= FORCE_EPP_MODE;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin == 2) {
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-		return 0;
-	}
-	return -ENODEV;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int parport_config(struct pcmcia_device *link)
@@ -164,6 +149,9 @@ static int parport_config(struct pcmcia_device *link)
 
     dev_dbg(&link->dev, "parport_config\n");
 
+    if (epp_mode)
+	    link->config_index |= FORCE_EPP_MODE;
+
     ret = pcmcia_loop_config(link, parport_config_check, NULL);
     if (ret)
 	    goto failed;
diff --git a/drivers/pcmcia/pcmcia_cis.c b/drivers/pcmcia/pcmcia_cis.c
index 160da06..e2c9241 100644
--- a/drivers/pcmcia/pcmcia_cis.c
+++ b/drivers/pcmcia/pcmcia_cis.c
@@ -6,7 +6,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Copyright (C) 1999	     David A. Hinds
- * Copyright (C) 2004-2009   Dominik Brodowski
+ * Copyright (C) 2004-2010   Dominik Brodowski
  *
  * 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
@@ -125,13 +125,24 @@ next_entry:
 	return ret;
 }
 
+
+/**
+ * pcmcia_io_cfg_data_width() - convert cfgtable to data path width parameter
+ */
+static int pcmcia_io_cfg_data_width(unsigned int flags)
+{
+	if (!(flags & CISTPL_IO_8BIT))
+		return IO_DATA_PATH_WIDTH_16;
+	if (!(flags & CISTPL_IO_16BIT))
+		return IO_DATA_PATH_WIDTH_8;
+	return IO_DATA_PATH_WIDTH_AUTO;
+}
+
+
 struct pcmcia_cfg_mem {
 	struct pcmcia_device *p_dev;
+	int (*conf_check) (struct pcmcia_device *p_dev, void *priv_data);
 	void *priv_data;
-	int (*conf_check) (struct pcmcia_device *p_dev,
-			   cistpl_cftable_entry_t *cfg,
-			   cistpl_cftable_entry_t *dflt,
-			   void *priv_data);
 	cisparse_t parse;
 	cistpl_cftable_entry_t dflt;
 };
@@ -184,16 +195,63 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
 	if ((flags & CONF_AUTO_AUDIO) && (cfg->flags & CISTPL_CFTABLE_AUDIO))
 		p_dev->config_flags |= CONF_ENABLE_SPKR;
 
-	return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt,
-				   cfg_mem->priv_data);
+
+	/* IO window settings? */
+	if (flags & CONF_AUTO_SET_IO) {
+		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+		int i = 0;
+
+		p_dev->resource[0]->start = p_dev->resource[0]->end = 0;
+		p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+		if (io->nwin == 0)
+			return -ENODEV;
+
+		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+		p_dev->resource[0]->flags |=
+					pcmcia_io_cfg_data_width(io->flags);
+		if (io->nwin > 1) {
+			/* For multifunction cards, by convention, we
+			 * configure the network function with window 0,
+			 * and serial with window 1 */
+			i = (io->win[1].len > io->win[0].len);
+			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
+			p_dev->resource[1]->start = io->win[1-i].base;
+			p_dev->resource[1]->end = io->win[1-i].len;
+		}
+		p_dev->resource[0]->start = io->win[i].base;
+		p_dev->resource[0]->end = io->win[i].len;
+		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
+	}
+
+	/* MEM window settings? */
+	if (flags & CONF_AUTO_SET_IOMEM) {
+		/* so far, we only set one memory window */
+		cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+
+		p_dev->resource[2]->start = p_dev->resource[2]->end = 0;
+		if (mem->nwin == 0)
+			return -ENODEV;
+
+		p_dev->resource[2]->start = mem->win[0].host_addr;
+		p_dev->resource[2]->end = mem->win[0].len;
+		if (p_dev->resource[2]->end < 0x1000)
+			p_dev->resource[2]->end = 0x1000;
+		p_dev->card_addr = mem->win[0].card_addr;
+	}
+
+	dev_dbg(&p_dev->dev,
+		"checking configuration %x: %pr %pr %pr (%d lines)\n",
+		p_dev->config_index, p_dev->resource[0], p_dev->resource[1],
+		p_dev->resource[2], p_dev->io_lines);
+
+	return cfg_mem->conf_check(p_dev, cfg_mem->priv_data);
 }
 
 /**
  * pcmcia_loop_config() - loop over configuration options
  * @p_dev:	the struct pcmcia_device which we need to loop for.
  * @conf_check:	function to call for each configuration option.
- *		It gets passed the struct pcmcia_device, the CIS data
- *		describing the configuration option, and private data
+ *		It gets passed the struct pcmcia_device and private data
  *		being passed to pcmcia_loop_config()
  * @priv_data:	private data to be passed to the conf_check function.
  *
@@ -203,8 +261,6 @@ static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv)
  */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
-						 cistpl_cftable_entry_t *cfg,
-						 cistpl_cftable_entry_t *dflt,
 						 void *priv_data),
 		       void *priv_data)
 {
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 0b5fc2f..bd9ce09 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -99,9 +99,7 @@ static int aha152x_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = info;
 
-    link->resource[0]->end = 0x20;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-    link->config_flags |= CONF_ENABLE_IRQ;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
     link->config_regs = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
@@ -121,24 +119,24 @@ static void aha152x_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int aha152x_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int aha152x_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
+
 	/* For New Media T&J, look for a SCSI window */
-	if (cfg->io.win[0].len >= 0x20)
-		p_dev->resource[0]->start = cfg->io.win[0].base;
-	else if ((cfg->io.nwin > 1) &&
-		 (cfg->io.win[1].len >= 0x20))
-		p_dev->resource[0]->start = cfg->io.win[1].base;
-	if ((cfg->io.nwin > 0) &&
-	    (p_dev->resource[0]->start < 0xffff)) {
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -EINVAL;
+	if ((p_dev->resource[0]->end < 0x20) &&
+		(p_dev->resource[1]->end >= 0x20))
+		p_dev->resource[0]->start = p_dev->resource[1]->start;
+
+	if (p_dev->resource[0]->start >= 0xffff)
+		return -EINVAL;
+
+	p_dev->resource[1]->start = p_dev->resource[1]->end = 0;
+	p_dev->resource[0]->end = 0x20;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int aha152x_config_cs(struct pcmcia_device *link)
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 3b9f311..f2dc627 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -82,9 +82,7 @@ static int fdomain_probe(struct pcmcia_device *link)
 
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 0x10;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 	link->config_regs = PRESENT_OPTION;
 
 	return fdomain_config(link);
@@ -103,13 +101,12 @@ static void fdomain_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int fdomain_config_check(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int fdomain_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
+	p_dev->resource[0]->end = 0x10;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	return pcmcia_request_io(p_dev);
 }
 
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 344d499..3b90ad9 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1556,13 +1556,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 
 	nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info);
 
-	/* The io structure describes IO port mapping */
-	link->resource[0]->end	 = 0x10;
-	link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO;
-
-	/* General socket configuration */
-	link->config_flags	 |= CONF_ENABLE_IRQ;
-
 	ret = nsp_cs_config(link);
 
 	nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
@@ -1594,50 +1587,27 @@ static void nsp_cs_detach(struct pcmcia_device *link)
     ethernet device available to the system.
 ======================================================================*/
 
-static int nsp_cs_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int nsp_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	nsp_hw_data		*data = priv_data;
 
-	if (cfg->index == 0)
+	if (p_dev->config_index == 0)
 		return -ENODEV;
 
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-					pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			goto next_entry;
-	}
+	/* This reserves IO space but doesn't actually enable it */
+	if (pcmcia_request_io(p_dev) != 0)
+		goto next_entry;
 
-	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
-		cistpl_mem_t	*mem =
-			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+	if (resource_size(p_dev->resource[2])) {
 		p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
 					WIN_MEMORY_TYPE_CM |
 					WIN_ENABLE);
-		p_dev->resource[2]->start = mem->win[0].host_addr;
-		p_dev->resource[2]->end = mem->win[0].len;
 		if (p_dev->resource[2]->end < 0x1000)
 			p_dev->resource[2]->end = 0x1000;
 		if (pcmcia_request_window(p_dev, p_dev->resource[2], 0) != 0)
 			goto next_entry;
 		if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
-						mem->win[0].card_addr) != 0)
+						p_dev->card_addr) != 0)
 			goto next_entry;
 
 		data->MmioAddress = (unsigned long)
@@ -1664,7 +1634,8 @@ static int nsp_cs_config(struct pcmcia_device *link)
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
 	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
-		CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO;
+		CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IOMEM |
+		CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
 	if (ret)
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 468fd12..e8a06e3 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -155,9 +155,7 @@ static int qlogic_probe(struct pcmcia_device *link)
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 16;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 	link->config_regs = PRESENT_OPTION;
 
 	return qlogic_config(link);
@@ -176,14 +174,11 @@ static void qlogic_detach(struct pcmcia_device *link)
 
 /*====================================================================*/
 
-static int qlogic_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cfg,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int qlogic_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
 	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 7a0bb9a..6ceb57c 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -683,14 +683,11 @@ static struct scsi_host_template sym53c500_driver_template = {
      .shost_attrs		= SYM53C500_shost_attrs
 };
 
-static int SYM53C500_config_check(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cfg,
-				  cistpl_cftable_entry_t *dflt,
-				  void *priv_data)
+static int SYM53C500_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	p_dev->io_lines = 10;
-	p_dev->resource[0]->start = cfg->io.win[0].base;
-	p_dev->resource[0]->end = cfg->io.win[0].len;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
 	if (p_dev->resource[0]->start == 0)
 		return -ENODEV;
@@ -857,9 +854,7 @@ SYM53C500_probe(struct pcmcia_device *link)
 		return -ENOMEM;
 	info->p_dev = link;
 	link->priv = info;
-	link->resource[0]->end = 16;
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-	link->config_flags |= CONF_ENABLE_IRQ;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return SYM53C500_config(link);
 } /* SYM53C500_attach */
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index a796a93..4225203 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -424,41 +424,45 @@ static int pfc_config(struct pcmcia_device *p_dev)
 	return -ENODEV;
 }
 
-static int simple_config_check(struct pcmcia_device *p_dev,
-			       cistpl_cftable_entry_t *cf,
-			       cistpl_cftable_entry_t *dflt,
-			       void *priv_data)
+static int simple_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
 	static const int size_table[2] = { 8, 16 };
 	int *try = priv_data;
 
-	p_dev->io_lines = ((*try & 0x1) == 0) ?
-			16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+	if (p_dev->resource[0]->start == 0)
+		return -ENODEV;
 
-	if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[(*try >> 1)])
-	    && (cf->io.win[0].base != 0)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -EINVAL;
+	if ((*try & 0x1) == 0)
+		p_dev->io_lines = 16;
+
+	if (p_dev->resource[0]->end != size_table[(*try >> 1)])
+		return -ENODEV;
+
+	p_dev->resource[0]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int simple_config_check_notpicky(struct pcmcia_device *p_dev,
-					cistpl_cftable_entry_t *cf,
-					cistpl_cftable_entry_t *dflt,
 					void *priv_data)
 {
 	static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 	int j;
 
-	if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
-		for (j = 0; j < 5; j++) {
-			p_dev->resource[0]->start = base[j];
-			p_dev->io_lines = base[j] ? 16 : 3;
-			if (!pcmcia_request_io(p_dev))
-				return 0;
-		}
+	if (p_dev->io_lines > 3)
+		return -ENODEV;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = 8;
+
+	for (j = 0; j < 5; j++) {
+		p_dev->resource[0]->start = base[j];
+		p_dev->io_lines = base[j] ? 16 : 3;
+		if (!pcmcia_request_io(p_dev))
+			return 0;
 	}
 	return -ENODEV;
 }
@@ -468,12 +472,9 @@ static int simple_config(struct pcmcia_device *link)
 	struct serial_info *info = link->priv;
 	int i = -ENODEV, try;
 
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = 8;
-
 	/* First pass: look for a config entry that looks normal.
 	 * Two tries: without IO aliases, then with aliases */
-	link->config_flags |= CONF_AUTO_SET_VPP;
+	link->config_flags |= CONF_AUTO_SET_VPP | CONF_AUTO_SET_IO;
 	for (try = 0; try < 4; try++)
 		if (!pcmcia_loop_config(link, simple_config_check, &try))
 			goto found_port;
@@ -503,43 +504,44 @@ found_port:
 	return setup_serial(link, info, link->resource[0]->start, link->irq);
 }
 
-static int multi_config_check(struct pcmcia_device *p_dev,
-			      cistpl_cftable_entry_t *cf,
-			      cistpl_cftable_entry_t *dflt,
-			      void *priv_data)
+static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	int *base2 = priv_data;
+	int *multi = priv_data;
+
+	if (p_dev->resource[1]->end)
+		return -EINVAL;
 
 	/* The quad port cards have bad CIS's, so just look for a
 	   window larger than 8 ports and assume it will be right */
-	if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev)) {
-			*base2 = p_dev->resource[0]->start + 8;
-			return 0;
-		}
-	}
-	return -ENODEV;
+	if (p_dev->resource[0]->end <= 8)
+		return -EINVAL;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[0]->end = *multi * 8;
+
+	if (pcmcia_request_io(p_dev))
+		return -ENODEV;
+	return 0;
 }
 
 static int multi_config_check_notpicky(struct pcmcia_device *p_dev,
-				       cistpl_cftable_entry_t *cf,
-				       cistpl_cftable_entry_t *dflt,
 				       void *priv_data)
 {
 	int *base2 = priv_data;
 
-	if (cf->io.nwin == 2) {
-		p_dev->resource[0]->start = cf->io.win[0].base;
-		p_dev->resource[1]->start = cf->io.win[1].base;
-		p_dev->io_lines = cf->io.flags & CISTPL_IO_LINES_MASK;
-		if (!pcmcia_request_io(p_dev)) {
-			*base2 = p_dev->resource[1]->start;
-			return 0;
-		}
-	}
-	return -ENODEV;
+	if (!p_dev->resource[0]->end || !p_dev->resource[1]->end)
+		return -ENODEV;
+
+	p_dev->resource[0]->end = p_dev->resource[1]->end = 8;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+
+	if (pcmcia_request_io(p_dev))
+		return -ENODEV;
+
+	*base2 = p_dev->resource[0]->start + 8;
+	return 0;
 }
 
 static int multi_config(struct pcmcia_device *link)
@@ -547,12 +549,12 @@ static int multi_config(struct pcmcia_device *link)
 	struct serial_info *info = link->priv;
 	int i, base2 = 0;
 
+	link->config_flags |= CONF_AUTO_SET_IO;
 	/* First, look for a generic full-sized window */
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	link->resource[0]->end = info->multi * 8;
-	if (pcmcia_loop_config(link, multi_config_check, &base2)) {
+	if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
+		base2 = link->resource[0]->start + 8;
+	else {
 		/* If that didn't work, look for two windows */
-		link->resource[0]->end = link->resource[1]->end = 8;
 		info->multi = 2;
 		if (pcmcia_loop_config(link, multi_config_check_notpicky,
 				       &base2)) {
@@ -587,7 +589,7 @@ static int multi_config(struct pcmcia_device *link)
 		    link->config_index == 3) {
 			err = setup_serial(link, info, base2,
 					link->irq);
-			base2 = link->resource[0]->start;;
+			base2 = link->resource[0]->start;
 		} else {
 			err = setup_serial(link, info, link->resource[0]->start,
 					link->irq);
@@ -611,18 +613,18 @@ static int multi_config(struct pcmcia_device *link)
 	return 0;
 }
 
-static int serial_check_for_multi(struct pcmcia_device *p_dev,
-				  cistpl_cftable_entry_t *cf,
-				  cistpl_cftable_entry_t *dflt,
-				  void *priv_data)
+static int serial_check_for_multi(struct pcmcia_device *p_dev,  void *priv_data)
 {
 	struct serial_info *info = p_dev->priv;
 
-	if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0))
-		info->multi = cf->io.win[0].len >> 3;
+	if (!p_dev->resource[0]->end)
+		return -EINVAL;
+
+	if ((!p_dev->resource[1]->end) && (p_dev->resource[0]->end % 8 == 0))
+		info->multi = p_dev->resource[0]->end >> 3;
 
-	if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) &&
-		(cf->io.win[1].len == 8))
+	if ((p_dev->resource[1]->end) && (p_dev->resource[0]->end == 8)
+		&& (p_dev->resource[1]->end == 8))
 		info->multi = 2;
 
 	return 0; /* break */
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index 678fbf6..c43c689 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -710,36 +710,12 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
 
 
 static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
 				void *priv_data)
 {
-	if (cfg->index == 0)
+	if (p_dev->config_index == 0)
 		return -EINVAL;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev);
-	}
-
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void das16cs_pcmcia_config(struct pcmcia_device *link)
@@ -748,6 +724,9 @@ static void das16cs_pcmcia_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "das16cs_pcmcia_config\n");
 
+	/* Do we need to allocate an interrupt? */
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 12a96b7..d395909 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -192,35 +192,12 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
 
 
 static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		return pcmcia_request_io(p_dev);
-	}
-	return 0;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
+
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -238,6 +215,8 @@ static void das08_pcmcia_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "das08_pcmcia_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index f22dc0f..7129b0c 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -530,35 +530,12 @@ static void dio700_cs_detach(struct pcmcia_device *link)
 ======================================================================*/
 
 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void dio700_config(struct pcmcia_device *link)
@@ -570,7 +547,8 @@ static void dio700_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "dio700_config\n");
 
-	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+		CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
 	if (ret) {
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index 6dc2b06..4defdda 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -282,35 +282,12 @@ static void dio24_cs_detach(struct pcmcia_device *link)
 ======================================================================*/
 
 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 static void dio24_config(struct pcmcia_device *link)
@@ -321,7 +298,8 @@ static void dio24_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "dio24_config\n");
 
-	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
+		CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
 	if (ret) {
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 6eacbd7..5123b31 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -261,35 +261,12 @@ static void labpc_cs_detach(struct pcmcia_device *link)
 ======================================================================*/
 
 static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
 				void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		/* This reserves IO space but doesn't actually enable it */
-		if (pcmcia_request_io(p_dev) != 0)
-			return -ENODEV;
-	}
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* If we got this far, we're cool! */
-	return 0;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -300,7 +277,7 @@ static void labpc_config(struct pcmcia_device *link)
 	dev_dbg(&link->dev, "labpc_config\n");
 
 	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ |
-		CONF_AUTO_AUDIO;
+		CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, NULL);
 	if (ret) {
@@ -316,7 +293,6 @@ static void labpc_config(struct pcmcia_device *link)
 	   the I/O windows and the interrupt mapping, and putting the
 	   card and host interface into "Memory and IO" mode.
 	 */
-	p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
 	ret = pcmcia_enable_device(link);
 	if (ret)
 		goto failed;
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index da4e2a2..f1e31d3 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -262,10 +262,6 @@ static struct pcmcia_device *cur_dev = NULL;
 
 static int cs_attach(struct pcmcia_device *link)
 {
-	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
-	link->resource[0]->end = 16;
-	link->config_flags |= CONF_ENABLE_IRQ;
-
 	cur_dev = link;
 
 	mio_cs_config(link);
@@ -299,15 +295,12 @@ static int mio_cs_resume(struct pcmcia_device *link)
 }
 
 
-static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
 	int base, ret;
 
-	p_dev->resource[0]->end = cfg->io.win[0].len;
-	p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
 	for (base = 0x000; base < 0x400; base += 0x20) {
 		p_dev->resource[0]->start = base;
@@ -324,6 +317,7 @@ static void mio_cs_config(struct pcmcia_device *link)
 	int ret;
 
 	DPRINTK("mio_cs_config(link=%p)\n", link);
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL);
 	if (ret) {
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index 03a72d7..afd283d 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1068,35 +1068,11 @@ static void daqp_cs_detach(struct pcmcia_device *link)
 ======================================================================*/
 
 
-static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev,
-				cistpl_cftable_entry_t *cfg,
-				cistpl_cftable_entry_t *dflt,
-				void *priv_data)
+static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* Do we need to allocate an interrupt? */
-	p_dev->config_flags |= CONF_ENABLE_IRQ;
-
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-		p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-		p_dev->resource[0]->flags |=
-			pcmcia_io_cfg_data_width(io->flags);
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		if (io->nwin > 1) {
-			p_dev->resource[1]->flags = p_dev->resource[0]->flags;
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-	}
-
-	/* This reserves IO space but doesn't actually enable it */
 	return pcmcia_request_io(p_dev);
 }
 
@@ -1106,6 +1082,8 @@ static void daqp_cs_config(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "daqp_cs_config\n");
 
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
 	ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL);
 	if (ret) {
 		dev_warn(&link->dev, "no configuration found\n");
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index 670a76b..76edd39 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -31,8 +31,6 @@ static int ixj_probe(struct pcmcia_device *p_dev)
 {
 	dev_dbg(&p_dev->dev, "ixj_attach()\n");
 	/* Create new ixj device */
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
 	if (!p_dev->priv) {
 		return -ENOMEM;
@@ -109,36 +107,28 @@ failed:
 	return;
 }
 
-static int ixj_config_check(struct pcmcia_device *p_dev,
-			    cistpl_cftable_entry_t *cfg,
-			    cistpl_cftable_entry_t *dflt,
-			    void *priv_data)
+static int ixj_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-		p_dev->io_lines = 3;
-		if (io->nwin == 2) {
-			p_dev->resource[1]->start = io->win[1].base;
-			p_dev->resource[1]->end = io->win[1].len;
-		}
-		if (!pcmcia_request_io(p_dev))
-			return 0;
-	}
-	return -ENODEV;
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+	p_dev->io_lines = 3;
+
+	return pcmcia_request_io(p_dev);
 }
 
 static int ixj_config(struct pcmcia_device * link)
 {
 	IXJ *j;
 	ixj_info_t *info;
-	cistpl_cftable_entry_t dflt = { 0 };
 
 	info = link->priv;
 	dev_dbg(&link->dev, "ixj_config\n");
 
-	if (pcmcia_loop_config(link, ixj_config_check, &dflt))
+	link->config_flags = CONF_AUTO_SET_IO;
+
+	if (pcmcia_loop_config(link, ixj_config_check, NULL))
 		goto failed;
 
 	if (pcmcia_enable_device(link))
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index d960629..81d7eea 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -131,28 +131,12 @@ static void sl811_cs_release(struct pcmcia_device * link)
 	platform_device_unregister(&platform_dev);
 }
 
-static int sl811_cs_config_check(struct pcmcia_device *p_dev,
-				 cistpl_cftable_entry_t *cfg,
-				 cistpl_cftable_entry_t *dflt,
-				 void *priv_data)
+static int sl811_cs_config_check(struct pcmcia_device *p_dev, void *priv_data)
 {
-	if (cfg->index == 0)
-		return -ENODEV;
+	if (p_dev->config_index == 0)
+		return -EINVAL;
 
-	/* IO window settings */
-	p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
-	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
-		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
-		p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
-
-		p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-		p_dev->resource[0]->start = io->win[0].base;
-		p_dev->resource[0]->end = io->win[0].len;
-
-		return pcmcia_request_io(p_dev);
-	}
-	pcmcia_disable_device(p_dev);
-	return -ENODEV;
+	return pcmcia_request_io(p_dev);
 }
 
 
@@ -164,7 +148,7 @@ static int sl811_cs_config(struct pcmcia_device *link)
 	dev_dbg(&link->dev, "sl811_cs_config\n");
 
 	link->config_flags |= CONF_ENABLE_IRQ |	CONF_AUTO_SET_VPP |
-		CONF_AUTO_CHECK_VCC;
+		CONF_AUTO_CHECK_VCC | CONF_AUTO_SET_IO;
 
 	if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))
 		goto failed;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 0577e5f..0b8c8d4 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -93,6 +93,7 @@ struct pcmcia_device {
 	/* device setup */
 	unsigned int		irq;
 	struct resource		*resource[PCMCIA_NUM_RESOURCES];
+	resource_size_t		card_addr;	/* for the 1st IOMEM resource */
 	unsigned int		vpp;
 
 	unsigned int		config_flags;	/* CONF_ENABLE_ flags below */
@@ -175,8 +176,6 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse);
 /* loop CIS entries for valid configuration */
 int pcmcia_loop_config(struct pcmcia_device *p_dev,
 		       int	(*conf_check)	(struct pcmcia_device *p_dev,
-						 cistpl_cftable_entry_t *cf,
-						 cistpl_cftable_entry_t *dflt,
 						 void *priv_data),
 		       void *priv_data);
 
@@ -225,16 +224,6 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev);
 #define IO_DATA_PATH_WIDTH_16	0x08
 #define IO_DATA_PATH_WIDTH_AUTO	0x10
 
-/* convert flag found in cfgtable to data path width parameter */
-static inline int pcmcia_io_cfg_data_width(unsigned int flags)
-{
-	if (!(flags & CISTPL_IO_8BIT))
-		return IO_DATA_PATH_WIDTH_16;
-	if (!(flags & CISTPL_IO_16BIT))
-		return IO_DATA_PATH_WIDTH_8;
-	return IO_DATA_PATH_WIDTH_AUTO;
-}
-
 /* IO memory */
 #define WIN_MEMORY_TYPE_CM	0x00 /* default */
 #define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
@@ -264,16 +253,17 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
 #define PRESENT_IOSIZE		0x200
 
 /* flags to be passed to pcmcia_enable_device() */
-#define CONF_ENABLE_IRQ         0x01
-#define CONF_ENABLE_SPKR        0x02
-#define CONF_ENABLE_PULSE_IRQ   0x04
-#define CONF_ENABLE_ESR         0x08
+#define CONF_ENABLE_IRQ         0x0001
+#define CONF_ENABLE_SPKR        0x0002
+#define CONF_ENABLE_PULSE_IRQ   0x0004
+#define CONF_ENABLE_ESR         0x0008
 
 /* flags used by pcmcia_loop_config() autoconfiguration */
-#define CONF_AUTO_CHECK_VCC	0x10 /* check for matching Vcc? */
-#define CONF_AUTO_SET_VPP	0x20 /* set Vpp? */
-#define CONF_AUTO_AUDIO		0x40 /* enable audio line? */
-
+#define CONF_AUTO_CHECK_VCC	0x0100 /* check for matching Vcc? */
+#define CONF_AUTO_SET_VPP	0x0200 /* set Vpp? */
+#define CONF_AUTO_AUDIO		0x0400 /* enable audio line? */
+#define CONF_AUTO_SET_IO	0x0800 /* set ->resource[0,1] */
+#define CONF_AUTO_SET_IOMEM	0x1000 /* set ->resource[2] */
 
 #endif /* __KERNEL__ */
 
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:19 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:19 +0200
Subject: [PATCH 03/22] pcmcia: move Vpp setup to struct pcmcia_device
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-3-git-send-email-linux@dominikbrodowski.net>

Some drivers prefer to explicitly set Vpp. Instead of passing the
voltage inside config_req_t, store it in struct pcmcia_device.

CC: linux-ide at vger.kernel.org
CC: netdev at vger.kernel.org
CC: linux-mtd at lists.infradead.org
CC: linux-wireless at vger.kernel.org
CC: linux-serial at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: linux-scsi at vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan at profusion.mobi> (for drivers/bluetooth)
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/ata/pata_pcmcia.c                  |    4 ++--
 drivers/bluetooth/bt3c_cs.c                |    2 +-
 drivers/bluetooth/btuart_cs.c              |    2 +-
 drivers/ide/ide-cs.c                       |    6 +++---
 drivers/isdn/hisax/sedlbauer_cs.c          |    8 ++++----
 drivers/mtd/maps/pcmciamtd.c               |    4 ++--
 drivers/net/wireless/airo_cs.c             |    8 ++++----
 drivers/net/wireless/atmel_cs.c            |    4 ++--
 drivers/net/wireless/hostap/hostap_cs.c    |   10 +++++-----
 drivers/net/wireless/orinoco/orinoco_cs.c  |    4 ++--
 drivers/net/wireless/orinoco/spectrum_cs.c |    4 ++--
 drivers/pcmcia/pcmcia_resource.c           |    3 ++-
 drivers/scsi/pcmcia/nsp_cs.c               |    8 ++++----
 drivers/serial/serial_cs.c                 |    2 +-
 drivers/usb/host/sl811_cs.c                |    8 ++++----
 include/pcmcia/cs.h                        |    1 -
 include/pcmcia/ds.h                        |    1 +
 17 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index e944aa0..12cdc9f 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -194,9 +194,9 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 7ab8f29..2c8d981 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -686,7 +686,7 @@ static int bt3c_check_config(struct pcmcia_device *p_dev,
 	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
 	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
 		p_dev->resource[0]->start = cf->io.win[0].base;
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 1c4f5e8..7ea6fa4 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -615,7 +615,7 @@ static int btuart_check_config(struct pcmcia_device *p_dev,
 	p_dev->io_lines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
 
 	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		p_dev->vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 	    (cf->io.win[0].base != 0)) {
 		p_dev->resource[0]->start = cf->io.win[0].base;
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 2a4cb9c..82690e4 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -221,9 +221,9 @@ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		pdev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		pdev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
@@ -311,7 +311,7 @@ static int ide_config(struct pcmcia_device *link)
     info->host = host;
     dev_info(&link->dev, "ide-cs: hd%c: Vpp = %d.%d\n",
 	    'a' + host->ports[0]->index * 2,
-	    link->conf.Vpp / 10, link->conf.Vpp % 10);
+	    link->vpp / 10, link->vpp % 10);
 
     kfree(stk);
     return 0;
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index a024192..ad07d61 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -191,9 +191,9 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,
 	}
 
 	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
@@ -257,8 +257,8 @@ static int __devinit sedlbauer_config(struct pcmcia_device *link)
     /* Finally, report what we've done */
     dev_info(&link->dev, "index 0x%02x:",
 	   link->conf.ConfigIndex);
-    if (link->conf.Vpp)
-	printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
+    if (link->vpp)
+	printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
     if (link->conf.Attributes & CONF_ENABLE_IRQ)
 	printk(", irq %d", link->irq);
     if (link->resource[0])
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index 31ce404..ab94c8a 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -570,9 +570,9 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 	dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
 	link->conf.Attributes = 0;
 	if(setvpp == 2) {
-		link->conf.Vpp = dev->vpp;
+		link->vpp = dev->vpp;
 	} else {
-		link->conf.Vpp = 0;
+		link->vpp = 0;
 	}
 
 	link->conf.IntType = INT_MEMORY;
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index 9a121a5..488e7b4 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -166,9 +166,9 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
 	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
@@ -244,8 +244,8 @@ static int airo_config(struct pcmcia_device *link)
 	/* Finally, report what we've done */
 	dev_info(&link->dev, "index 0x%02x: ",
 	       link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
+	if (link->vpp)
+		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	printk(", irq %d", link->irq);
 	if (link->resource[0])
 		printk(" & %pR", link->resource[0]);
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index 3b63216..479f508 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -183,9 +183,9 @@ static int atmel_config_check(struct pcmcia_device *p_dev,
 	/* Use power settings for Vcc and Vpp if present */
 	/*  Note that the CIS values need to be rescaled */
 	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
+		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
 
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index ba54d1b..3f35dd4 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -508,9 +508,9 @@ static int prism2_config_check(struct pcmcia_device *p_dev,
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		p_dev->vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+		p_dev->vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
 	p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
@@ -605,9 +605,9 @@ static int prism2_config(struct pcmcia_device *link)
 	/* Finally, report what we've done */
 	printk(KERN_INFO "%s: index 0x%02x: ",
 	       dev_info, link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp / 10,
-		       link->conf.Vpp % 10);
+	if (link->vpp)
+		printk(", Vpp %d.%d", link->vpp / 10,
+		       link->vpp % 10);
 	if (link->conf.Attributes & CONF_ENABLE_IRQ)
 		printk(", irq %d", link->irq);
 	if (link->resource[0])
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index ef46a2d..f7e3fa6 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -181,10 +181,10 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 873877e..1bbad10 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -243,10 +243,10 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
 	}
 
 	if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 	else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	/* Do we need to allocate an interrupt? */
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 14b1a95..817d00a 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -303,6 +303,7 @@ int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
 		ret = -EIO;
 		goto unlock;
 	}
+	p_dev->vpp = new_vpp;
 
 unlock:
 	mutex_unlock(&s->ops_mutex);
@@ -458,7 +459,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	}
 
 	/* Do power control.  We don't allow changes in Vcc. */
-	s->socket.Vpp = req->Vpp;
+	s->socket.Vpp = p_dev->vpp;
 	if (s->ops->set_socket(s, &s->socket)) {
 		mutex_unlock(&s->ops_mutex);
 		dev_printk(KERN_WARNING, &p_dev->dev,
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index e872e06..50574e8 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1624,10 +1624,10 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 		}
 
 		if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->conf.Vpp =
+			p_dev->vpp =
 				cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		} else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
-			p_dev->conf.Vpp =
+			p_dev->vpp =
 				dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		}
 
@@ -1749,8 +1749,8 @@ static int nsp_cs_config(struct pcmcia_device *link)
 	/* Finally, report what we've done */
 	printk(KERN_INFO "nsp_cs: index 0x%02x: ",
 	       link->conf.ConfigIndex);
-	if (link->conf.Vpp) {
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
+	if (link->vpp) {
+		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	}
 	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
 		printk(", irq %d", link->irq);
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 7d475b2..9597442 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -440,7 +440,7 @@ static int simple_config_check(struct pcmcia_device *p_dev,
 	int *try = priv_data;
 
 	if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 
 	p_dev->io_lines = ((*try & 0x1) == 0) ?
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 0e13a00..8e84752 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -152,10 +152,10 @@ static int sl811_cs_config_check(struct pcmcia_device *p_dev,
 		}
 
 	if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
 	else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM))
-		p_dev->conf.Vpp =
+		p_dev->vpp =
 			dflt->vpp1.param[CISTPL_POWER_VNOM]/10000;
 
 	/* we need an interrupt */
@@ -201,8 +201,8 @@ static int sl811_cs_config(struct pcmcia_device *link)
 
 	dev_info(&link->dev, "index 0x%02x: ",
 		link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10);
+	if (link->vpp)
+		printk(", Vpp %d.%d", link->vpp/10, link->vpp%10);
 	printk(", irq %d", link->irq);
 	printk(", io %pR", link->resource[0]);
 	printk("\n");
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index e13d0cd..ccb8e6e 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -22,7 +22,6 @@
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int	Attributes;
-    u_int	Vpp; /* both Vpp1 and Vpp2 */
     u_int	IntType;
     u_int	ConfigBase;
     u_char	Status, Pin, Copy, ExtStatus;
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 8e307b9..6137fbc 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -94,6 +94,7 @@ struct pcmcia_device {
 	/* device setup */
 	unsigned int		irq;
 	struct resource		*resource[PCMCIA_NUM_RESOURCES];
+	unsigned int		vpp;
 
 	unsigned int		io_lines; /* number of I/O lines */
 
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:22 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:22 +0200
Subject: [PATCH 06/22] pcmcia: simplify IntType
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-6-git-send-email-linux@dominikbrodowski.net>

IntType was only set to INT_MEMORY (driver pcmciamtd) or INT_MEMORY_AND_IO
(all other drivers). As this flags seems to relate to ioport access, make
it conditional to the driver having requested IO port access. There are two
drivers which do not request IO ports, but did set INT_MEMORY_AND_IO:
ray_cs and b43. For those, we consistently only set INT_MEMORY in future.

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-ide at vger.kernel.org
CC: linux-usb at vger.kernel.org
CC: laforge at gnumonks.org
CC: linux-mtd at lists.infradead.org
CC: alsa-devel at alsa-project.org
CC: linux-serial at vger.kernel.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Acked-by: Gustavo F. Padovan <padovan at profusion.mobi> (for drivers/bluetooth)
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 drivers/ata/pata_pcmcia.c                        |    1 -
 drivers/bluetooth/bluecard_cs.c                  |    1 -
 drivers/bluetooth/bt3c_cs.c                      |    1 -
 drivers/bluetooth/btuart_cs.c                    |    1 -
 drivers/bluetooth/dtl1_cs.c                      |    1 -
 drivers/char/pcmcia/cm4000_cs.c                  |    3 ---
 drivers/char/pcmcia/cm4040_cs.c                  |    3 ---
 drivers/char/pcmcia/ipwireless/main.c            |    1 -
 drivers/char/pcmcia/synclink_cs.c                |    2 --
 drivers/ide/ide-cs.c                             |    1 -
 drivers/isdn/hardware/avm/avm_cs.c               |    1 -
 drivers/isdn/hisax/avma1_cs.c                    |    1 -
 drivers/isdn/hisax/elsa_cs.c                     |    1 -
 drivers/isdn/hisax/sedlbauer_cs.c                |    1 -
 drivers/isdn/hisax/teles_cs.c                    |    1 -
 drivers/mtd/maps/pcmciamtd.c                     |    2 --
 drivers/net/pcmcia/3c574_cs.c                    |    1 -
 drivers/net/pcmcia/3c589_cs.c                    |    1 -
 drivers/net/pcmcia/axnet_cs.c                    |    1 -
 drivers/net/pcmcia/com20020_cs.c                 |    1 -
 drivers/net/pcmcia/fmvj18x_cs.c                  |    1 -
 drivers/net/pcmcia/ibmtr_cs.c                    |    1 -
 drivers/net/pcmcia/nmclan_cs.c                   |    1 -
 drivers/net/pcmcia/pcnet_cs.c                    |    1 -
 drivers/net/pcmcia/smc91c92_cs.c                 |    1 -
 drivers/net/pcmcia/xirc2ps_cs.c                  |    1 -
 drivers/net/wireless/airo_cs.c                   |    1 -
 drivers/net/wireless/atmel_cs.c                  |    1 -
 drivers/net/wireless/b43/pcmcia.c                |    1 -
 drivers/net/wireless/hostap/hostap_cs.c          |    1 -
 drivers/net/wireless/libertas/if_cs.c            |    1 -
 drivers/net/wireless/orinoco/orinoco_cs.c        |    1 -
 drivers/net/wireless/orinoco/spectrum_cs.c       |    1 -
 drivers/net/wireless/ray_cs.c                    |    1 -
 drivers/net/wireless/wl3501_cs.c                 |    1 -
 drivers/parport/parport_cs.c                     |    1 -
 drivers/pcmcia/cs_internal.h                     |    1 -
 drivers/pcmcia/pcmcia_resource.c                 |   10 +---------
 drivers/scsi/pcmcia/aha152x_stub.c               |    1 -
 drivers/scsi/pcmcia/fdomain_stub.c               |    1 -
 drivers/scsi/pcmcia/nsp_cs.c                     |    1 -
 drivers/scsi/pcmcia/qlogic_stub.c                |    1 -
 drivers/scsi/pcmcia/sym53c500_cs.c               |    1 -
 drivers/serial/serial_cs.c                       |    2 --
 drivers/staging/comedi/drivers/cb_das16_cs.c     |    1 -
 drivers/staging/comedi/drivers/das08_cs.c        |    1 -
 drivers/staging/comedi/drivers/ni_daq_700.c      |    1 -
 drivers/staging/comedi/drivers/ni_daq_dio24.c    |    1 -
 drivers/staging/comedi/drivers/ni_labpc_cs.c     |    1 -
 drivers/staging/comedi/drivers/ni_mio_cs.c       |    1 -
 drivers/staging/comedi/drivers/quatech_daqp_cs.c |    1 -
 drivers/staging/wlags49_h2/wl_cs.c               |    1 -
 drivers/telephony/ixj_pcmcia.c                   |    1 -
 drivers/usb/host/sl811_cs.c                      |    1 -
 include/pcmcia/cs.h                              |    7 -------
 sound/pcmcia/pdaudiocf/pdaudiocf.c               |    1 -
 sound/pcmcia/vx/vxpocket.c                       |    1 -
 57 files changed, 1 insertions(+), 78 deletions(-)

diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 12cdc9f..c2679c0 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -250,7 +250,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
 	pdev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	pdev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
 	pdev->conf.Attributes = CONF_ENABLE_IRQ;
-	pdev->conf.IntType = INT_MEMORY_AND_IO;
 
 	/* See if we have a manufacturer identifier. Use it to set is_kme for
 	   vendor quirks */
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index d52e90a..4cb2dfe 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -866,7 +866,6 @@ static int bluecard_probe(struct pcmcia_device *link)
 	link->priv = info;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return bluecard_config(link);
 }
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 2c8d981..fb01807 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -661,7 +661,6 @@ static int bt3c_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return bt3c_config(link);
 }
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 7ea6fa4..897c7c7 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -590,7 +590,6 @@ static int btuart_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return btuart_config(link);
 }
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index db7c8db..b4c9a2e 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -576,7 +576,6 @@ static int dtl1_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 8;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return dtl1_config(link);
 }
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index ec73d9f..d2accd6 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1767,8 +1767,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
 	if (pcmcia_loop_config(link, cm4000_config_check, NULL))
 		goto cs_release;
 
-	link->conf.IntType = 00000002;
-
 	if (pcmcia_request_configuration(link, &link->conf))
 		goto cs_release;
 
@@ -1829,7 +1827,6 @@ static int cm4000_probe(struct pcmcia_device *link)
 
 	dev->p_dev = link;
 	link->priv = dev;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
 	init_waitqueue_head(&dev->devq);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 815cde1..a32eba0 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -547,8 +547,6 @@ static int reader_config(struct pcmcia_device *link, int devno)
 	if (pcmcia_loop_config(link, cm4040_config_check, NULL))
 		goto cs_release;
 
-	link->conf.IntType = 00000002;
-
 	fail_rc = pcmcia_request_configuration(link, &link->conf);
 	if (fail_rc != 0) {
 		dev_printk(KERN_INFO, &link->dev,
@@ -599,7 +597,6 @@ static int reader_probe(struct pcmcia_device *link)
 	link->priv = dev;
 	dev->p_dev = link;
 
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	dev_table[i] = link;
 
 	init_waitqueue_head(&dev->devq);
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 8d2b86a..0f0be4d 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -173,7 +173,6 @@ static int config_ipwireless(struct ipw_dev *ipw)
 		return ret;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 9ecd6be..ba7ccf5 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -551,7 +551,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
     /* Initialize the struct pcmcia_device structure */
 
     link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     ret = mgslpc_config(link);
     if (ret)
@@ -595,7 +594,6 @@ static int mgslpc_config(struct pcmcia_device *link)
 	    goto failed;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 8;
     link->conf.Present = PRESENT_OPTION;
 
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c
index 82690e4..cf7cb49 100644
--- a/drivers/ide/ide-cs.c
+++ b/drivers/ide/ide-cs.c
@@ -100,7 +100,6 @@ static int ide_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     return ide_config(link);
 } /* ide_attach */
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c
index 09b1795..938ca41 100644
--- a/drivers/isdn/hardware/avm/avm_cs.c
+++ b/drivers/isdn/hardware/avm/avm_cs.c
@@ -80,7 +80,6 @@ static int avmcs_probe(struct pcmcia_device *p_dev)
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
     p_dev->conf.ConfigIndex = 1;
     p_dev->conf.Present = PRESENT_OPTION;
 
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c
index 94263c2..7d5ff20 100644
--- a/drivers/isdn/hisax/avma1_cs.c
+++ b/drivers/isdn/hisax/avma1_cs.c
@@ -85,7 +85,6 @@ static int __devinit avma1cs_probe(struct pcmcia_device *p_dev)
 
     /* General socket configuration */
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
     p_dev->conf.ConfigIndex = 1;
     p_dev->conf.Present = PRESENT_OPTION;
 
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c
index b3c08aa..df360c8 100644
--- a/drivers/isdn/hisax/elsa_cs.c
+++ b/drivers/isdn/hisax/elsa_cs.c
@@ -130,7 +130,6 @@ static int __devinit elsa_cs_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     return elsa_cs_config(link);
 } /* elsa_cs_attach */
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index 40001ad..169061f 100644
--- a/drivers/isdn/hisax/sedlbauer_cs.c
+++ b/drivers/isdn/hisax/sedlbauer_cs.c
@@ -133,7 +133,6 @@ static int __devinit sedlbauer_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 
     link->conf.Attributes = 0;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     return sedlbauer_config(link);
 } /* sedlbauer_attach */
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c
index 7296102..46e72a1 100644
--- a/drivers/isdn/hisax/teles_cs.c
+++ b/drivers/isdn/hisax/teles_cs.c
@@ -110,7 +110,6 @@ static int __devinit teles_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     return teles_cs_config(link);
 } /* teles_attach */
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index ab94c8a..663b48b 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -575,7 +575,6 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 		link->vpp = 0;
 	}
 
-	link->conf.IntType = INT_MEMORY;
 	link->conf.ConfigIndex = 0;
 	DEBUG(2, "Setting Configuration");
 	ret = pcmcia_request_configuration(link, &link->conf);
@@ -720,7 +719,6 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
 	link->priv = dev;
 
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY;
 
 	return pcmciamtd_config(link);
 }
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index c683f77..41ecb27 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -281,7 +281,6 @@ static int tc574_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 32;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
 
 	dev->netdev_ops = &el3_netdev_ops;
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index 61f9cf2..6888672 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -217,7 +217,6 @@ static int tc589_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
 
     dev->netdev_ops = &el3_netdev_ops;
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 8734ed8..4d4928a 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -167,7 +167,6 @@ static int axnet_probe(struct pcmcia_device *link)
     info->p_dev = link;
     link->priv = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     dev->netdev_ops = &axnet_netdev_ops;
 
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 3c400cf..a58eafe 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -161,7 +161,6 @@ static int com20020_probe(struct pcmcia_device *p_dev)
     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     p_dev->resource[0]->end = 16;
     p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-    p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
     info->dev = dev;
     p_dev->priv = info;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index dfd3284..caf2b2e 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -253,7 +253,6 @@ static int fmvj18x_probe(struct pcmcia_device *link)
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index dbdea7f..1327f08 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -153,7 +153,6 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[0]->end = 4;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
     info->dev = dev;
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 68f2dee..90d1728 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -461,7 +461,6 @@ static int nmclan_probe(struct pcmcia_device *link)
     link->resource[0]->end = 32;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
 
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index f3d7a14..6913576 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -261,7 +261,6 @@ static int pcnet_probe(struct pcmcia_device *link)
     link->priv = dev;
 
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     dev->netdev_ops = &pcnet_netdev_ops;
 
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 2031a27..2c2a878 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -327,7 +327,6 @@ static int smc91c92_probe(struct pcmcia_device *link)
     link->resource[0]->end = 16;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     /* The SMC91c92-specific entries in the device structure. */
     dev->netdev_ops = &smc_netdev_ops;
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 59398a6..1776f49 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -530,7 +530,6 @@ xirc2ps_probe(struct pcmcia_device *link)
 
     /* General socket configuration */
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
 
     /* Fill in card specific entries */
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c
index ab60f10..ccb2fdd 100644
--- a/drivers/net/wireless/airo_cs.c
+++ b/drivers/net/wireless/airo_cs.c
@@ -104,7 +104,6 @@ static int airo_probe(struct pcmcia_device *p_dev)
 	  device, and can be hard-wired here.
 	*/
 	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index d6d585c..8b75158 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -114,7 +114,6 @@ static int atmel_probe(struct pcmcia_device *p_dev)
 	  device, and can be hard-wired here.
 	*/
 	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	/* Allocate space for private device-specific data */
 	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index 618d9b5..138b26f 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -73,7 +73,6 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	err = -ENODEV;
 
 	dev->conf.Attributes = CONF_ENABLE_IRQ;
-	dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 3fa285b..0fe6f82 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -437,7 +437,6 @@ static int hostap_cs_probe(struct pcmcia_device *p_dev)
 	int ret;
 
 	PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info);
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	ret = prism2_config(p_dev);
 	if (ret) {
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index 9c29839..814b7fa 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -836,7 +836,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	p_dev->priv = card;
 
 	p_dev->conf.Attributes = 0;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 
 	if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) {
 		lbs_pr_err("error in pcmcia_loop_config\n");
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index f7e3fa6..1147d6b 100644
--- a/drivers/net/wireless/orinoco/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -123,7 +123,6 @@ orinoco_cs_probe(struct pcmcia_device *link)
 	 * number, sizes, and attributes of IO windows) are fixed by
 	 * the nature of the device, and can be hard-wired here. */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return orinoco_cs_config(link);
 }				/* orinoco_cs_attach */
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 1bbad10..20b08ab 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -185,7 +185,6 @@ spectrum_cs_probe(struct pcmcia_device *link)
 	 * number, sizes, and attributes of IO windows) are fixed by
 	 * the nature of the device, and can be hard-wired here. */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return spectrum_cs_config(link);
 }				/* spectrum_cs_attach */
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index ab34cb8..30cfd88 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -319,7 +319,6 @@ static int ray_probe(struct pcmcia_device *p_dev)
 
 	/* General socket configuration */
 	p_dev->conf.Attributes = CONF_ENABLE_IRQ;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 	p_dev->conf.ConfigIndex = 1;
 
 	p_dev->priv = dev;
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index a1cc2d4..92a9ad5 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1889,7 +1889,6 @@ static int wl3501_probe(struct pcmcia_device *p_dev)
 
 	/* General socket configuration */
 	p_dev->conf.Attributes	= CONF_ENABLE_IRQ;
-	p_dev->conf.IntType	= INT_MEMORY_AND_IO;
 	p_dev->conf.ConfigIndex	= 1;
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c
index 23e50f4..afd946e 100644
--- a/drivers/parport/parport_cs.c
+++ b/drivers/parport/parport_cs.c
@@ -104,7 +104,6 @@ static int parport_probe(struct pcmcia_device *link)
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
     link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
 
     return parport_config(link);
 } /* parport_attach */
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7ef464d..a0c5adb 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -34,7 +34,6 @@ typedef struct config_t {
 	struct kref	ref;
 	unsigned int	state;
 	unsigned int	Attributes;
-	unsigned int	IntType;
 	unsigned int	ConfigBase;
 	unsigned char	Option;
 	unsigned int	CardValues;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 8834bb4..6210e1c 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -447,11 +447,6 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	if (!(s->state & SOCKET_PRESENT))
 		return -ENODEV;
 
-	if (req->IntType & INT_CARDBUS) {
-		dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n");
-		return -EINVAL;
-	}
-
 	mutex_lock(&s->ops_mutex);
 	c = p_dev->function_config;
 	if (c->state & CONFIG_LOCKED) {
@@ -470,12 +465,9 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 	}
 
 	/* Pick memory or I/O card, DMA mode, interrupt */
-	c->IntType = req->IntType;
 	c->Attributes = req->Attributes;
-	if (req->IntType & INT_MEMORY_AND_IO)
+	if (p_dev->_io)
 		s->socket.flags |= SS_IOCARD;
-	if (req->IntType & INT_ZOOMED_VIDEO)
-		s->socket.flags |= SS_ZVCARD | SS_IOCARD;
 	if (req->Attributes & CONF_ENABLE_DMA)
 		s->socket.flags |= SS_DMA_MODE;
 	if (req->Attributes & CONF_ENABLE_SPKR) {
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c
index 61f49bd..3c0046e 100644
--- a/drivers/scsi/pcmcia/aha152x_stub.c
+++ b/drivers/scsi/pcmcia/aha152x_stub.c
@@ -103,7 +103,6 @@ static int aha152x_probe(struct pcmcia_device *link)
     link->resource[0]->end = 0x20;
     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
     link->conf.Attributes = CONF_ENABLE_IRQ;
-    link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.Present = PRESENT_OPTION;
 
     return aha152x_config_cs(link);
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
index 13dbe5c..8ff7603 100644
--- a/drivers/scsi/pcmcia/fdomain_stub.c
+++ b/drivers/scsi/pcmcia/fdomain_stub.c
@@ -86,7 +86,6 @@ static int fdomain_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 0x10;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
 	return fdomain_config(link);
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index b90cade..c0cf2df 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1563,7 +1563,6 @@ static int nsp_cs_probe(struct pcmcia_device *link)
 
 	/* General socket configuration */
 	link->conf.Attributes	 = CONF_ENABLE_IRQ;
-	link->conf.IntType	 = INT_MEMORY_AND_IO;
 
 	ret = nsp_cs_config(link);
 
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index eb775f1..77f46a2 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -159,7 +159,6 @@ static int qlogic_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 16;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.Present = PRESENT_OPTION;
 
 	return qlogic_config(link);
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 321e390..9aaf974 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -862,7 +862,6 @@ SYM53C500_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 16;
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return SYM53C500_config(link);
 } /* SYM53C500_attach */
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 0460c08..38baede 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -337,8 +337,6 @@ static int serial_probe(struct pcmcia_device *link)
 	if (do_sound)
 		link->conf.Attributes |= CONF_ENABLE_SPKR;
 
-	link->conf.IntType = INT_MEMORY_AND_IO;
-
 	return serial_config(link);
 }
 
diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c
index f8ede11..11271b6 100644
--- a/drivers/staging/comedi/drivers/cb_das16_cs.c
+++ b/drivers/staging/comedi/drivers/cb_das16_cs.c
@@ -694,7 +694,6 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)
 
 	/* Initialize the pcmcia_device structure */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 48d9fb1..319aad4 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -170,7 +170,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)
 	   device, and can be hard-wired here.
 	 */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index 8cf56cb..d269bbd 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -499,7 +499,6 @@ static int dio700_cs_attach(struct pcmcia_device *link)
 	   device, and can be hard-wired here.
 	 */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	pcmcia_cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index ba69343..fcaa829 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -251,7 +251,6 @@ static int dio24_cs_attach(struct pcmcia_device *link)
 	   device, and can be hard-wired here.
 	 */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	pcmcia_cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c
index 5d5f11f..a936c11 100644
--- a/drivers/staging/comedi/drivers/ni_labpc_cs.c
+++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c
@@ -227,7 +227,6 @@ static int labpc_cs_attach(struct pcmcia_device *link)
 	   device, and can be hard-wired here.
 	 */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	pcmcia_cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c
index 1f24263..be7e021 100644
--- a/drivers/staging/comedi/drivers/ni_mio_cs.c
+++ b/drivers/staging/comedi/drivers/ni_mio_cs.c
@@ -266,7 +266,6 @@ static int cs_attach(struct pcmcia_device *link)
 	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
 	link->resource[0]->end = 16;
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	cur_dev = link;
 
diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
index bf489d7..cd818fb 100644
--- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c
+++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c
@@ -1039,7 +1039,6 @@ static int daqp_cs_attach(struct pcmcia_device *link)
 	   device, and can be hard-wired here.
 	 */
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	daqp_cs_config(link);
 
diff --git a/drivers/staging/wlags49_h2/wl_cs.c b/drivers/staging/wlags49_h2/wl_cs.c
index 19c3354..b2efff6 100644
--- a/drivers/staging/wlags49_h2/wl_cs.c
+++ b/drivers/staging/wlags49_h2/wl_cs.c
@@ -148,7 +148,6 @@ static int wl_adapter_attach(struct pcmcia_device *link)
 	link->resource[0]->end  = HCF_NUM_IO_PORTS;
 	link->resource[0]->flags= IO_DATA_PATH_WIDTH_16;
 	link->conf.Attributes   = CONF_ENABLE_IRQ;
-	link->conf.IntType      = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex  = 5;
 	link->conf.Present      = PRESENT_OPTION;
 
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c
index a1900e5..5ccc6d0 100644
--- a/drivers/telephony/ixj_pcmcia.c
+++ b/drivers/telephony/ixj_pcmcia.c
@@ -34,7 +34,6 @@ static int ixj_probe(struct pcmcia_device *p_dev)
 	/* Create new ixj device */
 	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
 	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-	p_dev->conf.IntType = INT_MEMORY_AND_IO;
 	p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
 	if (!p_dev->priv) {
 		return -ENOMEM;
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 8e84752..78bad51 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -228,7 +228,6 @@ static int sl811_cs_probe(struct pcmcia_device *link)
 	link->priv = local;
 
 	link->conf.Attributes = 0;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 
 	return sl811_cs_config(link);
 }
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 29d693f..674edbc 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -22,7 +22,6 @@
 /* For RequestConfiguration */
 typedef struct config_req_t {
     u_int	Attributes;
-    u_int	IntType;
     u_int	ConfigBase;
     u_char	ConfigIndex;
     u_int	Present;
@@ -36,12 +35,6 @@ typedef struct config_req_t {
 #define CONF_ENABLE_ESR		0x10
 #define CONF_VALID_CLIENT	0x100
 
-/* IntType field */
-#define INT_MEMORY		0x01
-#define INT_MEMORY_AND_IO	0x02
-#define INT_CARDBUS		0x04
-#define INT_ZOOMED_VIDEO	0x08
-
 /* Configuration registers present */
 #define PRESENT_OPTION		0x001
 #define PRESENT_STATUS		0x002
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 7ab9174..2e1282d 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -143,7 +143,6 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
 	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index a6edfc3..a48b3ee 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -163,7 +163,6 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 	link->resource[0]->end = 16;
 
 	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
 
-- 
1.7.0.4



From linux at dominikbrodowski.net  Thu Oct 21 11:35:17 2010
From: linux at dominikbrodowski.net (Dominik Brodowski)
Date: Thu, 21 Oct 2010 17:35:17 +0200
Subject: [PATCH 01/22] pcmcia: do not use win_req_t when calling
	pcmcia_request_window()
In-Reply-To: <20101021153450.GA12405@comet.dominikbrodowski.net>
References: <20101021153450.GA12405@comet.dominikbrodowski.net>
Message-ID: <1287675338-12588-1-git-send-email-linux@dominikbrodowski.net>

Instead of win_req_t, drivers are now requested to fill out
struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four iomem
ranges. After a call to pcmcia_request_window(), the windows found there
are reserved and may be used until pcmcia_release_window() is called.

CC: netdev at vger.kernel.org
CC: linux-wireless at vger.kernel.org
CC: linux-mtd at lists.infradead.org
CC: Jiri Kosina <jkosina at suse.cz>
CC: linux-scsi at vger.kernel.org
Tested-by: Wolfram Sang <w.sang at pengutronix.de>
Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>
---
 Documentation/pcmcia/driver-changes.txt |    7 +++
 drivers/char/pcmcia/ipwireless/main.c   |   87 +++++++++++++------------------
 drivers/char/pcmcia/ipwireless/main.h   |    4 --
 drivers/mtd/maps/pcmciamtd.c            |   53 ++++++++++---------
 drivers/net/pcmcia/fmvj18x_cs.c         |   29 ++++------
 drivers/net/pcmcia/ibmtr_cs.c           |   42 +++++++--------
 drivers/net/pcmcia/pcnet_cs.c           |   44 ++++++++--------
 drivers/net/pcmcia/smc91c92_cs.c        |   15 +++---
 drivers/net/pcmcia/xirc2ps_cs.c         |   16 +++---
 drivers/net/wireless/b43/pcmcia.c       |   14 ++---
 drivers/net/wireless/ray_cs.c           |   44 +++++++--------
 drivers/net/wireless/ray_cs.h           |    2 -
 drivers/pcmcia/pcmcia_resource.c        |   60 ++++++++++++----------
 drivers/scsi/pcmcia/nsp_cs.c            |   49 +++++++-----------
 include/pcmcia/cs.h                     |   24 ---------
 include/pcmcia/ds.h                     |   28 +++++++---
 16 files changed, 241 insertions(+), 277 deletions(-)

diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
index 26c0f9c..86e0f49 100644
--- a/Documentation/pcmcia/driver-changes.txt
+++ b/Documentation/pcmcia/driver-changes.txt
@@ -1,4 +1,11 @@
 This file details changes in 2.6 which affect PCMCIA card driver authors:
+* pcmcia_request_window changes (as of 2.6.36)
+   Instead of win_req_t, drivers are now requested to fill out
+   struct pcmcia_device *p_dev->resource[2,3,4,5] for up to four ioport
+   ranges. After a call to pcmcia_request_window(), the regions found there
+   are reserved and may be used immediately -- until pcmcia_release_window()
+   is called.
+
 * pcmcia_request_io changes (as of 2.6.36)
    Instead of io_req_t, drivers are now requested to fill out
    struct pcmcia_device *p_dev->resource[0,1] for up to two ioport
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 67bdb05..8d2b86a 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -105,62 +105,54 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
 	if (cfg->mem.nwin == 0)
 		return 0;
 
-	ipw->request_common_memory.Attributes =
+	p_dev->resource[2]->flags |=
 		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
-	ipw->request_common_memory.Size = cfg->mem.win[0].len;
-	if (ipw->request_common_memory.Size < 0x1000)
-		ipw->request_common_memory.Size = 0x1000;
-	ipw->request_common_memory.AccessSpeed = 0;
-
-	ret = pcmcia_request_window(p_dev, &ipw->request_common_memory,
-				&ipw->handle_common_memory);
+	p_dev->resource[2]->start = cfg->mem.win[0].host_addr;
+	p_dev->resource[2]->end = cfg->mem.win[0].len;
+	if (p_dev->resource[2]->end < 0x1000)
+		p_dev->resource[2]->end = 0x1000;
 
+	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
 	if (ret != 0)
 		goto exit1;
 
-	ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2],
 				cfg->mem.win[0].card_addr);
-
 	if (ret != 0)
 		goto exit2;
 
 	ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
 
-	ipw->common_memory = ioremap(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
-	request_mem_region(ipw->request_common_memory.Base,
-			ipw->request_common_memory.Size,
+	ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]));
+	request_mem_region(p_dev->resource[2]->start,
+			resource_size(p_dev->resource[2]),
 			IPWIRELESS_PCCARD_NAME);
 
-	ipw->request_attr_memory.Attributes =
-		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
-	ipw->request_attr_memory.Base = 0;
-	ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */
-	ipw->request_attr_memory.AccessSpeed = 0;
-
-	ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory,
-				&ipw->handle_attr_memory);
-
+	p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
+					WIN_ENABLE;
+	p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
+	ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
 	if (ret != 0)
 		goto exit2;
 
-	ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
 	if (ret != 0)
 		goto exit3;
 
-	ipw->attr_memory = ioremap(ipw->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
-	request_mem_region(ipw->request_attr_memory.Base,
-			ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME);
+	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+				resource_size(p_dev->resource[3]));
+	request_mem_region(p_dev->resource[3]->start,
+			resource_size(p_dev->resource[3]),
+			IPWIRELESS_PCCARD_NAME);
 
 	return 0;
 
 exit3:
 exit2:
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		release_mem_region(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]));
 		iounmap(ipw->common_memory);
 	}
 exit1:
@@ -201,13 +193,9 @@ static int config_ipwireless(struct ipw_dev *ipw)
 			(unsigned int) link->irq);
 	if (ipw->attr_memory && ipw->common_memory)
 		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n",
-			ipw->request_attr_memory.Base,
-			ipw->request_attr_memory.Base
-			+ ipw->request_attr_memory.Size - 1,
-			ipw->request_common_memory.Base,
-			ipw->request_common_memory.Base
-			+ ipw->request_common_memory.Size - 1);
+			": attr memory %pR, common memory %pR\n",
+			link->resource[3],
+			link->resource[2]);
 
 	ipw->network = ipwireless_network_create(ipw->hardware);
 	if (!ipw->network)
@@ -231,17 +219,16 @@ static int config_ipwireless(struct ipw_dev *ipw)
 	return 0;
 
 exit:
-	if (ipw->attr_memory) {
-		release_mem_region(ipw->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
-		iounmap(ipw->attr_memory);
-
-	}
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		release_mem_region(link->resource[2]->start,
+				resource_size(link->resource[2]));
 		iounmap(ipw->common_memory);
 	}
+	if (ipw->attr_memory) {
+		release_mem_region(link->resource[3]->start,
+				resource_size(link->resource[3]));
+		iounmap(ipw->attr_memory);
+	}
 	pcmcia_disable_device(link);
 	return -1;
 }
@@ -249,13 +236,13 @@ exit:
 static void release_ipwireless(struct ipw_dev *ipw)
 {
 	if (ipw->common_memory) {
-		release_mem_region(ipw->request_common_memory.Base,
-				ipw->request_common_memory.Size);
+		release_mem_region(ipw->link->resource[2]->start,
+				resource_size(ipw->link->resource[2]));
 		iounmap(ipw->common_memory);
 	}
 	if (ipw->attr_memory) {
-		release_mem_region(ipw->request_attr_memory.Base,
-				ipw->request_attr_memory.Size);
+		release_mem_region(ipw->link->resource[3]->start,
+				resource_size(ipw->link->resource[3]));
 		iounmap(ipw->attr_memory);
 	}
 	pcmcia_disable_device(ipw->link);
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index c207be8..9040219 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -45,13 +45,9 @@ struct ipw_dev {
 	struct pcmcia_device *link;
 	int is_v2_card;
 
-	window_handle_t handle_attr_memory;
 	void __iomem *attr_memory;
-	win_req_t request_attr_memory;
 
-	window_handle_t handle_common_memory;
 	void __iomem *common_memory;
-	win_req_t request_common_memory;
 
 	/* Reference to attribute memory, containing CIS data */
 	void *attribute_memory;
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index e9ca5ba..fb3c538 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)")
 static caddr_t remap_window(struct map_info *map, unsigned long to)
 {
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
-	window_handle_t win = (window_handle_t)map->map_priv_2;
+	struct resource *win = (struct resource *) map->map_priv_2;
 	unsigned int offset;
 	int ret;
 
@@ -339,7 +339,7 @@ static void pcmciamtd_release(struct pcmcia_device *link)
 
 	DEBUG(3, "link = 0x%p", link);
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		if(dev->win_base) {
 			iounmap(dev->win_base);
 			dev->win_base = NULL;
@@ -491,9 +491,8 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 {
 	struct pcmciamtd_dev *dev = link->priv;
 	struct mtd_info *mtd = NULL;
-	win_req_t req;
 	int ret;
-	int i;
+	int i, j = 0;
 	static char *probes[] = { "jedec_probe", "cfi_probe" };
 	int new_name = 0;
 
@@ -520,28 +519,34 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 	 * smaller windows until we succeed
 	 */
 
-	req.Attributes =  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-	req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
-	req.Base = 0;
-	req.AccessSpeed = mem_speed;
-	link->win = (window_handle_t)link;
-	req.Size = (force_size) ? force_size << 20 : MAX_PCMCIA_ADDR;
+	link->resource[2]->flags |=  WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+	link->resource[2]->flags |= (dev->pcmcia_map.bankwidth == 1) ?
+					WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16;
+	link->resource[2]->start = 0;
+	link->resource[2]->end = (force_size) ? force_size << 20 :
+					MAX_PCMCIA_ADDR;
 	dev->win_size = 0;
 
 	do {
 		int ret;
-		DEBUG(2, "requesting window with size = %dKiB memspeed = %d",
-		      req.Size >> 10, req.AccessSpeed);
-		ret = pcmcia_request_window(link, &req, &link->win);
+		DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
+			(unsigned long) resource_size(link->resource[2]) >> 10,
+			mem_speed);
+		ret = pcmcia_request_window(link, link->resource[2], mem_speed);
 		DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
 		if(ret) {
-			req.Size >>= 1;
+			j++;
+			link->resource[2]->start = 0;
+			link->resource[2]->end = (force_size) ?
+					force_size << 20 : MAX_PCMCIA_ADDR;
+			link->resource[2]->end >>= j;
 		} else {
-			DEBUG(2, "Got window of size %dKiB", req.Size >> 10);
-			dev->win_size = req.Size;
+			DEBUG(2, "Got window of size %luKiB", (unsigned long)
+				resource_size(link->resource[2]) >> 10);
+			dev->win_size = resource_size(link->resource[2]);
 			break;
 		}
-	} while(req.Size >= 0x1000);
+	} while (link->resource[2]->end >= 0x1000);
 
 	DEBUG(2, "dev->win_size = %d", dev->win_size);
 
@@ -553,20 +558,20 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 	DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
 
 	/* Get write protect status */
-	DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win);
-	dev->win_base = ioremap(req.Base, req.Size);
+	dev->win_base = ioremap(link->resource[2]->start,
+				resource_size(link->resource[2]));
 	if(!dev->win_base) {
-		dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n",
-			req.Base, req.Size);
+		dev_err(&dev->p_dev->dev, "ioremap(%pR) failed\n",
+			link->resource[2]);
 		pcmciamtd_release(link);
 		return -ENODEV;
 	}
-	DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x",
-	      dev, req.Base, dev->win_base, req.Size);
+	DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
+	      dev, link->resource[2], dev->win_base);
 
 	dev->offset = 0;
 	dev->pcmcia_map.map_priv_1 = (unsigned long)dev;
-	dev->pcmcia_map.map_priv_2 = (unsigned long)link->win;
+	dev->pcmcia_map.map_priv_2 = (unsigned long)link->resource[2];
 
 	dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp;
 	link->conf.Attributes = 0;
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 98fffb0..dfd3284 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -544,20 +544,18 @@ failed:
 
 static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 {
-    win_req_t req;
     u_char __iomem *base;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	return -1;
 
-    base = ioremap(req.Base, req.Size);
-    pcmcia_map_mem_page(link, link->win, 0);
+    base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+    pcmcia_map_mem_page(link, link->resource[2], 0);
 
     /*
      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
@@ -582,7 +580,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
     }
 
     iounmap(base);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i != 0x200) ? 0 : -1;
 
 } /* fmvj18x_get_hwinfo */
@@ -590,27 +588,26 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 
 static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
-    win_req_t req;
     int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
     local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[3]->start = link->resource[3]->end = 0;
+    i = pcmcia_request_window(link, link->resource[3], 0);
     if (i != 0)
 	return -1;
 
-    lp->base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(link->resource[3]->start,
+		       resource_size(link->resource[3]));
     if (lp->base == NULL) {
 	printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
 	return -1;
     }
 
-    i = pcmcia_map_mem_page(link, link->win, 0);
+    i = pcmcia_map_mem_page(link, link->resource[3], 0);
     if (i != 0) {
 	iounmap(lp->base);
 	lp->base = NULL;
@@ -638,7 +635,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
     u_char __iomem *tmp;
-    int j;
 
     dev_dbg(&link->dev, "fmvj18x_release\n");
 
@@ -646,7 +642,6 @@ static void fmvj18x_release(struct pcmcia_device *link)
 	tmp = lp->base;
 	lp->base = NULL;    /* set NULL before iounmap */
 	iounmap(tmp);
-	j = pcmcia_release_window(link, link->win);
     }
 
     pcmcia_disable_device(link);
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index b0d06a3..dbdea7f 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -102,9 +102,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 typedef struct ibmtr_dev_t {
 	struct pcmcia_device	*p_dev;
-    struct net_device	*dev;
-    window_handle_t     sram_win_handle;
-    struct tok_info	*ti;
+	struct net_device	*dev;
+	struct tok_info		*ti;
 } ibmtr_dev_t;
 
 static void netdev_get_drvinfo(struct net_device *dev,
@@ -210,7 +209,6 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     ibmtr_dev_t *info = link->priv;
     struct net_device *dev = info->dev;
     struct tok_info *ti = netdev_priv(dev);
-    win_req_t req;
     int i, ret;
 
     dev_dbg(&link->dev, "ibmtr_config\n");
@@ -240,37 +238,37 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
 
     /* Allocate the MMIO memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; 
-    req.Size = 0x2000;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[2]->flags |= WIN_USE_WAIT;
+    link->resource[2]->start = 0;
+    link->resource[2]->end = 0x2000;
+    ret = pcmcia_request_window(link, link->resource[2], 250);
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_map_mem_page(link, link->win, mmiobase);
+    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase);
     if (ret)
 	    goto failed;
-    ti->mmio = ioremap(req.Base, req.Size);
+    ti->mmio = ioremap(link->resource[2]->start,
+		    resource_size(link->resource[2]));
 
     /* Allocate the SRAM memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0;
-    req.Size = sramsize * 1024;
-    req.AccessSpeed = 250;
-    ret = pcmcia_request_window(link, &req, &info->sram_win_handle);
+    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0;
+    link->resource[3]->end = sramsize * 1024;
+    ret = pcmcia_request_window(link, link->resource[3], 250);
     if (ret)
 	    goto failed;
 
-    ret = pcmcia_map_mem_page(link, info->sram_win_handle, srambase);
+    ret = pcmcia_map_mem_page(link, link->resource[3], srambase);
     if (ret)
 	    goto failed;
 
     ti->sram_base = srambase >> 12;
-    ti->sram_virt = ioremap(req.Base, req.Size);
-    ti->sram_phys = req.Base;
+    ti->sram_virt = ioremap(link->resource[3]->start,
+		    resource_size(link->resource[3]));
+    ti->sram_phys = link->resource[3]->start;
 
     ret = pcmcia_request_configuration(link, &link->conf);
     if (ret)
@@ -316,7 +314,7 @@ static void ibmtr_release(struct pcmcia_device *link)
 
 	dev_dbg(&link->dev, "ibmtr_release\n");
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct tok_info *ti = netdev_priv(dev);
 		iounmap(ti->mmio);
 	}
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index f9b509a..aa6ee6b 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -300,22 +300,22 @@ static void pcnet_detach(struct pcmcia_device *link)
 static hw_info_t *get_hwinfo(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    win_req_t req;
     u_char __iomem *base, *virt;
     int i, j;
 
     /* Allocate a small memory window */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = 0; req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	return NULL;
 
-    virt = ioremap(req.Base, req.Size);
+    virt = ioremap(link->resource[2]->start,
+	    resource_size(link->resource[2]));
     for (i = 0; i < NR_INFO; i++) {
-	pcmcia_map_mem_page(link, link->win, hw_info[i].offset & ~(req.Size-1));
-	base = &virt[hw_info[i].offset & (req.Size-1)];
+	pcmcia_map_mem_page(link, link->resource[2],
+		hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+	base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
 	if ((readb(base+0) == hw_info[i].a0) &&
 	    (readb(base+2) == hw_info[i].a1) &&
 	    (readb(base+4) == hw_info[i].a2)) {
@@ -326,7 +326,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
     }
 
     iounmap(virt);
-    j = pcmcia_release_window(link, link->win);
+    j = pcmcia_release_window(link, link->resource[2]);
     return (i < NR_INFO) ? hw_info+i : NULL;
 } /* get_hwinfo */
 
@@ -1486,7 +1486,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
 {
     struct net_device *dev = link->priv;
     pcnet_dev_t *info = PRIV(dev);
-    win_req_t req;
     int i, window_size, offset, ret;
 
     window_size = (stop_pg - start_pg) << 8;
@@ -1497,22 +1496,22 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     window_size = roundup_pow_of_two(window_size);
 
     /* Allocate a memory window */
-    req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    req.Attributes |= WIN_USE_WAIT;
-    req.Base = 0; req.Size = window_size;
-    req.AccessSpeed = mem_speed;
-    ret = pcmcia_request_window(link, &req, &link->win);
+    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0; link->resource[3]->end = window_size;
+    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
     if (ret)
 	    goto failed;
 
     offset = (start_pg << 8) + cm_offset;
     offset -= offset % window_size;
-    ret = pcmcia_map_mem_page(link, link->win, offset);
+    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
     if (ret)
 	    goto failed;
 
     /* Try scribbling on the buffer */
-    info->base = ioremap(req.Base, window_size);
+    info->base = ioremap(link->resource[3]->start,
+			resource_size(link->resource[3]));
     for (i = 0; i < (TX_PAGES<<8); i += 2)
 	__raw_writew((i>>1), info->base+offset+i);
     udelay(100);
@@ -1521,19 +1520,20 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
     pcnet_reset_8390(dev);
     if (i != (TX_PAGES<<8)) {
 	iounmap(info->base);
-	pcmcia_release_window(link, link->win);
-	info->base = NULL; link->win = 0;
+	pcmcia_release_window(link, link->resource[3]);
+	info->base = NULL;
 	goto failed;
     }
 
     ei_status.mem = info->base + offset;
-    ei_status.priv = req.Size;
+    ei_status.priv = resource_size(link->resource[3]);
     dev->mem_start = (u_long)ei_status.mem;
-    dev->mem_end = dev->mem_start + req.Size;
+    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
 
     ei_status.tx_start_page = start_pg;
     ei_status.rx_start_page = start_pg + TX_PAGES;
-    ei_status.stop_page = start_pg + ((req.Size - offset) >> 8);
+    ei_status.stop_page = start_pg + (
+	    (resource_size(link->resource[3]) - offset) >> 8);
 
     /* set up block i/o functions */
     ei_status.get_8390_hdr = &shmem_get_8390_hdr;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 377367d..acc6807 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -442,7 +442,6 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    win_req_t req;
     unsigned int offset;
     int i;
 
@@ -459,16 +458,16 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     dev->base_addr = link->resource[0]->start;
 
     /* Allocate a memory window, for accessing the ISR */
-    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    req.Base = req.Size = 0;
-    req.AccessSpeed = 0;
-    i = pcmcia_request_window(link, &req, &link->win);
+    link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
     if (i != 0)
 	    return -ENODEV;
 
-    smc->base = ioremap(req.Base, req.Size);
+    smc->base = ioremap(link->resource[2]->start,
+		    resource_size(link->resource[2]));
     offset = (smc->manfid == MANFID_MOTOROLA) ? link->conf.ConfigBase : 0;
-    i = pcmcia_map_mem_page(link, link->win, offset);
+    i = pcmcia_map_mem_page(link, link->resource[2], offset);
     if ((i == 0) &&
 	(smc->manfid == MANFID_MEGAHERTZ) &&
 	(smc->cardid == PRODID_MEGAHERTZ_EM3288))
@@ -999,7 +998,7 @@ config_failed:
 static void smc91c92_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "smc91c92_release\n");
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct net_device *dev = link->priv;
 		struct smc_private *smc = netdev_priv(dev);
 		iounmap(smc->base);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index f581952..4308bda 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -869,8 +869,6 @@ xirc2ps_config(struct pcmcia_device * link)
 	goto config_error;
 
     if (local->dingo) {
-	win_req_t req;
-
 	/* Reset the modem's BAR to the correct value
 	 * This is necessary because in the RequestConfiguration call,
 	 * the base address of the ethernet port (BasePort1) is written
@@ -890,14 +888,14 @@ xirc2ps_config(struct pcmcia_device * link)
 	 * is at 0x0800. So we allocate a window into the attribute
 	 * memory and write direct to the CIS registers
 	 */
-	req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-	req.Base = req.Size = 0;
-	req.AccessSpeed = 0;
-	if ((err = pcmcia_request_window(link, &req, &link->win)))
+	link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM |
+					WIN_ENABLE;
+	link->resource[2]->start = link->resource[2]->end = 0;
+	if ((err = pcmcia_request_window(link, link->resource[2], 0)))
 	    goto config_error;
 
-	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;
-	if ((err = pcmcia_map_mem_page(link, link->win, 0)))
+	local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800;
+	if ((err = pcmcia_map_mem_page(link, link->resource[2], 0)))
 	    goto config_error;
 
 	/* Setup the CCRs; there are no infos in the CIS about the Ethernet
@@ -988,7 +986,7 @@ xirc2ps_release(struct pcmcia_device *link)
 {
 	dev_dbg(&link->dev, "release\n");
 
-	if (link->win) {
+	if (link->resource[2]->end) {
 		struct net_device *dev = link->priv;
 		local_info_t *local = netdev_priv(dev);
 		if (local->dingo)
diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c
index dfbc41d..618d9b5 100644
--- a/drivers/net/wireless/b43/pcmcia.c
+++ b/drivers/net/wireless/b43/pcmcia.c
@@ -63,7 +63,6 @@ static int b43_pcmcia_resume(struct pcmcia_device *dev)
 static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 {
 	struct ssb_bus *ssb;
-	win_req_t win;
 	int err = -ENOMEM;
 	int res = 0;
 
@@ -76,16 +75,15 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	dev->conf.Attributes = CONF_ENABLE_IRQ;
 	dev->conf.IntType = INT_MEMORY_AND_IO;
 
-	win.Attributes =  WIN_ENABLE | WIN_DATA_WIDTH_16 |
+	dev->resource[2]->flags |=  WIN_ENABLE | WIN_DATA_WIDTH_16 |
 			 WIN_USE_WAIT;
-	win.Base = 0;
-	win.Size = SSB_CORE_SIZE;
-	win.AccessSpeed = 250;
-	res = pcmcia_request_window(dev, &win, &dev->win);
+	dev->resource[2]->start = 0;
+	dev->resource[2]->end = SSB_CORE_SIZE;
+	res = pcmcia_request_window(dev, dev->resource[2], 250);
 	if (res != 0)
 		goto err_kfree_ssb;
 
-	res = pcmcia_map_mem_page(dev, dev->win, 0);
+	res = pcmcia_map_mem_page(dev, dev->resource[2], 0);
 	if (res != 0)
 		goto err_disable;
 
@@ -96,7 +94,7 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)
 	if (res != 0)
 		goto err_disable;
 
-	err = ssb_bus_pcmciabus_register(ssb, dev, win.Base);
+	err = ssb_bus_pcmciabus_register(ssb, dev, dev->resource[2]->start);
 	if (err)
 		goto err_disable;
 	dev->priv = ssb;
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88560d0..ab34cb8 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -391,7 +391,6 @@ static int ray_config(struct pcmcia_device *link)
 {
 	int ret = 0;
 	int i;
-	win_req_t req;
 	struct net_device *dev = (struct net_device *)link->priv;
 	ray_dev_t *local = netdev_priv(dev);
 
@@ -420,46 +419,45 @@ static int ray_config(struct pcmcia_device *link)
 		goto failed;
 
 /*** Set up 32k window for shared memory (transmit and control) ************/
-	req.Attributes =
-	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x8000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &link->win);
+	link->resource[2]->flags |= WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
+	link->resource[2]->start = 0;
+	link->resource[2]->end = 0x8000;
+	ret = pcmcia_request_window(link, link->resource[2], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, link->win, 0);
+	ret = pcmcia_map_mem_page(link, link->resource[2], 0);
 	if (ret)
 		goto failed;
-	local->sram = ioremap(req.Base, req.Size);
+	local->sram = ioremap(link->resource[2]->start,
+			resource_size(link->resource[2]));
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
-	req.Attributes =
+	link->resource[3]->flags |=
 	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x4000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &local->rmem_handle);
+	link->resource[3]->start = 0;
+	link->resource[3]->end = 0x4000;
+	ret = pcmcia_request_window(link, link->resource[3], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, local->rmem_handle, 0x8000);
+	ret = pcmcia_map_mem_page(link, link->resource[3], 0x8000);
 	if (ret)
 		goto failed;
-	local->rmem = ioremap(req.Base, req.Size);
+	local->rmem = ioremap(link->resource[3]->start,
+			resource_size(link->resource[3]));
 
 /*** Set up window for attribute memory ***********************************/
-	req.Attributes =
+	link->resource[4]->flags |=
 	    WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
-	req.Base = 0;
-	req.Size = 0x1000;
-	req.AccessSpeed = ray_mem_speed;
-	ret = pcmcia_request_window(link, &req, &local->amem_handle);
+	link->resource[4]->start = 0;
+	link->resource[4]->end = 0x1000;
+	ret = pcmcia_request_window(link, link->resource[4], ray_mem_speed);
 	if (ret)
 		goto failed;
-	ret = pcmcia_map_mem_page(link, local->amem_handle, 0);
+	ret = pcmcia_map_mem_page(link, link->resource[4], 0);
 	if (ret)
 		goto failed;
-	local->amem = ioremap(req.Base, req.Size);
+	local->amem = ioremap(link->resource[4]->start,
+			resource_size(link->resource[4]));
 
 	dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
 	dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 9f01ddb..e79848f 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -25,8 +25,6 @@ struct beacon_rx {
 typedef struct ray_dev_t {
     int card_status;
     int authentication_state;
-    window_handle_t amem_handle;   /* handle to window for attribute memory  */
-    window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
     void __iomem *sram;            /* pointer to beginning of shared RAM     */
     void __iomem *amem;            /* pointer to attribute mem window        */
     void __iomem *rmem;            /* pointer to receive buffer window       */
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 9ba4dad..bf16a1c 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -204,11 +204,10 @@ int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
 EXPORT_SYMBOL(pcmcia_write_config_byte);
 
 
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int offset)
 {
 	struct pcmcia_socket *s = p_dev->socket;
-	struct resource *res = wh;
 	unsigned int w;
 	int ret;
 
@@ -386,7 +385,12 @@ out:
 	return ret;
 } /* pcmcia_release_io */
 
-
+/**
+ * pcmcia_release_window() - release reserved iomem for PCMCIA devices
+ *
+ * pcmcia_release_window() releases struct resource *res which was
+ * previously reserved by calling pcmcia_request_window().
+ */
 int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 {
 	struct pcmcia_socket *s = p_dev->socket;
@@ -420,6 +424,8 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
 		kfree(win->res);
 		win->res = NULL;
 	}
+	res->start = res->end = 0;
+	res->flags = IORESOURCE_MEM;
 	p_dev->_win &= ~CLIENT_WIN_REQ(w);
 	mutex_unlock(&s->ops_mutex);
 
@@ -795,17 +801,21 @@ int pcmcia_setup_irq(struct pcmcia_device *p_dev)
 }
 
 
-/** pcmcia_request_window
+/**
+ * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
  *
- * Request_window() establishes a mapping between card memory space
- * and system memory space.
+ * pcmcia_request_window() attepts to reserve an iomem ranges specified in
+ * struct resource *res pointing to one of the entries in
+ * struct pcmcia_device *p_dev->resource[2..5]. The "start" value is the
+ * requested start of the IO mem resource; "end" reflects the size
+ * requested.
  */
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+			unsigned int speed)
 {
 	struct pcmcia_socket *s = p_dev->socket;
 	pccard_mem_map *win;
 	u_long align;
-	struct resource *res;
 	int w;
 
 	if (!(s->state & SOCKET_PRESENT)) {
@@ -814,19 +824,19 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	}
 
 	/* Window size defaults to smallest available */
-	if (req->Size == 0)
-		req->Size = s->map_size;
-	align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
-	if (req->Size & (s->map_size-1)) {
+	if (res->end == 0)
+		res->end = s->map_size;
+	align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
+	if (res->end & (s->map_size-1)) {
 		dev_dbg(&p_dev->dev, "invalid map size\n");
 		return -EINVAL;
 	}
-	if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
-	    (req->Base & (align-1))) {
+	if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
+	    (res->start & (align-1))) {
 		dev_dbg(&p_dev->dev, "invalid base address\n");
 		return -EINVAL;
 	}
-	if (req->Base)
+	if (res->start)
 		align = 0;
 
 	/* Allocate system memory window */
@@ -843,7 +853,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	win = &s->win[w];
 
 	if (!(s->features & SS_CAP_STATIC_MAP)) {
-		win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
+		win->res = pcmcia_find_mem_region(res->start, res->end, align,
 						0, s);
 		if (!win->res) {
 			dev_dbg(&p_dev->dev, "allocating mem region failed\n");
@@ -855,8 +865,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 
 	/* Configure the socket controller */
 	win->map = w+1;
-	win->flags = req->Attributes;
-	win->speed = req->AccessSpeed;
+	win->flags = res->flags & WIN_FLAGS_MAP;
+	win->speed = speed;
 	win->card_start = 0;
 
 	if (s->ops->set_mem_map(s, win) != 0) {
@@ -868,17 +878,14 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 
 	/* Return window handle */
 	if (s->features & SS_CAP_STATIC_MAP)
-		req->Base = win->static_start;
+		res->start = win->static_start;
 	else
-		req->Base = win->res->start;
+		res->start = win->res->start;
 
 	/* convert to new-style resources */
-	res = p_dev->resource[w + MAX_IO_WIN];
-	res->start = req->Base;
-	res->end = req->Base + req->Size - 1;
-	res->flags &= ~IORESOURCE_BITS;
-	res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
-	res->flags |= IORESOURCE_MEM;
+	res->end += res->start - 1;
+	res->flags &= ~WIN_FLAGS_REQ;
+	res->flags |= (win->map << 2) | IORESOURCE_MEM;
 	res->parent = win->res;
 	if (win->res)
 		request_resource(&iomem_resource, res);
@@ -886,7 +893,6 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
 	dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
 
 	mutex_unlock(&s->ops_mutex);
-	*wh = res;
 
 	return 0;
 } /* pcmcia_request_window */
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index dd9b403..e872e06 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1596,18 +1596,13 @@ static void nsp_cs_detach(struct pcmcia_device *link)
     ethernet device available to the system.
 ======================================================================*/
 
-struct nsp_cs_configdata {
-	nsp_hw_data		*data;
-	win_req_t		req;
-};
-
 static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 			       cistpl_cftable_entry_t *cfg,
 			       cistpl_cftable_entry_t *dflt,
 			       unsigned int vcc,
 			       void *priv_data)
 {
-	struct nsp_cs_configdata *cfg_mem = priv_data;
+	nsp_hw_data		*data = priv_data;
 
 	if (cfg->index == 0)
 		return -ENODEV;
@@ -1663,21 +1658,24 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,
 		if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
 			cistpl_mem_t	*mem =
 				(cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
-			cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-			cfg_mem->req.Attributes |= WIN_ENABLE;
-			cfg_mem->req.Base = mem->win[0].host_addr;
-			cfg_mem->req.Size = mem->win[0].len;
-			if (cfg_mem->req.Size < 0x1000)
-				cfg_mem->req.Size = 0x1000;
-			cfg_mem->req.AccessSpeed = 0;
-			if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)
+			p_dev->resource[2]->flags |= (WIN_DATA_WIDTH_16 |
+						WIN_MEMORY_TYPE_CM |
+						WIN_ENABLE);
+			p_dev->resource[2]->start = mem->win[0].host_addr;
+			p_dev->resource[2]->end = mem->win[0].len;
+			if (p_dev->resource[2]->end < 0x1000)
+				p_dev->resource[2]->end = 0x1000;
+			if (pcmcia_request_window(p_dev, p_dev->resource[2],
+							0) != 0)
 				goto next_entry;
-			if (pcmcia_map_mem_page(p_dev, p_dev->win,
+			if (pcmcia_map_mem_page(p_dev, p_dev->resource[2],
 					mem->win[0].card_addr) != 0)
 				goto next_entry;
 
-			cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
-			cfg_mem->data->MmioLength  = cfg_mem->req.Size;
+			data->MmioAddress = (unsigned long)
+				ioremap_nocache(p_dev->resource[2]->start,
+					resource_size(p_dev->resource[2]));
+			data->MmioLength  = resource_size(p_dev->resource[2]);
 		}
 		/* If we got this far, we're cool! */
 		return 0;
@@ -1693,18 +1691,12 @@ static int nsp_cs_config(struct pcmcia_device *link)
 {
 	int		  ret;
 	scsi_info_t	 *info	 = link->priv;
-	struct nsp_cs_configdata *cfg_mem;
 	struct Scsi_Host *host;
 	nsp_hw_data      *data = &nsp_data_base;
 
 	nsp_dbg(NSP_DEBUG_INIT, "in");
 
-	cfg_mem = kzalloc(sizeof(*cfg_mem), GFP_KERNEL);
-	if (!cfg_mem)
-		return -ENOMEM;
-	cfg_mem->data = data;
-
-	ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+	ret = pcmcia_loop_config(link, nsp_cs_config_check, data);
 	if (ret)
 		goto cs_failed;
 
@@ -1767,18 +1759,15 @@ static int nsp_cs_config(struct pcmcia_device *link)
 		printk(", io %pR", link->resource[0]);
 	if (link->resource[1])
 		printk(" & %pR", link->resource[1]);
-	if (link->win)
-		printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
-		       cfg_mem->req.Base+cfg_mem->req.Size-1);
+	if (link->resource[2])
+		printk(", mem %pR", link->resource[2]);
 	printk("\n");
 
-	kfree(cfg_mem);
 	return 0;
 
  cs_failed:
 	nsp_dbg(NSP_DEBUG_INIT, "config fail");
 	nsp_cs_release(link);
-	kfree(cfg_mem);
 
 	return -ENODEV;
 } /* nsp_cs_config */
@@ -1807,7 +1796,7 @@ static void nsp_cs_release(struct pcmcia_device *link)
 		scsi_remove_host(info->host);
 	}
 
-	if (link->win) {
+	if (resource_size(link->resource[2])) {
 		if (data != NULL) {
 			iounmap((void *)(data->MmioAddress));
 		}
diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
index 68d8bde..63cb9bb 100644
--- a/include/pcmcia/cs.h
+++ b/include/pcmcia/cs.h
@@ -68,28 +68,4 @@ typedef struct config_req_t {
 #define PRESENT_IOBASE_3	0x100
 #define PRESENT_IOSIZE		0x200
 
-/* For RequestWindow */
-typedef struct win_req_t {
-    u_int	Attributes;
-    u_long	Base;
-    u_int	Size;
-    u_int	AccessSpeed;
-} win_req_t;
-
-/* Attributes for RequestWindow */
-#define WIN_MEMORY_TYPE_CM	0x00 /* default */
-#define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
-#define WIN_DATA_WIDTH_8	0x00 /* default */
-#define WIN_DATA_WIDTH_16	0x02 /* MAP_16BIT */
-#define WIN_ENABLE		0x01 /* MAP_ACTIVE */
-#define WIN_USE_WAIT		0x40 /* MAP_USE_WAIT */
-
-#define WIN_FLAGS_MAP		0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
-					MAP_USE_WAIT */
-#define WIN_FLAGS_REQ		0x1c /* mapping to socket->win[i]:
-					0x04 -> 0
-					0x08 -> 1
-					0x0c -> 2
-					0x10 -> 3 */
-
 #endif /* _LINUX_CS_H */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index 70c58ed..6f7cb38 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -36,8 +36,6 @@ struct pcmcia_device;
 struct config_t;
 struct net_device;
 
-typedef struct resource *window_handle_t;
-
 /* dynamic device IDs for PCMCIA device drivers. See
  * Documentation/pcmcia/driver.txt for details.
 */
@@ -92,7 +90,6 @@ struct pcmcia_device {
 
 	/* deprecated, will be cleaned up soon */
 	config_req_t		conf;
-	window_handle_t		win;
 
 	/* device setup */
 	unsigned int		irq;
@@ -209,10 +206,10 @@ int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
 int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 				 config_req_t *req);
 
-int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req,
-			  window_handle_t *wh);
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win);
-int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win,
+int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
+			unsigned int speed);
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res);
+int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
 			unsigned int offset);
 
 int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
@@ -234,6 +231,23 @@ static inline int pcmcia_io_cfg_data_width(unsigned int flags)
 	return IO_DATA_PATH_WIDTH_AUTO;
 }
 
+/* IO memory */
+#define WIN_MEMORY_TYPE_CM	0x00 /* default */
+#define WIN_MEMORY_TYPE_AM	0x20 /* MAP_ATTRIB */
+#define WIN_DATA_WIDTH_8	0x00 /* default */
+#define WIN_DATA_WIDTH_16	0x02 /* MAP_16BIT */
+#define WIN_ENABLE		0x01 /* MAP_ACTIVE */
+#define WIN_USE_WAIT		0x40 /* MAP_USE_WAIT */
+
+#define WIN_FLAGS_MAP		0x63 /* MAP_ATTRIB | MAP_16BIT | MAP_ACTIVE |
+					MAP_USE_WAIT */
+#define WIN_FLAGS_REQ		0x1c /* mapping to socket->win[i]:
+					0x04 -> 0
+					0x08 -> 1
+					0x0c -> 2
+					0x10 -> 3 */
+
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_DS_H */
-- 
1.7.0.4



From computersforpeace at gmail.com  Thu Oct 21 11:54:06 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 21 Oct 2010 08:54:06 -0700
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style, signed-ness, 
	printing fixups
In-Reply-To: <AANLkTikthtaMh0qjFVLu29ZbageANnd_JsbB7wLqiMSM@mail.gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
	<AANLkTikthtaMh0qjFVLu29ZbageANnd_JsbB7wLqiMSM@mail.gmail.com>
Message-ID: <4CC0621E.9040102@gmail.com>

Hi,

I just want to be clear in communication this time, so I have a few
clarification questions.

On 10/21/2010 12:37 AM, Mike Frysinger wrote:
> On Thu, Oct 21, 2010 at 03:19, Brian Norris wrote:
>> There were some signed/unsigned integer comparisons. Their types were
>> changed for safety. Also, "strtol" was improperly used for unsigned
>> data types.
> 
> dont really like these being merged, but that's obviously Artem's call, not mine

What exactly do you not like? The use of unsigned types, the use of
strtoul, a lack of consistency, or something else? I'm open to changing
my type usages if you have ideas that make more sense.

>> -       while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
>> +       do {
>>                linebuf[lx++] = ' ';
>> +       } while (lx < (linebuflen - 1) && lx < (ascii_column - 1));
> 
> hmm, unrelated to your changes, but i'm pretty sure this can be
> rewritten into a sprintf ...
>   sprintf(linebuf + lx, "%*s", (linebuflen - 1) - lx, "")
> and integrating the ascii_column stuff too.  or maybe that's too complicated.


I can look try that in the future. You're probably right though. When I
wrote this, I really just copied/pasted/fixed the library hexdump code
from the linux kernel, so I didn't spend time making it the simplest
possible.

Thanks,
Brian


From nico at fluxnic.net  Thu Oct 21 12:32:02 2010
From: nico at fluxnic.net (Nicolas Pitre)
Date: Thu, 21 Oct 2010 12:32:02 -0400 (EDT)
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for
	Lock/Unlock bug.
In-Reply-To: <1287656983.2932.14.camel@localhost>
References: <1287498263-5561-1-git-send-email-phdm@macqel.be>
	<1287650398.2932.5.camel@localhost>
	<20101021093343.GA17631@frolo.macqel>
	<1287656983.2932.14.camel@localhost>
Message-ID: <alpine.LFD.2.00.1010211226120.2764@xanadu.home>

On Thu, 21 Oct 2010, Artem Bityutskiy wrote:

> On Thu, 2010-10-21 at 11:33 +0200, Philippe De Muyter wrote:
> > On Thu, Oct 21, 2010 at 11:39:58AM +0300, Artem Bityutskiy wrote:
> > > On Tue, 2010-10-19 at 16:24 +0200, Philippe De Muyter wrote:
> > > > Some flash chips have a small but annoying bug, documented in
> > > >     "Numonyx Axcell P33/P30 256-Mbit Specification Update"
> > > > 
> > > >     It states :
> > > >     When customer uses [...] block unlock, the block lock status might
> > > >     be altered inadvertently. Lock status might be set to either 01h
> > > >     or 03h unexpectedly (00h as expected data), which leads to
> > > >     program/erase failure on certain blocks.
> > > > 
> > > >     A workaround is given, (summary : issue a "Read Lock Status" before
> > > >     the "Lock" or "Unlock" command) which I have applied and tested
> > > >     with success.
> > > > 
> > > > Signed-off-by: Philippe De Muyter <phdm at macqel.be>
> > > 
> > > Is this Numonyx-specific issue? Should there be some kind of "if
> > > (numonyx)" statement?
> > 
> > This is clearly a bug specific to some Numonyx flashes.
> > My chips have Manufacturer ID: 0x89, Device ID: 0x881B, but there are
> > other chips in the same family.  The errata
> > http://www.numonyx.com/Documents/Specification%20Updates/509003_P3X_65nm_3V_256Mbit_Discrete.pdf does not list the ManufacturerIDs/DeviceIDs of the affected
> > chips.
> 
> CCed Nicolas correctly.
> 
> Anyway, if this affects only subset of chips, it make sense to make this
> quirk conditional, because this might affect boot speed, e.g., if some
> systems unlock all blocks on boot-up.

That is probably quite unlikely to make a difference given that there is 
no result delay involved.

However, does the erratum workaround imply that the status actually has 
to be read?  In other words, can you simply issue CMD 90 without calling 
cfi_read_query()?


Nicolas


From matthieu.castet at parrot.com  Thu Oct 21 12:52:18 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Thu, 21 Oct 2010 18:52:18 +0200
Subject: [PATCH 3/3 v3] NAND: add support for reading ONFI parameters
	from NAND device
In-Reply-To: <201008301832.24672.florian@openwrt.org>
References: <201008301832.24672.florian@openwrt.org>
Message-ID: <4CC06FC2.2060406@parrot.com>

Hi,

Florian Fainelli a ?crit :
> This patch adds support for reading NAND device ONFI parameters and use
> the ONFI informations to define its geometry. In case the device supports
> ONFI, the onfi_version field in struct nand_chip contains the version (BCD)
> and the onfi_params structure can be used by drivers to set up timings and
> such. We currently only support ONFI 1.0 parameters.
> 
> Signed-off-by: Brian Norris <norris at broadcom.com>
> Signed-off-by: Matthieu Castet <matthieu.castet at parrot.com>
> Signed-off-by: Maxime Bizon <mbizon at freebox.fr>
> Signed-off-by: Florian Fainelli <ffainelli at freebox.fr>
> ---
                 chip->cmdfunc = nand_command_lp;
> 
> +       /* TODO onfi flash name */
>         printk(KERN_INFO "NAND device: Manufacturer ID:"
> -              " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
> -              nand_manuf_ids[maf_idx].name, type->name);
> +               " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
> +               nand_manuf_ids[maf_idx].name,
> +               chip->onfi_version ? type->name:chip->onfi_params.model);
> 
I don't know if it has been noticed but it should be
chip->onfi_version ? chip->onfi_params.model : type->name

Matthieu


From matthieu.castet at parrot.com  Thu Oct 21 13:04:27 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Thu, 21 Oct 2010 19:04:27 +0200
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <1287649931.2932.3.camel@localhost>
References: <20101013163005.GB1889@silverbox.local>	<1287581218.9272.67.camel@localhost>
	<4CBFF865.9010706@linutronix.de>
	<1287649931.2932.3.camel@localhost>
Message-ID: <4CC0729B.7060109@parrot.com>

Hi,

Artem Bityutskiy a ?crit :
> On Thu, 2010-10-21 at 10:23 +0200, Sebastian Andrzej Siewior wrote:
>> Artem Bityutskiy wrote:
>>>> From a quick glance at the ubifs code, this might come out of the
>>>> garbage collector that is triggered on every sync() and writes
>>>> something even if nothing has changed.
> 
> Yeah, the UBIFS must be writing the commit start and commit end nodes,
> and then erasing the previous log LEB (all this is done in log.c). As
> soon as I have time I'll look at this, I really do not have time right
> now. And there is Matthiew's problem which is actually quite big, but
> for some reasons affects only him :-)
It could be interesting to know which nand flash are tested.

On our boards ST 256MB chip work fine, but micron flash got unstable 
page problem (sorry I don't have the model number ATM).

And it is getting worse, new SLC flash can now get up to 4 bits error 
per 512.


Matthieu


From w.sang at pengutronix.de  Thu Oct 21 13:10:45 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Thu, 21 Oct 2010 19:10:45 +0200
Subject: [PATCH] mtd: chips: add SST38VF640x nor-flashes
In-Reply-To: <1287716022-2792-1-git-send-email-zhangyd6@gmail.com>
References: <1287716022-2792-1-git-send-email-zhangyd6@gmail.com>
Message-ID: <20101021171045.GE11131@pengutronix.de>

On Thu, Oct 21, 2010 at 10:53:42PM -0400, zhangyd wrote:
> Due to broken CFI, these flashes should be operated in jedec probe mode.
> When you operate them in the CFI probe mode, you will get the wrong sector
> size.And it will fail to set up the flash during the probe(CFI mode).
> And i have tested it on my platform.
> 
> Signed-off-by: yidong zhang <zhangyd6 at gmail.com>

Still NACK. Unless Guillaume doesn't come to the conclusion that JEDEC is
better, supporting him is the preferred option IMO.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101021/81ff9167/attachment.sig>

From dedekind1 at gmail.com  Thu Oct 21 14:43:29 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 21 Oct 2010 21:43:29 +0300
Subject: ubifs: sync() causes writes even if nothing is changed
In-Reply-To: <4CC0729B.7060109@parrot.com>
References: <20101013163005.GB1889@silverbox.local>
	<1287581218.9272.67.camel@localhost> <4CBFF865.9010706@linutronix.de>
	<1287649931.2932.3.camel@localhost>  <4CC0729B.7060109@parrot.com>
Message-ID: <1287686609.7480.0.camel@brekeke>

On Thu, 2010-10-21 at 19:04 +0200, Matthieu CASTET wrote:
> Hi,
> 
> Artem Bityutskiy a ?crit :
> > On Thu, 2010-10-21 at 10:23 +0200, Sebastian Andrzej Siewior wrote:
> >> Artem Bityutskiy wrote:
> >>>> From a quick glance at the ubifs code, this might come out of the
> >>>> garbage collector that is triggered on every sync() and writes
> >>>> something even if nothing has changed.
> > 
> > Yeah, the UBIFS must be writing the commit start and commit end nodes,
> > and then erasing the previous log LEB (all this is done in log.c). As
> > soon as I have time I'll look at this, I really do not have time right
> > now. And there is Matthiew's problem which is actually quite big, but
> > for some reasons affects only him :-)
> It could be interesting to know which nand flash are tested.
> 
> On our boards ST 256MB chip work fine, but micron flash got unstable 
> page problem (sorry I don't have the model number ATM).
> 
> And it is getting worse, new SLC flash can now get up to 4 bits error 
> per 512.

It would be great if you sent me a board where unstable pages are easy
to reproduce.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From akpm at linux-foundation.org  Thu Oct 21 13:25:34 2010
From: akpm at linux-foundation.org (Andrew Morton)
Date: Thu, 21 Oct 2010 10:25:34 -0700
Subject: [PATCH V2 45/69] ST SPEAr: PCIE gadget suppport
In-Reply-To: <0901B62280FF37468247D8348744254F449565AA97@EAPEX1MAIL1.st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<c91308e26397dbe49f384c7d3cf168593e1fe8b0.1285933332.git.viresh.kumar@st.com>
	<20101019144725.977297f5.akpm@linux-foundation.org>
	<0901B62280FF37468247D8348744254F449565AA97@EAPEX1MAIL1.st.com>
Message-ID: <20101021102534.5845ac4a.akpm@linux-foundation.org>

On Thu, 21 Oct 2010 22:18:28 +0800 Pratyush ANAND <pratyush.anand at st.com> wrote:

> > > +static ssize_t pcie_gadget_show_help(struct device *dev,
> > > +           struct device_attribute *attr, char *buf)
> > > +{
> > > +   char text[] = "\t\tlink read->ltssm status\n \
> > > +           link write->arg1 = UP to enable ltsmm DOWN to disable\n \
> > > +           int_type read->type of supported interrupt\n \
> > > +           int_type write->arg1 = interrupt type to be configured and\n \
> > > +           can be INTA, MSI or NO_INT\n \
> > > +           (select MSI only when you have programmed no_of_msi)\n \
> > > +           no_of_msi read->zero if MSI is not enabled by host\n \
> > > +           and positive value is the number of MSI vector granted\n \
> > > +           no_of_msi write->arg1 = number of MSI vector needed\n \
> > > +           inta write->arg1 = 1 to assert INTA and 0 to de-assert\n \
> > > +           send_msi write->arg1 = MSI vector to be send\n \
> > > +           vendor_id read->programmed vendor id (hex)\n\
> > > +           vendor_id write->arg1 = vendor id(hex) to be programmed\n \
> > > +           device_id read->programmed device id(hex)\n \
> > > +           device_id write->arg1 = device id(hex) to be programmed\n \
> > > +           bar0_size read->size of bar0 in hex\n \
> > > +           bar0_size write->arg1= size of bar0 in hex\n \
> > > +           (default bar0 size is 1000 (hex) bytes)\n \
> > > +           bar0_address read->address of bar0 mapped area in hex\n \
> > > +           bar0_address write->arg1 = address of bar0 mapped area in
> > hex\n\
> > > +           (default mapping of bar0 is SYSRAM1(E0800000)\n \
> > > +           (always program bar size before bar address)\n \
> > > +           (kernel might modify bar size and address to align)\n \
> > > +           (read back bar size and address after writing to check)\n \
> > > +           bar0_rw_offset read->offset of bar0 for which bar0_data \n \
> > > +           will return value\n \
> > > +           bar0_rw_offset write->arg1 = offset of bar0 for which\n \
> > > +           bar0_data will write value\n \
> > > +           bar0_data read->data at bar0_rw_offset\n \
> > > +           bar0_data write->arg1 = data to be written at\n \
> > > +           bar0_rw_offset\n";
> > > +
> > > +   int size = (sizeof(text) < PAGE_SIZE) ? sizeof(text) : PAGE_SIZE;
> > > +
> > > +   return snprintf(buf, size, "%s", text);
> > > +}
> >
> > What the heck is this??
> >
> 
> This was just to provide help for different sysfs nodes. What could be the other
> Way to do it? Should it be better to remove help node from here provide all the help
> In a separate document?

Yes, documenting it externally would be more typical.



From phdm at macqel.be  Thu Oct 21 15:34:41 2010
From: phdm at macqel.be (Philippe De Muyter)
Date: Thu, 21 Oct 2010 21:34:41 +0200
Subject: [PATCH] mtd: Apply Numonyx Axcell P33/P30 workaround for
	Lock/Unlock bug.
In-Reply-To: <alpine.LFD.2.00.1010211226120.2764@xanadu.home>
References: <1287498263-5561-1-git-send-email-phdm@macqel.be>
	<1287650398.2932.5.camel@localhost>
	<20101021093343.GA17631@frolo.macqel>
	<1287656983.2932.14.camel@localhost>
	<alpine.LFD.2.00.1010211226120.2764@xanadu.home>
Message-ID: <20101021193441.GA17855@frolo.macqel>

Hello Nicolas,

On Thu, Oct 21, 2010 at 12:32:02PM -0400, Nicolas Pitre wrote:
> On Thu, 21 Oct 2010, Artem Bityutskiy wrote:
> 
> > On Thu, 2010-10-21 at 11:33 +0200, Philippe De Muyter wrote:
> > > On Thu, Oct 21, 2010 at 11:39:58AM +0300, Artem Bityutskiy wrote:
> > > > On Tue, 2010-10-19 at 16:24 +0200, Philippe De Muyter wrote:
> > > > > Some flash chips have a small but annoying bug, documented in
> > > > >     "Numonyx Axcell P33/P30 256-Mbit Specification Update"
> > > > > 
> > > > >     It states :
> > > > >     When customer uses [...] block unlock, the block lock status might
> > > > >     be altered inadvertently. Lock status might be set to either 01h
> > > > >     or 03h unexpectedly (00h as expected data), which leads to
> > > > >     program/erase failure on certain blocks.
> > > > > 
> > > > >     A workaround is given, (summary : issue a "Read Lock Status" before
> > > > >     the "Lock" or "Unlock" command) which I have applied and tested
> > > > >     with success.
> > > > > 
> > > > > Signed-off-by: Philippe De Muyter <phdm at macqel.be>
> > > > 
> > > > Is this Numonyx-specific issue? Should there be some kind of "if
> > > > (numonyx)" statement?
> > > 
> > > This is clearly a bug specific to some Numonyx flashes.
> > > My chips have Manufacturer ID: 0x89, Device ID: 0x881B, but there are
> > > other chips in the same family.  The errata
> > > http://www.numonyx.com/Documents/Specification%20Updates/509003_P3X_65nm_3V_256Mbit_Discrete.pdf does not list the ManufacturerIDs/DeviceIDs of the affected
> > > chips.
> > 
> > CCed Nicolas correctly.
> > 
> > Anyway, if this affects only subset of chips, it make sense to make this
> > quirk conditional, because this might affect boot speed, e.g., if some
> > systems unlock all blocks on boot-up.
> 
> That is probably quite unlikely to make a difference given that there is 
> no result delay involved.
> 
> However, does the erratum workaround imply that the status actually has 
> to be read?  In other words, can you simply issue CMD 90 without calling 
> cfi_read_query()?

Here is the relevant excerpt of the errata :

Workaround:  If the interval between 60h and its subsequent command
             can be guaranteed within 20us, Option I is recommended,
             otherwise Option II (involves hardware) should be selected.
Option I: The table below lists the detail command sequences:
Command
              Data bus           Address bus       Remarks
Sequence
  1              90h            Block Address
                                                   Read Lock Status
  2             Read         Block Address + 02h
 (2)(3)                                      (1)
3                60h           Block Address
 (2)(3)                                      (1)   Lock/Unlock/RCR Configuration
4           D0h/01h/03h        Block Address
Notes:
(1) Block Address refers to RCR configuration data only when the 60h
    command sequence is used to set RCR register combined with 03h
    subsequent command.
(2) For the third and fourth command sequences, the Block Address must
    be the same.
(3) The interval between 60h command and its subsequent D0h/01h/2Fh/03h
    commands should be less than 20us.

Philippe

-- 
Philippe De Muyter  phdm at macqel dot be  Tel +32 27029044
Macq Electronique SA  rue de l'Aeronef 2  B-1140 Bruxelles  Fax +32 27029077


From vapier.adi at gmail.com  Thu Oct 21 15:45:53 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 21 Oct 2010 15:45:53 -0400
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style, signed-ness, 
	printing fixups
In-Reply-To: <4CC0621E.9040102@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
	<AANLkTikthtaMh0qjFVLu29ZbageANnd_JsbB7wLqiMSM@mail.gmail.com>
	<4CC0621E.9040102@gmail.com>
Message-ID: <AANLkTi=kVN90MrdD5f9ifzb4XLrV4Gh7Z00iHkeRYQ7Y@mail.gmail.com>

On Thu, Oct 21, 2010 at 11:54, Brian Norris wrote:
> On 10/21/2010 12:37 AM, Mike Frysinger wrote:
>> On Thu, Oct 21, 2010 at 03:19, Brian Norris wrote:
>>> There were some signed/unsigned integer comparisons. Their types were
>>> changed for safety. Also, "strtol" was improperly used for unsigned
>>> data types.
>>
>> dont really like these being merged, but that's obviously Artem's call, not mine
>
> What exactly do you not like? The use of unsigned types, the use of
> strtoul, a lack of consistency, or something else? I'm open to changing
> my type usages if you have ideas that make more sense.

i dont have a problem with the changes.  i was talking about doing
style and functional (type changes) in one patch rather than two.
-mike


From maximlevitsky at gmail.com  Thu Oct 21 18:54:11 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 22 Oct 2010 00:54:11 +0200
Subject: pwrite() to nand in raw mode fails with EINVAL
In-Reply-To: <1285768684.32420.91.camel@sakura.staff.proxad.net>
References: <1285699650.32420.70.camel@sakura.staff.proxad.net>
	<1285764747.2437.116.camel@localhost>
	<1285768684.32420.91.camel@sakura.staff.proxad.net>
Message-ID: <1287701651.8965.0.camel@maxim-laptop>

On Wed, 2010-09-29 at 15:58 +0200, Maxime Bizon wrote:
> On Wed, 2010-09-29 at 15:52 +0300, Artem Bityutskiy wrote:
> 
> > Maxime, I've cleaned up comments, added your signed-off-by and cc
> > stable. Is this OK?
> 
> Yep
> 
> > It would also be nice to get an ack from Maxim Levitsky.
> 
> The patch fixes the problem, but I let Maxim decides if that's the
> correct way to fix it.

Very sorry for not noticing this.
I will look very carefully at this tomorrow.

Best regards,
	Maxim Levitsky



From maximlevitsky at gmail.com  Thu Oct 21 20:09:58 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Fri, 22 Oct 2010 02:09:58 +0200
Subject: pwrite() to nand in raw mode fails with EINVAL
In-Reply-To: <1287701651.8965.0.camel@maxim-laptop>
References: <1285699650.32420.70.camel@sakura.staff.proxad.net>
	<1285764747.2437.116.camel@localhost>
	<1285768684.32420.91.camel@sakura.staff.proxad.net>
	<1287701651.8965.0.camel@maxim-laptop>
Message-ID: <1287706198.12734.16.camel@maxim-laptop>

On Fri, 2010-10-22 at 00:54 +0200, Maxim Levitsky wrote:
> On Wed, 2010-09-29 at 15:58 +0200, Maxime Bizon wrote:
> > On Wed, 2010-09-29 at 15:52 +0300, Artem Bityutskiy wrote:
> > 
> > > Maxime, I've cleaned up comments, added your signed-off-by and cc
> > > stable. Is this OK?
> > 
> > Yep
> > 
> > > It would also be nice to get an ack from Maxim Levitsky.
> > 
> > The patch fixes the problem, but I let Maxim decides if that's the
> > correct way to fix it.
> 
> Very sorry for not noticing this.
> I will look very carefully at this tomorrow.
> 
> Best regards,
> 	Maxim Levitsky
> 
I don't see any reason for that patch to be wrong.
I can't test it on my xD card, because like I said before its OOB is
fake, and it probably just emulates the NAND interface.

So of course:

Acked-by: Maxim Levitsky <maximlevitsky at gmail.com>

Best regards,
	Maxim Levitsky



From zhangyd6 at gmail.com  Thu Oct 21 20:17:27 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Fri, 22 Oct 2010 08:17:27 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
Message-ID: <AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>

On Thu, Oct 21, 2010 at 11:24 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/21 yidong zhang <zhangyd6 at gmail.com>:
>>> Hi.
>>> The patch use the fixup_sst39vf_rev_b() function which calls
>>> fixup_old_sst_eraseregion().
>>> It sets the NumEraseRegions to 1, thus CFI reports only the 1st erase
>>> region, i.e. the one calculated with the sector information (8KByte).
>>>
>>> Did you actually tested it with a real chip ?
>>
>> Yes, i did test both SST39VF6401B and SST38VF6401 a moment ago; The
>> SST39VF6401B works fine. But the SST38VF6401 couldn't work because of
>> the sector-size.It was 64KByte when i displayed the erase size.
>
> Could you send me your log with SST38VF6401 please ?
> I need to investigate on this.


Typical byte/word write timeout: 8 ?s
Maximum byte/word write timeout: 16 ?s
Typical full buffer write timeout: 8 ?s
Maximum full buffer write timeout: 64 ?s
Typical block erase timeout: 16 ms
Maximum block erase timeout: 32 ms
Typical chip erase timeout: 32 ms
Maximum chip erase timeout: 64 ms
Device size: 0x800000 bytes (8 MiB)
Flash Device Interface description: 0x0001
  - x16-only asynchronous interface
Max. bytes in buffer write: 0x20
Number of Erase Block Regions: 2
  Erase Region #0: BlockSize 0x10000 bytes, 1024 blocks
cif->cfiq->EraseRegionInfo[i] = 10003ff
  Erase Region #1: BlockSize 0x10000 bytes, 128 blocks
cif->cfiq->EraseRegionInfo[i] = 100007f
mb86hxx_pflash: Found 1 x16 devices at 0x0 in 16-bit bank
number of CFI chips: 1
ersize is 10000, ernum is 400
Sum of regions (4000000) != total size of set of interleaved chips (800000)



>
> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>


From kumar.gala at freescale.com  Fri Oct 22 02:01:12 2010
From: kumar.gala at freescale.com (Kumar Gala)
Date: Fri, 22 Oct 2010 01:01:12 -0500
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the partitions
	by OF node
In-Reply-To: <1287301490.1951.0.camel@localhost>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
	<1287256647.1781.34.camel@brekeke>
	<AANLkTimr03KAKnz5sfwm19=KzB-ik95WM_qQO0YP9qVs@mail.gmail.com>
	<1287301490.1951.0.camel@localhost>
Message-ID: <3AE1F37D-F328-40EF-8B35-F94CC074D384@freescale.com>


On Oct 17, 2010, at 2:44 AM, Artem Bityutskiy wrote:

> On Sat, 2010-10-16 at 19:05 -0600, Grant Likely wrote:
>> On Sat, Oct 16, 2010 at 1:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>>> On Tue, 2010-10-12 at 18:18 +0800, Mingkai Hu wrote:
>>>> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
>>>> Acked-by: Grant Likely <grant.likely at secretlab.ca>
>>>> ---
>>>> v4:
>>>> - Updated to latest kernel base(Linux 2.6.36-rc7).
>>>> - Made changes according to Grant's comments.
>>> 
>>> Looks good to me, pushed to l2-mtd-2.6.git, thanks.
>> 
>> Wait!  It will break whenever CONFIG_OF is not set.  I broke
>> linux-next with this patch.  It can be solved by wrapping the block
>> with #ifdef CONFIG_OF, but I'd like to find a better solution.
> 
> OK, removed.

Grant, poke.  Would like to see this either resolved or have this patch go in for .37 w/CONFIG_OF and fix properly for .38.

- k


From grant.likely at secretlab.ca  Fri Oct 22 03:39:44 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Fri, 22 Oct 2010 01:39:44 -0600
Subject: [PATCH v4 5/5] mtd: m25p80: add support to parse the
	partitions by OF node
In-Reply-To: <3AE1F37D-F328-40EF-8B35-F94CC074D384@freescale.com>
References: <1286878714-13090-1-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-2-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-3-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-4-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-5-git-send-email-Mingkai.hu@freescale.com>
	<1286878714-13090-6-git-send-email-Mingkai.hu@freescale.com>
	<1287256647.1781.34.camel@brekeke>
	<AANLkTimr03KAKnz5sfwm19=KzB-ik95WM_qQO0YP9qVs@mail.gmail.com>
	<1287301490.1951.0.camel@localhost>
	<3AE1F37D-F328-40EF-8B35-F94CC074D384@freescale.com>
Message-ID: <20101022073944.GE8205@angua.secretlab.ca>

On Fri, Oct 22, 2010 at 01:01:12AM -0500, Kumar Gala wrote:
> 
> On Oct 17, 2010, at 2:44 AM, Artem Bityutskiy wrote:
> 
> > On Sat, 2010-10-16 at 19:05 -0600, Grant Likely wrote:
> >> On Sat, Oct 16, 2010 at 1:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >>> On Tue, 2010-10-12 at 18:18 +0800, Mingkai Hu wrote:
> >>>> Signed-off-by: Mingkai Hu <Mingkai.hu at freescale.com>
> >>>> Acked-by: Grant Likely <grant.likely at secretlab.ca>
> >>>> ---
> >>>> v4:
> >>>> - Updated to latest kernel base(Linux 2.6.36-rc7).
> >>>> - Made changes according to Grant's comments.
> >>> 
> >>> Looks good to me, pushed to l2-mtd-2.6.git, thanks.
> >> 
> >> Wait!  It will break whenever CONFIG_OF is not set.  I broke
> >> linux-next with this patch.  It can be solved by wrapping the block
> >> with #ifdef CONFIG_OF, but I'd like to find a better solution.
> > 
> > OK, removed.
> 
> Grant, poke.  Would like to see this either resolved or have this patch go in for .37 w/CONFIG_OF and fix properly for .38.
> 

Okay, I've added it to my devicetree/next branch with the fix.
Assuming no last minute linux-next problems, I'll be asking Linus to
pull that branch early next week.

g.


From glecerf at gmail.com  Fri Oct 22 03:52:18 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 09:52:18 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
Message-ID: <AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>

2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>>> Yes, i did test both SST39VF6401B and SST38VF6401 a moment ago; The
>>> SST39VF6401B works fine. But the SST38VF6401 couldn't work because of
>>> the sector-size.It was 64KByte when i displayed the erase size.
>>
>> Could you send me your log with SST38VF6401 please ?
>> I need to investigate on this.
>
> Typical byte/word write timeout: 8 ?s
> Maximum byte/word write timeout: 16 ?s
> Typical full buffer write timeout: 8 ?s
> Maximum full buffer write timeout: 64 ?s
> Typical block erase timeout: 16 ms
> Maximum block erase timeout: 32 ms
> Typical chip erase timeout: 32 ms
> Maximum chip erase timeout: 64 ms
> Device size: 0x800000 bytes (8 MiB)
> Flash Device Interface description: 0x0001
> ?- x16-only asynchronous interface
> Max. bytes in buffer write: 0x20
> Number of Erase Block Regions: 2

You didn't applied my latest patch, you would have only 1 erase region
if you did.

> ?Erase Region #0: BlockSize 0x10000 bytes, 1024 blocks
> cif->cfiq->EraseRegionInfo[i] = 10003ff
> ?Erase Region #1: BlockSize 0x10000 bytes, 128 blocks
> cif->cfiq->EraseRegionInfo[i] = 100007f
> mb86hxx_pflash: Found 1 x16 devices at 0x0 in 16-bit bank
> number of CFI chips: 1
> ersize is 10000, ernum is 400
> Sum of regions (4000000) != total size of set of interleaved chips (800000)

This is the typical error with SST chips when the
fixup_sst39vf_rev_b() fixup function isn't called.

Could you try and report me which patches you applied and what results
you have with SST38VF6401 ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From zhangyd6 at gmail.com  Fri Oct 22 04:46:30 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Fri, 22 Oct 2010 16:46:30 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
	<AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
Message-ID: <AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>

On Fri, Oct 22, 2010 at 3:52 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>>>> Yes, i did test both SST39VF6401B and SST38VF6401 a moment ago; The
>>>> SST39VF6401B works fine. But the SST38VF6401 couldn't work because of
>>>> the sector-size.It was 64KByte when i displayed the erase size.
>>>
>>> Could you send me your log with SST38VF6401 please ?
>>> I need to investigate on this.
>>
>> Typical byte/word write timeout: 8 ?s
>> Maximum byte/word write timeout: 16 ?s
>> Typical full buffer write timeout: 8 ?s
>> Maximum full buffer write timeout: 64 ?s
>> Typical block erase timeout: 16 ms
>> Maximum block erase timeout: 32 ms
>> Typical chip erase timeout: 32 ms
>> Maximum chip erase timeout: 64 ms
>> Device size: 0x800000 bytes (8 MiB)
>> Flash Device Interface description: 0x0001
>> ?- x16-only asynchronous interface
>> Max. bytes in buffer write: 0x20
>> Number of Erase Block Regions: 2
>
> You didn't applied my latest patch, you would have only 1 erase region
> if you did.
  It was printed by the print_cfi_ident function. And the region
number is readed from the flash. So there was 2 erase region

>> ?Erase Region #0: BlockSize 0x10000 bytes, 1024 blocks
>> cif->cfiq->EraseRegionInfo[i] = 10003ff
>> ?Erase Region #1: BlockSize 0x10000 bytes, 128 blocks
>> cif->cfiq->EraseRegionInfo[i] = 100007f
>> mb86hxx_pflash: Found 1 x16 devices at 0x0 in 16-bit bank
>> number of CFI chips: 1
>> ersize is 10000, ernum is 400
>> Sum of regions (4000000) != total size of set of interleaved chips (800000)
>
> This is the typical error with SST chips when the
> fixup_sst39vf_rev_b() fixup function isn't called.

   It did call the fixup_sst39vf_recv_b() function, so you can see
 >>number of CFI chips: 1
When we take the 1st erase region, we will get the wrong flash size
because of the wrong information(ersize is 10000, ernum is 400).

>
> Could you try and report me which patches you applied and what results
> you have with SST38VF6401 ?

Sorry, my current kernel version is not the latest one. My kernel
version is 2.6.31. I changed the code as your patch.  But i can
confirm that the flash(SST39VF6401B) works fine. But the SST38VF6401
flash couldn't pass the probe. Please see the log below

>>  Erase Region #0: BlockSize 0x10000 bytes, 1024 blocks
>> cif->cfiq->EraseRegionInfo[i] = 10003ff
>>  Erase Region #1: BlockSize 0x10000 bytes, 128 blocks
>> cif->cfiq->EraseRegionInfo[i] = 100007f

I think the information we get from the flash is wrong. So we
shuoldn't take the 1st Erase Region. We can not  get the right
description of the flash in the CFI mode. Maybe they should be moved
to JEDEC mode.

> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>


From joern at logfs.org  Fri Oct 22 04:39:52 2010
From: joern at logfs.org (=?utf-8?B?SsO2cm4=?= Engel)
Date: Fri, 22 Oct 2010 10:39:52 +0200
Subject: [PATCH] drivers/mtd/devices/phram.c: Use KBUILD_MODNAME
In-Reply-To: <1287657452.2932.15.camel@localhost>
References: <1287596362.1813.205.camel@Joe-Laptop>
	<1287657452.2932.15.camel@localhost>
Message-ID: <20101022083952.GJ16783@logfs.org>

On Thu, 21 October 2010 13:37:32 +0300, Artem Bityutskiy wrote:
> On Wed, 2010-10-20 at 10:39 -0700, Joe Perches wrote:
> > Use the more standard #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > No change in output strings.
> > 
> > Signed-off-by: Joe Perches <joe at perches.com>
> 
> Pushed to l2-mtd-2.6.git, thanks.

Fine with me. (aka Acked-By:)

J?rn

-- 
"Error protection by error detection and correction."
-- from a university class


From leiwen at marvell.com  Fri Oct 22 06:14:38 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:38 +0800
Subject: [PATCH V3 0/6] pxa3xx_nand update series set
Message-ID: <1287742484-4276-1-git-send-email-leiwen@marvell.com>

[PATCH V3 1/6] pxa3xx_nand: make scan procedure more clear
[PATCH V3 2/6] pxa3xx_nand: rework irq logic 
[PATCH V3 3/6] pxa3xx_nand: discard wait_for_event,write_cmd,__readid function
[PATCH V3 4/6] pxa3xx_nand: unify prepare command
[PATCH V3 5/6] pxa3xx_nand: mtd scan id process could be defined by driver itself
[PATCH V3 6/6] pxa3xx_nand: clean the keep configure code


From leiwen at marvell.com  Fri Oct 22 06:14:39 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:39 +0800
Subject: [PATCH V3 1/6] pxa3xx_nand: make scan procedure more clear
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-2-git-send-email-leiwen@marvell.com>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/nand/pxa3xx_nand.c |   98 ++++++++++++++++++++++------------------
 1 files changed, 54 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 17f8518..aff28dc 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -126,6 +126,7 @@ struct pxa3xx_nand_info {
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
+	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -1044,34 +1045,26 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
 	this->chip_delay = 25;
 }
 
-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa3xx_nand_info *info;
-	struct nand_chip *this;
 	struct mtd_info *mtd;
 	struct resource *r;
-	int ret = 0, irq;
-
-	pdata = pdev->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -ENODEV;
-	}
+	int ret, irq;
 
 	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
 			GFP_KERNEL);
 	if (!mtd) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return -ENOMEM;
+		return NULL;
 	}
 
 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
 	info->pdev = pdev;
 
-	this = &info->nand_chip;
 	mtd->priv = info;
+	info->mtd = mtd;
 	mtd->owner = THIS_MODULE;
 
 	info->clk = clk_get(&pdev->dev, NULL);
@@ -1149,31 +1142,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 	}
 
 	pxa3xx_nand_init_mtd(mtd, info);
+	platform_set_drvdata(pdev, info);
 
-	platform_set_drvdata(pdev, mtd);
-
-	if (nand_scan(mtd, 1)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
-		ret = -ENXIO;
-		goto fail_free_irq;
-	}
-
-#ifdef CONFIG_MTD_PARTITIONS
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
-
-		nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
-		if (nr_parts)
-			return add_mtd_partitions(mtd, parts, nr_parts);
-	}
-
-	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-#else
-	return 0;
-#endif
+	return info;
 
 fail_free_irq:
 	free_irq(irq, info);
@@ -1193,13 +1164,13 @@ fail_put_clk:
 	clk_put(info->clk);
 fail_free_mtd:
 	kfree(mtd);
-	return ret;
+	return NULL;
 }
 
 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 	struct resource *r;
 	int irq;
 
@@ -1230,11 +1201,50 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+	struct pxa3xx_nand_platform_data *pdata;
+	struct pxa3xx_nand_info *info;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -ENODEV;
+	}
+
+	info = alloc_nand_resource(pdev);
+	if (info == NULL)
+		return -ENOMEM;
+
+	if (nand_scan(info->mtd, 1)) {
+		dev_err(&pdev->dev, "failed to scan nand\n");
+		pxa3xx_nand_remove(pdev);
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	if (mtd_has_cmdlinepart()) {
+		static const char *probes[] = { "cmdlinepart", NULL };
+		struct mtd_partition *parts;
+		int nr_parts;
+
+		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+		if (nr_parts)
+			return add_mtd_partitions(mtd, parts, nr_parts);
+	}
+
+	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+#else
+	return 0;
+#endif
+}
+
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 
 	if (info->state != STATE_READY) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
@@ -1246,8 +1256,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 
 	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
 	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
-- 
1.7.0.4



From leiwen at marvell.com  Fri Oct 22 06:14:41 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:41 +0800
Subject: [PATCH V3 3/6] pxa3xx_nand: discard wait_for_event, write_cmd,
	__readid function
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-4-git-send-email-leiwen@marvell.com>

Since we have rework the irq process, we don't need additional
delay in wait_for_event. Also write_cmd and __readid is also
discarded for the same reason.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/nand/pxa3xx_nand.c |   77 +---------------------------------------
 1 files changed, 1 insertions(+), 76 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dc24000..a7f623f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -258,25 +258,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-#define WAIT_EVENT_TIMEOUT	10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	int timeout = WAIT_EVENT_TIMEOUT;
-	uint32_t ndsr;
-
-	while (timeout--) {
-		ndsr = nand_readl(info, NDSR) & NDSR_MASK;
-		if (ndsr & event) {
-			nand_writel(info, NDSR, ndsr);
-			return 0;
-		}
-		udelay(10);
-	}
-
-	return -ETIMEDOUT;
-}
-
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -414,35 +395,6 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 	nand_writel(info, NDCR, ndcr | int_mask);
 }
 
-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
-{
-	uint32_t ndcr;
-
-	/* clear status bits and run */
-	nand_writel(info, NDSR, NDSR_MASK);
-
-	ndcr = info->reg_ndcr;
-
-	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
-	ndcr |= NDCR_ND_RUN;
-
-	nand_writel(info, NDCR, ndcr);
-
-	if (wait_for_event(info, NDSR_WRCMDREQ)) {
-		printk(KERN_ERR "timed out writing command\n");
-		return -ETIMEDOUT;
-	}
-
-	nand_writel(info, NDCB0, info->ndcb0);
-	nand_writel(info, NDCB0, info->ndcb1);
-	nand_writel(info, NDCB0, info->ndcb2);
-	return 0;
-}
-
 static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
 	switch (info->state) {
@@ -789,33 +741,6 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
 	return 0;
 }
 
-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	uint32_t ndcr;
-	uint8_t  id_buff[8];
-
-	prepare_other_cmd(info, cmdset->read_id);
-
-	/* Send command */
-	if (write_cmd(info))
-		goto fail_timeout;
-
-	/* Wait for CMDDM(command done successfully) */
-	if (wait_for_event(info, NDSR_RDDREQ))
-		goto fail_timeout;
-
-	__raw_readsl(info->mmio_base + NDDB, id_buff, 2);
-	*id = id_buff[0] | (id_buff[1] << 8);
-	return 0;
-
-fail_timeout:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
@@ -868,7 +793,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 
 	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to __readid */
+	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;
 
-- 
1.7.0.4



From leiwen at marvell.com  Fri Oct 22 06:14:42 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:42 +0800
Subject: [PATCH V3 4/6] pxa3xx_nand: unify prepare command
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-5-git-send-email-leiwen@marvell.com>

Make the interface simpler which could make both debug
and enhancement easier.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/nand/pxa3xx_nand.c |  260 +++++++++++++++++++++-------------------
 1 files changed, 134 insertions(+), 126 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index a7f623f..0ca2b88 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -28,6 +28,7 @@
 
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
 #define NAND_STOP_DELAY		(2 * HZ/50)
+#define PAGE_CHUNK_SIZE		(2048)
 
 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -77,6 +78,7 @@
 #define NDSR_RDDREQ		(0x1 << 1)
 #define NDSR_WRCMDREQ		(0x1)
 
+#define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
@@ -319,66 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
 	nand_writel(info, NDSR, NDSR_MASK);
 }
 
-static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-		uint16_t cmd, int column, int page_addr)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	pxa3xx_set_datasize(info);
-
-	/* generate values for NDCBx registers */
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
-	info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
-	if (info->col_addr_cycles == 2) {
-		/* large block, 2 cycles for column address
-		 * row address starts from 3rd cycle
-		 */
-		info->ndcb1 |= page_addr << 16;
-		if (info->row_addr_cycles == 3)
-			info->ndcb2 = (page_addr >> 16) & 0xff;
-	} else
-		/* small block, 1 cycles for column address
-		 * row address starts from 2nd cycle
-		 */
-		info->ndcb1 = page_addr << 8;
-
-	if (cmd == cmdset->program)
-		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-}
-
-static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
-			uint16_t cmd, int page_addr)
-{
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
-	info->ndcb1 = page_addr;
-	info->ndcb2 = 0;
-}
-
-static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
-
-	info->oob_size = 0;
-	if (cmd == cmdset->read_id) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1);
-		info->data_size = 8;
-	} else if (cmd == cmdset->read_status) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(4);
-		info->data_size = 8;
-	} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
-		   cmd == cmdset->unlock) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(5);
-	} else
-		BUG();
-}
-
 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 {
 	uint32_t ndcr;
@@ -529,94 +471,164 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
 	return 1;
 }
 
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-				int column, int page_addr)
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+		uint16_t column, int page_addr)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	int ret, exec_cmd = 0;
+	uint16_t cmd;
+	int addr_cycle, exec_cmd, ndcb0;
+	struct mtd_info *mtd = info->mtd;
+
+	ndcb0 = 0;
+	addr_cycle = 0;
+	exec_cmd = 1;
 
-	info->use_dma = (use_dma) ? 1 : 0;
-	info->use_ecc = 0;
-	info->data_size = 0;
-	info->state = 0;
+	/* reset data and oob column point to handle data */
+	info->buf_start		= 0;
+	info->buf_count		= 0;
+	info->oob_size		= 0;
+	info->use_ecc		= 0;
 
 	switch (command) {
+	case NAND_CMD_READ0:
+	case NAND_CMD_PAGEPROG:
+		info->use_ecc = 1;
 	case NAND_CMD_READOOB:
-		/* disable HW ECC to get all the OOB data */
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		info->buf_start = mtd->writesize + column;
-		memset(info->data_buff, 0xFF, info->buf_count);
-
-		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
-		/* We only are OOB, so if the data has error, does not matter */
-		if (info->retcode == ERR_DBERR)
-			info->retcode = ERR_NONE;
-
-		exec_cmd = 1;
+		pxa3xx_set_datasize(info);
+		break;
+	case NAND_CMD_SEQIN:
+		exec_cmd = 0;
+		break;
+	default:
+		info->ndcb1 = 0;
+		info->ndcb2 = 0;
 		break;
+	}
+
+	info->ndcb0 = ndcb0;
+	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+		     + info->col_addr_cycles);
 
+	switch (command) {
+	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		info->use_ecc = 1;
-		info->retcode = ERR_NONE;
-		info->buf_start = column;
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		cmd  = info->cmdset->read1;
+		if (command == NAND_CMD_READOOB)
+			info->buf_start = mtd->writesize + column;
+		else
+			info->buf_start = column;
 
-		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
-		if (info->retcode == ERR_DBERR) {
-			/* for blank page (all 0xff), HW will calculate its ECC as
-			 * 0, which is different from the ECC information within
-			 * OOB, ignore such double bit errors
-			 */
-			if (is_buf_blank(info->data_buff, mtd->writesize))
-				info->retcode = ERR_NONE;
-		}
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| addr_cycle
+					| (cmd & NDCB0_CMD1_MASK);
+		else
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| NDCB0_DBC
+					| addr_cycle
+					| cmd;
 
-		exec_cmd = 1;
-		break;
 	case NAND_CMD_SEQIN:
-		info->buf_start = column;
+		/* small page addr setting */
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+					| (column & 0xFF);
+
+			info->ndcb2 = 0;
+		}
+		else {
+			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+					| (column & 0xFFFF);
+
+			if (page_addr & 0xFF0000)
+				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+			else
+				info->ndcb2 = 0;
+		}
+
 		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xff, info->buf_count);
+		memset(info->data_buff, 0xFF, info->buf_count);
 
-		/* save column/page_addr for next CMD_PAGEPROG */
-		info->seqin_column = column;
-		info->seqin_page_addr = page_addr;
 		break;
+
 	case NAND_CMD_PAGEPROG:
-		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
+		if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
+			exec_cmd = 0;
+			break;
+		}
 
-		prepare_read_prog_cmd(info, cmdset->program,
-				info->seqin_column, info->seqin_page_addr);
-		exec_cmd = 1;
-		break;
-	case NAND_CMD_ERASE1:
-		prepare_erase_cmd(info, cmdset->erase, page_addr);
-		exec_cmd = 1;
-		break;
-	case NAND_CMD_ERASE2:
+		cmd = info->cmdset->program;
+		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+				| NDCB0_AUTO_RS
+				| NDCB0_ST_ROW_EN
+				| NDCB0_DBC
+				| cmd
+				| addr_cycle;
 		break;
+
 	case NAND_CMD_READID:
+		cmd = info->cmdset->read_id;
+		info->buf_count = info->read_id_bytes;
+		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+
+		info->data_size = 8;
+		break;
 	case NAND_CMD_STATUS:
-		info->use_dma = 0;	/* force PIO read */
-		info->buf_start = 0;
-		info->buf_count = (command == NAND_CMD_READID) ?
-				info->read_id_bytes : 1;
-
-		prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-				cmdset->read_id : cmdset->read_status);
-		exec_cmd = 1;
+		cmd = info->cmdset->read_status;
+		info->buf_count = 1;
+		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+
+		info->data_size = 8;
+		break;
+
+	case NAND_CMD_ERASE1:
+		cmd = info->cmdset->erase;
+		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+				| NDCB0_AUTO_RS
+				| NDCB0_ADDR_CYC(3)
+				| NDCB0_DBC
+				| cmd;
+		info->ndcb1 = page_addr;
+		info->ndcb2 = 0;
+
 		break;
 	case NAND_CMD_RESET:
-		prepare_other_cmd(info, cmdset->reset);
-		exec_cmd = 1;
+		cmd = info->cmdset->reset;
+		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+				| cmd;
+
+		break;
+
+	case NAND_CMD_ERASE2:
+		exec_cmd = 0;
 		break;
+
 	default:
-		printk(KERN_ERR "non-supported command.\n");
+		exec_cmd = 0;
+		printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
 		break;
 	}
 
+	return exec_cmd;
+}
+
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+		int column, int page_addr)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	int ret, exec_cmd;
+
+	/* if this is a x16 device ,then convert the input
+	 * "byte" address into a "word" address appropriate
+	 * for indexing a word-oriented device
+	 */
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
 		pxa3xx_nand_start(info);
@@ -629,10 +641,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			pxa3xx_nand_stop(info);
 		}
 		info->state = STATE_IDLE;
-		if (info->retcode == ERR_DBERR) {
-			printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-			info->retcode = ERR_NONE;
-		}
 	}
 }
 
-- 
1.7.0.4



From leiwen at marvell.com  Fri Oct 22 06:14:40 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:40 +0800
Subject: [PATCH V3 2/6] pxa3xx_nand: rework irq logic
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-3-git-send-email-leiwen@marvell.com>

Enable all irq when we start the nand controller, and
put all the transaction logic in the pxa3xx_nand_irq.

By doing this way, we could dramatically increase the
performance by avoid unnecessary delay.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/nand/pxa3xx_nand.c |  319 +++++++++++++++++++---------------------
 1 files changed, 153 insertions(+), 166 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index aff28dc..dc24000 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -27,6 +27,7 @@
 #include <plat/pxa3xx_nand.h>
 
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
+#define NAND_STOP_DELAY		(2 * HZ/50)
 
 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -52,16 +53,18 @@
 #define NDCR_ND_MODE		(0x3 << 21)
 #define NDCR_NAND_MODE   	(0x0)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
-#define NDCR_CLR_ECC		(0x1 << 19)
+#define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)
 
 #define NDCR_RA_START		(0x1 << 15)
 #define NDCR_PG_PER_BLK		(0x1 << 14)
 #define NDCR_ND_ARB_EN		(0x1 << 12)
+#define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK		(0xfff)
-#define NDSR_RDY		(0x1 << 11)
+#define NDSR_RDY                (0x1 << 12)
+#define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED		(0x1 << 10)
 #define NDSR_CS1_PAGED		(0x1 << 9)
 #define NDSR_CS0_CMDD		(0x1 << 8)
@@ -104,13 +107,15 @@ enum {
 };
 
 enum {
-	STATE_READY	= 0,
+	STATE_IDLE = 0,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
 	STATE_DMA_DONE,
 	STATE_PIO_READING,
 	STATE_PIO_WRITING,
+	STATE_CMD_DONE,
+	STATE_READY,
 };
 
 struct pxa3xx_nand_info {
@@ -292,7 +297,48 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 	}
 }
 
-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
+/**
+ * NOTE: it is a must to set ND_RUN firstly, then write
+ * command buffer, otherwise, it does not work.
+ * We enable all the interrupt at the same time, and
+ * let pxa3xx_nand_irq to handle all logic.
+ */
+static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
+{
+	uint32_t ndcr;
+
+	ndcr = info->reg_ndcr;
+	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
+	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
+	ndcr |= NDCR_ND_RUN;
+
+	/* clear status bits and run */
+	nand_writel(info, NDCR, 0);
+	nand_writel(info, NDSR, NDSR_MASK);
+	nand_writel(info, NDCR, ndcr);
+}
+
+static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
+{
+	uint32_t ndcr;
+	int timeout = NAND_STOP_DELAY;
+
+	/* wait RUN bit in NDCR become 0 */
+	ndcr = nand_readl(info, NDCR);
+	while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0)) {
+		ndcr = nand_readl(info, NDCR);
+		udelay(1);
+	}
+
+	if (timeout <= 0) {
+		ndcr &= ~NDCR_ND_RUN;
+		nand_writel(info, NDCR, ndcr);
+	}
+	/* clear status bits */
+	nand_writel(info, NDSR, NDSR_MASK);
+}
+
+static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
 		uint16_t cmd, int column, int page_addr)
 {
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
@@ -319,21 +365,18 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
 
 	if (cmd == cmdset->program)
 		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-
-	return 0;
 }
 
-static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
+static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
 			uint16_t cmd, int page_addr)
 {
 	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
 	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
 	info->ndcb1 = page_addr;
 	info->ndcb2 = 0;
-	return 0;
 }
 
-static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
+static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 {
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
 
@@ -343,7 +386,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 
 	info->oob_size = 0;
 	if (cmd == cmdset->read_id) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(3);
+		info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1);
 		info->data_size = 8;
 	} else if (cmd == cmdset->read_status) {
 		info->ndcb0 |= NDCB0_CMD_TYPE(4);
@@ -352,9 +395,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 		   cmd == cmdset->unlock) {
 		info->ndcb0 |= NDCB0_CMD_TYPE(5);
 	} else
-		return -EINVAL;
-
-	return 0;
+		BUG();
 }
 
 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
@@ -402,10 +443,8 @@ static int write_cmd(struct pxa3xx_nand_info *info)
 	return 0;
 }
 
-static int handle_data_pio(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
 	switch (info->state) {
 	case STATE_PIO_WRITING:
 		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
@@ -413,14 +452,6 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 		if (info->oob_size > 0)
 			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
 					DIV_ROUND_UP(info->oob_size, 4));
-
-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-
-		ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-		if (!ret) {
-			printk(KERN_ERR "program command time out\n");
-			return -1;
-		}
 		break;
 	case STATE_PIO_READING:
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
@@ -432,14 +463,11 @@ static int handle_data_pio(struct pxa3xx_nand_info *info)
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
 				info->state);
-		return -EINVAL;
+		BUG();
 	}
-
-	info->state = STATE_READY;
-	return 0;
 }
 
-static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+static void start_data_dma(struct pxa3xx_nand_info *info)
 {
 	struct pxa_dma_desc *desc = info->data_desc;
 	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
@@ -447,14 +475,21 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
 
-	if (dir_out) {
+	switch (info->state) {
+	case STATE_DMA_WRITING:
 		desc->dsadr = info->data_buff_phys;
 		desc->dtadr = info->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
-	} else {
+		break;
+	case STATE_DMA_READING:
 		desc->dtadr = info->data_buff_phys;
 		desc->dsadr = info->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+		break;
+	default:
+		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+				info->state);
+		BUG();
 	}
 
 	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
@@ -472,93 +507,60 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data)
 
 	if (dcsr & DCSR_BUSERR) {
 		info->retcode = ERR_DMABUSERR;
-		complete(&info->cmd_complete);
 	}
 
-	if (info->state == STATE_DMA_WRITING) {
-		info->state = STATE_DMA_DONE;
-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-	} else {
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
-	}
+	info->state = STATE_DMA_DONE;
+	enable_int(info, NDCR_INT_MASK);
+	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }
 
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
-	unsigned int status;
+	unsigned int status, is_completed = 0;
 
 	status = nand_readl(info, NDSR);
 
-	if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) {
-		if (status & NDSR_DBERR)
-			info->retcode = ERR_DBERR;
-		else if (status & NDSR_SBERR)
-			info->retcode = ERR_SBERR;
-
-		disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
-		if (info->use_dma) {
-			info->state = STATE_DMA_READING;
-			start_data_dma(info, 0);
-		} else {
-			info->state = STATE_PIO_READING;
-			complete(&info->cmd_complete);
-		}
-	} else if (status & NDSR_WRDREQ) {
-		disable_int(info, NDSR_WRDREQ);
+	if (status & NDSR_DBERR)
+		info->retcode = ERR_DBERR;
+	if (status & NDSR_SBERR)
+		info->retcode = ERR_SBERR;
+	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
+		/* whether use dma to transfer data */
 		if (info->use_dma) {
-			info->state = STATE_DMA_WRITING;
-			start_data_dma(info, 1);
+			disable_int(info, NDCR_INT_MASK);
+			info->state = (status & NDSR_RDDREQ) ?
+				      STATE_DMA_READING : STATE_DMA_WRITING;
+			start_data_dma(info);
+			goto NORMAL_IRQ_EXIT;
 		} else {
-			info->state = STATE_PIO_WRITING;
-			complete(&info->cmd_complete);
+			info->state = (status & NDSR_RDDREQ) ?
+				      STATE_PIO_READING : STATE_PIO_WRITING;
+			handle_data_pio(info);
 		}
-	} else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
-		if (status & NDSR_CS0_BBD)
-			info->retcode = ERR_BBERR;
-
-		disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
 	}
-	nand_writel(info, NDSR, status);
-	return IRQ_HANDLED;
-}
-
-static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	uint32_t ndcr;
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
-	if (write_cmd(info)) {
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_CS0_CMDD) {
+		info->state = STATE_CMD_DONE;
+		is_completed = 1;
 	}
+	if (status & NDSR_FLASH_RDY)
+		info->state = STATE_READY;
 
-	info->state = STATE_CMD_HANDLE;
-
-	enable_int(info, event);
-
-	ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-	if (!ret) {
-		printk(KERN_ERR "command execution timed out\n");
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_WRCMDREQ) {
+		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		status &= ~NDSR_WRCMDREQ;
+		info->state = STATE_CMD_HANDLE;
+		nand_writel(info, NDCB0, info->ndcb0);
+		nand_writel(info, NDCB0, info->ndcb1);
+		nand_writel(info, NDCB0, info->ndcb2);
 	}
 
-	if (info->use_dma == 0 && info->data_size > 0)
-		if (handle_data_pio(info))
-			goto fail_stop;
-
-	return 0;
-
-fail_stop:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
+	/* clear NDSR to let the controller exit the IRQ */
+	nand_writel(info, NDSR, status);
+	if (is_completed)
+		complete(&info->cmd_complete);
+NORMAL_IRQ_EXIT:
+	return IRQ_HANDLED;
 }
 
 static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
@@ -580,14 +582,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
 	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	int ret;
+	int ret, exec_cmd = 0;
 
 	info->use_dma = (use_dma) ? 1 : 0;
 	info->use_ecc = 0;
 	info->data_size = 0;
-	info->state = STATE_READY;
-
-	init_completion(&info->cmd_complete);
+	info->state = 0;
 
 	switch (command) {
 	case NAND_CMD_READOOB:
@@ -596,14 +596,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		info->buf_start = mtd->writesize + column;
 		memset(info->data_buff, 0xFF, info->buf_count);
 
-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
+		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
 		/* We only are OOB, so if the data has error, does not matter */
 		if (info->retcode == ERR_DBERR)
 			info->retcode = ERR_NONE;
+
+		exec_cmd = 1;
 		break;
 
 	case NAND_CMD_READ0:
@@ -613,11 +611,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		info->buf_count = mtd->writesize + mtd->oobsize;
 		memset(info->data_buff, 0xFF, info->buf_count);
 
-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
+		prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
 		if (info->retcode == ERR_DBERR) {
 			/* for blank page (all 0xff), HW will calculate its ECC as
 			 * 0, which is different from the ECC information within
@@ -626,6 +620,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			if (is_buf_blank(info->data_buff, mtd->writesize))
 				info->retcode = ERR_NONE;
 		}
+
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_SEQIN:
 		info->buf_start = column;
@@ -639,17 +635,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 	case NAND_CMD_PAGEPROG:
 		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
 
-		if (prepare_read_prog_cmd(info, cmdset->program,
-				info->seqin_column, info->seqin_page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
+		prepare_read_prog_cmd(info, cmdset->program,
+				info->seqin_column, info->seqin_page_addr);
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_ERASE1:
-		if (prepare_erase_cmd(info, cmdset->erase, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
+		prepare_erase_cmd(info, cmdset->erase, page_addr);
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_ERASE2:
 		break;
@@ -660,39 +652,35 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		info->buf_count = (command == NAND_CMD_READID) ?
 				info->read_id_bytes : 1;
 
-		if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-				cmdset->read_id : cmdset->read_status))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
+		prepare_other_cmd(info, (command == NAND_CMD_READID) ?
+				cmdset->read_id : cmdset->read_status);
+		exec_cmd = 1;
 		break;
 	case NAND_CMD_RESET:
-		if (prepare_other_cmd(info, cmdset->reset))
-			break;
-
-		ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
-		if (ret == 0) {
-			int timeout = 2;
-			uint32_t ndcr;
-
-			while (timeout--) {
-				if (nand_readl(info, NDSR) & NDSR_RDY)
-					break;
-				msleep(10);
-			}
-
-			ndcr = nand_readl(info, NDCR);
-			nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-		}
+		prepare_other_cmd(info, cmdset->reset);
+		exec_cmd = 1;
 		break;
 	default:
 		printk(KERN_ERR "non-supported command.\n");
 		break;
 	}
 
-	if (info->retcode == ERR_DBERR) {
-		printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-		info->retcode = ERR_NONE;
+	if (exec_cmd) {
+		init_completion(&info->cmd_complete);
+		pxa3xx_nand_start(info);
+
+		ret = wait_for_completion_timeout(&info->cmd_complete,
+				CHIP_DELAY_TIMEOUT);
+		if (!ret) {
+			printk(KERN_ERR "Wait time out!!!\n");
+			/* Stop State Machine for next command cycle */
+			pxa3xx_nand_stop(info);
+		}
+		info->state = STATE_IDLE;
+		if (info->retcode == ERR_DBERR) {
+			printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
+			info->retcode = ERR_NONE;
+		}
 	}
 }
 
@@ -807,10 +795,7 @@ static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
 	uint32_t ndcr;
 	uint8_t  id_buff[8];
 
-	if (prepare_other_cmd(info, cmdset->read_id)) {
-		printk(KERN_ERR "failed to prepare command\n");
-		return -EINVAL;
-	}
+	prepare_other_cmd(info, cmdset->read_id);
 
 	/* Send command */
 	if (write_cmd(info))
@@ -836,7 +821,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
-	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
+	uint32_t ndcr = 0x0; /* enable all interrupts */
 
 	if (f->page_size != 2048 && f->page_size != 512)
 		return -EINVAL;
@@ -887,11 +872,12 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;
 
-	if (__readid(info, &id))
+	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id == 0)
 		return -ENODEV;
 
 	/* Lookup the flash id */
-	id = (id >> 8) & 0xff;		/* device id is byte 2 */
 	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
 		if (id == nand_flash_ids[i].id) {
 			type =  &nand_flash_ids[i];
@@ -935,8 +921,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
 	/* we use default timing to detect id */
 	f = DEFAULT_FLASH_TYPE;
 	pxa3xx_nand_config_flash(info, f);
-	if (__readid(info, &id))
-		goto fail_detect;
+	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
 
 	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
 		/* we first choose the flash definition from platfrom */
@@ -954,7 +940,6 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
 	dev_warn(&info->pdev->dev,
 		 "failed to detect configured nand flash; found %04x instead of\n",
 		 id);
-fail_detect:
 	return -ENODEV;
 }
 
@@ -1176,10 +1161,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, NULL);
 
-	del_mtd_device(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
-	del_mtd_partitions(mtd);
-#endif
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
 		free_irq(irq, info);
@@ -1197,7 +1178,13 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	kfree(mtd);
+	if (mtd) {
+		del_mtd_device(mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+		del_mtd_partitions(mtd);
+#endif
+		kfree(mtd);
+	}
 	return 0;
 }
 
@@ -1231,10 +1218,10 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
 
 		if (nr_parts)
-			return add_mtd_partitions(mtd, parts, nr_parts);
+			return add_mtd_partitions(info->mtd, parts, nr_parts);
 	}
 
-	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
 #else
 	return 0;
 #endif
@@ -1246,7 +1233,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 	struct mtd_info *mtd = info->mtd;
 
-	if (info->state != STATE_READY) {
+	if (info->state) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
 		return -EAGAIN;
 	}
-- 
1.7.0.4



From leiwen at marvell.com  Fri Oct 22 06:14:43 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:43 +0800
Subject: [PATCH V3 5/6] pxa3xx_nand: mtd scan id process could be defined by
	driver itself
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-6-git-send-email-leiwen@marvell.com>

Different NAND driver may require its unique detection. For pxa3xx_nand,
it use its self id database to get the necessary info.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/nand/pxa3xx_nand.c |  258 ++++++++++++++++++++++++++--------------
 1 files changed, 168 insertions(+), 90 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 0ca2b88..b5dc5d7 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -123,6 +123,7 @@ enum {
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
 
+	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 	struct pxa3xx_nand_cmdset *cmdset;
 
@@ -157,6 +158,7 @@ struct pxa3xx_nand_info {
 
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
+	int			is_ready;
 
 	unsigned int		page_size;	/* page size of attached chip */
 	unsigned int		data_size;	/* data size in FIFO */
@@ -223,6 +225,8 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
+static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -437,8 +441,10 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 		info->state = STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY)
+	if (status & NDSR_FLASH_RDY) {
+		info->is_ready = 1;
 		info->state = STATE_READY;
+	}
 
 	if (status & NDSR_WRCMDREQ) {
 		nand_writel(info, NDSR, NDSR_WRCMDREQ);
@@ -487,6 +493,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	info->buf_count		= 0;
 	info->oob_size		= 0;
 	info->use_ecc		= 0;
+	info->is_ready		= 0;
 
 	switch (command) {
 	case NAND_CMD_READ0:
@@ -840,42 +847,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 	return 0;
 }
 
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_platform_data *pdata)
-{
-	const struct pxa3xx_nand_flash *f;
-	uint32_t id = -1;
-	int i;
-
-	if (pdata->keep_config)
-		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
-
-	/* we use default timing to detect id */
-	f = DEFAULT_FLASH_TYPE;
-	pxa3xx_nand_config_flash(info, f);
-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-
-	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
-		/* we first choose the flash definition from platfrom */
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-		if (f->chip_id == id) {
-			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
-			pxa3xx_nand_config_flash(info, f);
-			return 0;
-		}
-	}
-
-	dev_warn(&info->pdev->dev,
-		 "failed to detect configured nand flash; found %04x instead of\n",
-		 id);
-	return -ENODEV;
-}
-
 /* the maximum possible buffer size for large page with OOB data
  * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
  * data buffer and the DMA descriptor
@@ -917,56 +888,152 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 	return 0;
 }
 
-static struct nand_ecclayout hw_smallpage_ecclayout = {
-	.eccbytes = 6,
-	.eccpos = {8, 9, 10, 11, 12, 13 },
-	.oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
 
-static struct nand_ecclayout hw_largepage_ecclayout = {
-	.eccbytes = 24,
-	.eccpos = {
-		40, 41, 42, 43, 44, 45, 46, 47,
-		48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63},
-	.oobfree = { {2, 38} }
-};
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (info->retcode == ERR_SBERR) {
+		switch (info->use_ecc) {
+			case 1:
+				mtd->ecc_stats.corrected ++;
+				break;
+
+			case 0:
+			default:
+				break;
+		}
+	}
+	else if (info->retcode == ERR_DBERR) {
+		int buf_blank;
+
+		buf_blank = is_buf_blank(buf, mtd->writesize);
+		if (!buf_blank)
+			mtd->ecc_stats.failed++;
+	}
+
+	return 0;
+}
+
+static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf)
+{
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page)
+{
+	struct nand_chip *chip = mtd->priv;
+	/* Send commands to erase a block */
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+}
 
-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
-				 struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct nand_chip *this = &info->nand_chip;
-
-	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
-
-	this->waitfunc		= pxa3xx_nand_waitfunc;
-	this->select_chip	= pxa3xx_nand_select_chip;
-	this->dev_ready		= pxa3xx_nand_dev_ready;
-	this->cmdfunc		= pxa3xx_nand_cmdfunc;
-	this->read_word		= pxa3xx_nand_read_word;
-	this->read_byte		= pxa3xx_nand_read_byte;
-	this->read_buf		= pxa3xx_nand_read_buf;
-	this->write_buf		= pxa3xx_nand_write_buf;
-	this->verify_buf	= pxa3xx_nand_verify_buf;
-
-	this->ecc.mode		= NAND_ECC_HW;
-	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= info->page_size;
-
-	if (info->page_size == 2048)
-		this->ecc.layout = &hw_largepage_ecclayout;
+	struct mtd_info *mtd = info->mtd;
+	struct nand_chip *chip = mtd->priv;
+
+	/* use the common timing to make a try */
+	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (info->is_ready)
+		return 1;
 	else
-		this->ecc.layout = &hw_smallpage_ecclayout;
+		return 0;
+}
 
-	this->chip_delay = 25;
+static int pxa3xx_nand_scan(struct mtd_info *mtd)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	const struct pxa3xx_nand_flash *f = NULL;
+	struct nand_chip *chip = mtd->priv;
+	uint32_t id = -1;
+	int i, ret;
+
+	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
+		return 0;
+
+	ret = pxa3xx_nand_sensing(info);
+	if (!ret) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+
+		return -EINVAL;
+	}
+
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id != 0)
+		printk(KERN_INFO "Detect a flash id %x\n", id);
+	else {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+		return -EINVAL;
+	}
+
+	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+		/* find the chip in default list */
+		if (f->chip_id == id) {
+			pxa3xx_nand_config_flash(info, f);
+			mtd->writesize = f->page_size;
+			mtd->writesize_shift = ffs(mtd->writesize) - 1;
+			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+			mtd->oobsize = mtd->writesize / 32;
+			mtd->erasesize = f->page_size * f->page_per_block;
+			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
+
+			mtd->name = mtd_names[0];
+			break;
+		}
+	}
+
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+		return -EINVAL;
+	}
+
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = f->page_size;
+	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
+			  * f->page_size;
+	mtd->size = chip->chipsize;
+
+	/* Calculate the address shift from the page size */
+	chip->page_shift = ffs(mtd->writesize) - 1;
+	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
+	chip->numchips = 1;
+	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
+
+	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+	chip->options |= NAND_NO_AUTOINCR;
+	chip->options |= NAND_NO_READRDY;
+	chip->options |= NAND_USE_FLASH_BBT;
+
+	return nand_scan_tail(mtd);
 }
 
 static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct pxa3xx_nand_info *info;
+	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *r;
 	int ret, irq;
@@ -979,12 +1046,32 @@ static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev
 	}
 
 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
+	chip = (struct nand_chip *)(&mtd[1]);
 	info->pdev = pdev;
-
-	mtd->priv = info;
 	info->mtd = mtd;
+	mtd->priv = info;
 	mtd->owner = THIS_MODULE;
 
+	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+	chip->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
+	chip->ecc.calculate	= pxa3xx_nand_ecc_calculate;
+	chip->ecc.correct	= pxa3xx_nand_ecc_correct;
+	chip->controller        = &info->controller;
+	chip->waitfunc		= pxa3xx_nand_waitfunc;
+	chip->select_chip	= pxa3xx_nand_select_chip;
+	chip->dev_ready		= pxa3xx_nand_dev_ready;
+	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+	chip->read_word		= pxa3xx_nand_read_word;
+	chip->read_byte		= pxa3xx_nand_read_byte;
+	chip->read_buf		= pxa3xx_nand_read_buf;
+	chip->write_buf		= pxa3xx_nand_write_buf;
+	chip->verify_buf	= pxa3xx_nand_verify_buf;
+	chip->erase_cmd		= pxa3xx_nand_erase_cmd;
+	chip->scan_bbt		= nand_default_bbt;
+
+	spin_lock_init(&chip->controller->lock);
+	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1052,21 +1139,12 @@ static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev
 		goto fail_free_buf;
 	}
 
-	ret = pxa3xx_nand_detect_flash(info, pdata);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to detect flash\n");
-		ret = -ENODEV;
-		goto fail_free_irq;
-	}
-
-	pxa3xx_nand_init_mtd(mtd, info);
 	platform_set_drvdata(pdev, info);
 
 	return info;
 
-fail_free_irq:
-	free_irq(irq, info);
 fail_free_buf:
+	free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
 		dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1136,7 +1214,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 	if (info == NULL)
 		return -ENOMEM;
 
-	if (nand_scan(info->mtd, 1)) {
+	if (pxa3xx_nand_scan(info->mtd)) {
 		dev_err(&pdev->dev, "failed to scan nand\n");
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
-- 
1.7.0.4



From leiwen at marvell.com  Fri Oct 22 06:14:44 2010
From: leiwen at marvell.com (Lei Wen)
Date: Fri, 22 Oct 2010 18:14:44 +0800
Subject: [PATCH V3 6/6] pxa3xx_nand: clean the keep configure code
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <1287742484-4276-7-git-send-email-leiwen@marvell.com>

Signed-off-by: Lei Wen <leiwen at marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: Eric Miao <eric.y.miao at gmail.com>
Cc: David Woodhouse <dwmw2 at infradead.org>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    1 +
 drivers/mtd/nand/pxa3xx_nand.c               |  104 +++++++++-----------------
 2 files changed, 36 insertions(+), 69 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 01a8448..0bd4e88 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset {
 };
 
 struct pxa3xx_nand_flash {
+	char		*name;
 	uint32_t	chip_id;
 	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
 	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b5dc5d7..7901bde 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -211,15 +211,15 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-	{      0,   0, 2048,  8,  8,    0, &default_cmdset, &timing[0] },
-	{ 0x46ec,  32,  512, 16, 16, 4096, &default_cmdset, &timing[1] },
-	{ 0xdaec,  64, 2048,  8,  8, 2048, &default_cmdset, &timing[1] },
-	{ 0xd7ec, 128, 4096,  8,  8, 8192, &default_cmdset, &timing[1] },
-	{ 0xa12c,  64, 2048,  8,  8, 1024, &default_cmdset, &timing[2] },
-	{ 0xb12c,  64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
-	{ 0xdc2c,  64, 2048,  8,  8, 4096, &default_cmdset, &timing[2] },
-	{ 0xcc2c,  64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
-	{ 0xba20,  64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
+{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &default_cmdset, &timing[0] },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &default_cmdset, &timing[1] },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &default_cmdset, &timing[1] },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &default_cmdset, &timing[1] },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &default_cmdset, &timing[2] },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &default_cmdset, &timing[2] },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
 };
 
 /* Define a default flash type setting serve as flash detecting only */
@@ -772,7 +772,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 	/* calculate flash information */
 	info->cmdset = f->cmdset;
 	info->page_size = f->page_size;
-	info->oob_buff = info->data_buff + f->page_size;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
@@ -802,44 +801,12 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
 	uint32_t ndcr = nand_readl(info, NDCR);
-	struct nand_flash_dev *type = NULL;
-	uint32_t id = -1, page_per_block, num_blocks;
-	int i;
 
-	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;
 
-	pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
-	if (id == 0)
-		return -ENODEV;
-
-	/* Lookup the flash id */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			type =  &nand_flash_ids[i];
-			break;
-		}
-	}
-
-	if (!type)
-		return -ENODEV;
-
-	/* fill the missing flash information */
-	i = __ffs(page_per_block * info->page_size);
-	num_blocks = type->chipsize << (20 - i);
-
-	/* calculate addressing information */
-	info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
-	if (num_blocks * page_per_block > 65536)
-		info->row_addr_cycles = 3;
-	else
-		info->row_addr_cycles = 2;
-
 	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 	info->cmdset = &default_cmdset;
@@ -951,13 +918,15 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t id = -1;
+	uint64_t chipsize;
 	int i, ret;
 
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
-		return 0;
+		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
 	if (!ret) {
@@ -987,22 +956,11 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 			f = &builtin_flash_types[i - pdata->num_flash + 1];
 
 		/* find the chip in default list */
-		if (f->chip_id == id) {
-			pxa3xx_nand_config_flash(info, f);
-			mtd->writesize = f->page_size;
-			mtd->writesize_shift = ffs(mtd->writesize) - 1;
-			mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
-			mtd->oobsize = mtd->writesize / 32;
-			mtd->erasesize = f->page_size * f->page_per_block;
-			mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
-			mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
-
-			mtd->name = mtd_names[0];
+		if (f->chip_id == id)
 			break;
-		}
 	}
 
-	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
 		kfree(mtd);
 		info->mtd = NULL;
 		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
@@ -1010,20 +968,28 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 		return -EINVAL;
 	}
 
+	pxa3xx_nand_config_flash(info, f);
+	pxa3xx_flash_ids[0].name = f->name;
+	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+	pxa3xx_flash_ids[0].pagesize = f->page_size;
+	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+	pxa3xx_flash_ids[0].options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+KEEP_CONFIG:
+	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+		return -ENODEV;
+	/* calculate addressing information */
+	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	info->oob_buff = info->data_buff + mtd->writesize;
+	if ((mtd->size >> chip->page_shift) > 65536)
+		info->row_addr_cycles = 3;
+	else
+		info->row_addr_cycles = 2;
+	mtd->name = mtd_names[0];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = f->page_size;
-	chip->chipsize 	= (uint64_t)f->num_blocks * f->page_per_block
-			  * f->page_size;
-	mtd->size = chip->chipsize;
-
-	/* Calculate the address shift from the page size */
-	chip->page_shift = ffs(mtd->writesize) - 1;
-	chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
-	chip->numchips = 1;
-	chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
-
-	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
-	chip->options |= NAND_NO_AUTOINCR;
+	chip->ecc.size = mtd->writesize;
+	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16: 0;
 	chip->options |= NAND_NO_READRDY;
 	chip->options |= NAND_USE_FLASH_BBT;
 
-- 
1.7.0.4



From haojian.zhuang at gmail.com  Fri Oct 22 06:15:23 2010
From: haojian.zhuang at gmail.com (Haojian Zhuang)
Date: Fri, 22 Oct 2010 18:15:23 +0800
Subject: [PATCH V3 0/6] pxa3xx_nand update series set
In-Reply-To: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
References: <1287742484-4276-1-git-send-email-leiwen@marvell.com>
Message-ID: <AANLkTikVAU5KAN072O7xp=A3meFTw5AadUSoqbzEGofO@mail.gmail.com>

On Fri, Oct 22, 2010 at 6:14 PM, Lei Wen <leiwen at marvell.com> wrote:
> [PATCH V3 1/6] pxa3xx_nand: make scan procedure more clear
> [PATCH V3 2/6] pxa3xx_nand: rework irq logic
> [PATCH V3 3/6] pxa3xx_nand: discard wait_for_event,write_cmd,__readid function
> [PATCH V3 4/6] pxa3xx_nand: unify prepare command
> [PATCH V3 5/6] pxa3xx_nand: mtd scan id process could be defined by driver itself
> [PATCH V3 6/6] pxa3xx_nand: clean the keep configure code
>

Hi Eric and all,

Patches are refreshed. Please help to review.

Best Regards
Haojian


From glecerf at gmail.com  Fri Oct 22 06:41:40 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 12:41:40 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
	<AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
	<AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>
Message-ID: <AANLkTikG5KWJwm2MFCX+-j2f4JiVTsiG1qsgh4T8aoZQ@mail.gmail.com>

2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>> You didn't applied my latest patch, you would have only 1 erase region
>> if you did.
> ?It was printed by the print_cfi_ident function. And the region
> number is readed from the flash. So there was 2 erase region

OK, my bad :(

The datasheet is really f***ed up.

"Sector Information (y + 1 = Number of sectors; z x 256B = sector size)
y = 2047 + 1 = 2048 sectors (03FFH = 1023)
z = 32 x 256 Bytes = 8 KBytes/sector (0100H = 32)"

03FFH = 1023, so y = 1023 + 1 = 1024 sectors
0100H = 256 (not 32), so z = 256 x 256 = 64 KBytes/sector

I think we should modify the sector size on the fly, i.e. changing
0100h to 0020h (32).

Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
fixup_sst39vf_rev_b() ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From nikai at nikai.net  Fri Oct 22 06:47:24 2010
From: nikai at nikai.net (Nicolas Kaiser)
Date: Fri, 22 Oct 2010 12:47:24 +0200
Subject: [PATCH] block2mtd: dubious assignment
Message-ID: <20101022124724.59eba464@absol.kitzblitz>

When block2mtd_erase fails, a duplicated assignment instantly
changes instr->state from MTD_ERASE_FAILED to MTD_ERASE_DONE.

It looks to me like this might not be intended, or is it?

Signed-off-by: Nicolas Kaiser <nikai at nikai.net>
---
 drivers/mtd/devices/block2mtd.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 9365186..2cf0cc6 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -91,7 +91,6 @@ static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 	} else
 		instr->state = MTD_ERASE_DONE;
 
-	instr->state = MTD_ERASE_DONE;
 	mtd_erase_callback(instr);
 	return err;
 }
-- 
1.7.2.2


From joern at logfs.org  Fri Oct 22 10:34:16 2010
From: joern at logfs.org (=?utf-8?B?SsO2cm4=?= Engel)
Date: Fri, 22 Oct 2010 16:34:16 +0200
Subject: [PATCH] block2mtd: dubious assignment
In-Reply-To: <20101022124724.59eba464@absol.kitzblitz>
References: <20101022124724.59eba464@absol.kitzblitz>
Message-ID: <20101022143416.GA12737@logfs.org>

On Fri, 22 October 2010 12:47:24 +0200, Nicolas Kaiser wrote:
> 
> When block2mtd_erase fails, a duplicated assignment instantly
> changes instr->state from MTD_ERASE_FAILED to MTD_ERASE_DONE.
> 
> It looks to me like this might not be intended, or is it?

Definitely not.  Just proves how well block device errors are tested.

> Signed-off-by: Nicolas Kaiser <nikai at nikai.net>
Acked-By: Joern Engel <joern at logfs.org>

Artem, can I leave this patch to you as well?

J?rn

-- 
Eighty percent of success is showing up.
-- Woody Allen


From matthieu.castet at parrot.com  Fri Oct 22 10:55:42 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Fri, 22 Oct 2010 16:55:42 +0200
Subject: [RFC] write bad block marker even with BBT
Message-ID: <4CC1A5EE.9080605@parrot.com>

Hi,

do you think a patch like that make sense ?

This allow to solve problem where bootloader don't support reading BBT.

We could also add a new flag and do this only if this flag is set.


Matthieu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: btt.diff
Type: text/x-diff
Size: 630 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101022/c58b5ae7/attachment.bin>

From zhangyd6 at gmail.com  Fri Oct 22 11:07:20 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Fri, 22 Oct 2010 23:07:20 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTikG5KWJwm2MFCX+-j2f4JiVTsiG1qsgh4T8aoZQ@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
	<AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
	<AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>
	<AANLkTikG5KWJwm2MFCX+-j2f4JiVTsiG1qsgh4T8aoZQ@mail.gmail.com>
Message-ID: <AANLkTimrtKYLi9trbM7+t7gLqsSTme=_t--7nxdLkmAd@mail.gmail.com>

On Fri, Oct 22, 2010 at 6:41 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>>> You didn't applied my latest patch, you would have only 1 erase region
>>> if you did.
>> ?It was printed by the print_cfi_ident function. And the region
>> number is readed from the flash. So there was 2 erase region
>
> OK, my bad :(
>
> The datasheet is really f***ed up.
>
> "Sector Information (y + 1 = Number of sectors; z x 256B = sector size)
> y = 2047 + 1 = 2048 sectors (03FFH = 1023)
> z = 32 x 256 Bytes = 8 KBytes/sector (0100H = 32)"
>
> 03FFH = 1023, so y = 1023 + 1 = 1024 sectors
> 0100H = 256 (not 32), so z = 256 x 256 = 64 KBytes/sector
>
> I think we should modify the sector size on the fly, i.e. changing
> 0100h to 0020h (32).
>
> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
> fixup_sst39vf_rev_b() ?
>
Hi
  how about this attached patch.

> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-mtd-cfi_cmdset_0002-add-CFI-detection-for-SST-38VF64.patch
Type: application/octet-stream
Size: 1712 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101022/33a163ad/attachment-0001.obj>

From glecerf at gmail.com  Fri Oct 22 11:36:36 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 17:36:36 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTimrtKYLi9trbM7+t7gLqsSTme=_t--7nxdLkmAd@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
	<AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
	<AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>
	<AANLkTikG5KWJwm2MFCX+-j2f4JiVTsiG1qsgh4T8aoZQ@mail.gmail.com>
	<AANLkTimrtKYLi9trbM7+t7gLqsSTme=_t--7nxdLkmAd@mail.gmail.com>
Message-ID: <AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com>

2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
>> fixup_sst39vf_rev_b() ?
>>
> Hi
> ?how about this attached patch.

If it works for you, I'll send a patch series for SST 39VF640xB and
38VF640x, because both chips needs 0x50 as erase command.

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From glecerf at gmail.com  Fri Oct 22 11:40:15 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 17:40:15 +0200
Subject: [PATCH 1/4] mtd: cfi_util: add support for switching SST 39VF640xB
	chips into QRY mode
Message-ID: <20101022154015.11097.94660.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_util.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index e503b2c..360525c 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
 	cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
 	if (cfi_qry_present(map, base, cfi))
 		return 1;
+	/* SST 39VF640xB */
+	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+	if (cfi_qry_present(map, base, cfi))
+		return 1;
 	/* QRY not found */
 	return 0;
 }



From glecerf at gmail.com  Fri Oct 22 11:40:20 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 17:40:20 +0200
Subject: [PATCH 2/4] mtd: cfi_cmdset_0002: make sector erase command variable
In-Reply-To: <20101022154015.11097.94660.stgit@dev.siriade.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
Message-ID: <20101022154020.11097.4024.stgit@dev.siriade.com>

Some old SST chips use 0x50 as sector erase command, instead
of 0x30. Make this value variable to handle such chips.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 3e6c47b..209928b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -78,6 +78,7 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = {
 	.module		= THIS_MODULE
 };
 
+static map_word sector_erase_cmd = CMD(0x30);
 
 /* #define DEBUG_CFI_FEATURES */
 
@@ -674,7 +675,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 				 * there was an error (so leave the erase
 				 * routine to recover from it) or we trying to
 				 * use the erase-in-progress sector. */
-				map_write(map, CMD(0x30), chip->in_progress_block_addr);
+				map_write(map, sector_erase_cmd, chip->in_progress_block_addr);
 				chip->state = FL_ERASING;
 				chip->oldstate = FL_READY;
 				printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
@@ -727,7 +728,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 	switch(chip->oldstate) {
 	case FL_ERASING:
 		chip->state = chip->oldstate;
-		map_write(map, CMD(0x30), chip->in_progress_block_addr);
+		map_write(map, sector_erase_cmd, chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -870,7 +871,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
 			local_irq_disable();
 
 			/* Resume the write or erase operation */
-			map_write(map, CMD(0x30), adr);
+			map_write(map, sector_erase_cmd, adr);
 			chip->state = oldstate;
 			start = xip_currtime();
 		} else if (usec >= 1000000/HZ) {
@@ -1675,7 +1676,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	map_write(map, CMD(0x30), adr);
+	map_write(map, sector_erase_cmd, adr);
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;



From glecerf at gmail.com  Fri Oct 22 11:40:25 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 17:40:25 +0200
Subject: [PATCH 3/4] mtd: cfi_cmdset_0002: use 0x50 erase command for SST
	39VFxxxxB chips
In-Reply-To: <20101022154015.11097.94660.stgit@dev.siriade.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
Message-ID: <20101022154025.11097.94378.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 209928b..a359967 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -292,6 +292,8 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 
 	cfi->addr_unlock1 = 0x555;
 	cfi->addr_unlock2 = 0x2AA;
+
+	sector_erase_cmd = CMD(0x50);
 }
 
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)



From glecerf at gmail.com  Fri Oct 22 11:40:30 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 22 Oct 2010 17:40:30 +0200
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x
	chips
In-Reply-To: <20101022154015.11097.94660.stgit@dev.siriade.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
Message-ID: <20101022154030.11097.40767.stgit@dev.siriade.com>

Add support for SST38VF640x chips in CFI mode.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index a359967..0248253 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -296,6 +296,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 	sector_erase_cmd = CMD(0x50);
 }
 
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	fixup_sst39vf_rev_b(mtd, param);
+
+	/*
+	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
+	 * it should report a size of 8KBytes (0x0020 *256).
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);
+}
+
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
 {
 	struct map_info *map = mtd->priv;
@@ -347,6 +362,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
 	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+	{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
+	{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
+	{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
+	{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif



From zhangyd6 at gmail.com  Fri Oct 22 11:42:39 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Fri, 22 Oct 2010 23:42:39 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<20101016100744.GA10815@pengutronix.de>
	<AANLkTikOKx7hhF9jffRF+HvfwYFDghZAzNBgO-pZpAFv@mail.gmail.com>
	<20101016131752.GA2676@pengutronix.de>
	<AANLkTim+RBZRsYFyqXRD65tPw69s3rKogEnBFBQr4E5q@mail.gmail.com>
	<20101018114104.GC15440@pengutronix.de>
	<AANLkTimcpMb6-VykL0jSsocVF4z19TLMUi4c6dvvbNtF@mail.gmail.com>
	<AANLkTi=jNvWZe-bED0fZa-XbvoLmpu7VcFN7nUN=4Tru@mail.gmail.com>
	<AANLkTinLTW25faUTBfKBVcpFXFrtv1UhWWDN9Dgm1jOH@mail.gmail.com>
	<AANLkTiknoWR_v-TfV5M5ZwsV3Lsk=EDDD185kXp4B96V@mail.gmail.com>
	<AANLkTin-4fGYzD8a9rDp9M7YEk1y7JbXmZVLjA=3iU3Q@mail.gmail.com>
	<AANLkTimwhvNmfz5rVjzCTc5_GaNzCg185v+NLD6bLgno@mail.gmail.com>
	<AANLkTinjcF_4wDGXN+Jg43Pjq=iM++1YQ9+evHrgxPaa@mail.gmail.com>
	<AANLkTinr5E2E4Nth_-XybNPKfHnrgSFPWtVqxkMdQa-Y@mail.gmail.com>
	<AANLkTi=NKDPhdoDYE0ZdM2tuqWdFBNbui1AHZw_wXx97@mail.gmail.com>
	<AANLkTikG5KWJwm2MFCX+-j2f4JiVTsiG1qsgh4T8aoZQ@mail.gmail.com>
	<AANLkTimrtKYLi9trbM7+t7gLqsSTme=_t--7nxdLkmAd@mail.gmail.com>
	<AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com>
Message-ID: <AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com>

On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
>>> fixup_sst39vf_rev_b() ?
>>>
>> Hi
>> ?how about this attached patch.
>
> If it works for you, I'll send a patch series for SST 39VF640xB and
> 38VF640x, because both chips needs 0x50 as erase command.

Sorry, i cannot test it right now.  I will sent the result as soon as i can.
>
> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>


From dedekind1 at gmail.com  Fri Oct 22 12:13:50 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 22 Oct 2010 19:13:50 +0300
Subject: [PATCH] block2mtd: dubious assignment
In-Reply-To: <20101022143416.GA12737@logfs.org>
References: <20101022124724.59eba464@absol.kitzblitz>
	<20101022143416.GA12737@logfs.org>
Message-ID: <1287764030.7480.1.camel@brekeke>

On Fri, 2010-10-22 at 16:34 +0200, J?rn Engel wrote:
> On Fri, 22 October 2010 12:47:24 +0200, Nicolas Kaiser wrote:
> > 
> > When block2mtd_erase fails, a duplicated assignment instantly
> > changes instr->state from MTD_ERASE_FAILED to MTD_ERASE_DONE.
> > 
> > It looks to me like this might not be intended, or is it?
> 
> Definitely not.  Just proves how well block device errors are tested.
> 
> > Signed-off-by: Nicolas Kaiser <nikai at nikai.net>
> Acked-By: Joern Engel <joern at logfs.org>
> 
> Artem, can I leave this patch to you as well?

Yes, I'll put it to my l2 tree of course, thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From greg at kroah.com  Fri Oct 22 11:54:16 2010
From: greg at kroah.com (Greg KH)
Date: Fri, 22 Oct 2010 08:54:16 -0700
Subject: [stable] [Uclinux-dist-devel] [PATCH] mtd: Blackfin NFC: fix
	build error after nand_scan_ident() change
In-Reply-To: <AANLkTiktR-zNsv4KrnOBh3PxXZTHa6UypzqnwSBpE1=R@mail.gmail.com>
References: <1282974300-11664-1-git-send-email-vapier@gentoo.org>
	<AANLkTiktR-zNsv4KrnOBh3PxXZTHa6UypzqnwSBpE1=R@mail.gmail.com>
Message-ID: <20101022155416.GA18595@kroah.com>

On Sat, Oct 16, 2010 at 05:14:53AM -0400, Mike Frysinger wrote:
> stable team: could you pick this up for 2.6.35.x ?
> 
> it has been merged in mainline as eac15a429a27cb74115daaf4c1127c5e854d50e4

But it doesn't apply at all to .35-stable.  There is no call to
nand_scan_ident() in that file in the .35 tree.

So, no, sorry, I can't apply it :)

thanks,

greg k-h


From fabio.giovagnini at aurion-tech.com  Fri Oct 22 13:50:56 2010
From: fabio.giovagnini at aurion-tech.com (Fabio Giovagnini)
Date: Fri, 22 Oct 2010 19:50:56 +0200
Subject: [Help] SST39VF6401B Support
In-Reply-To: <AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com>
	<AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com>
Message-ID: <201010221950.57594.fabio.giovagnini@aurion-tech.com>

Hi Guys,
As Gullelm remeber for sure, I used the jedec probe for such a flash in a very 
old 2.6 kernel.

Now I'm migrating to the newets one kernel.
Do you tell me how the kernel will be updated with the last mtd stuff 
developed; or in place of it how to patch a standard kernel?

Thanks a  lot and sorry for my question if it is improper


In data venerd? 22 ottobre 2010 17:42:39, yidong zhang ha scritto:
: > On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com> 
wrote:
> > 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
> >>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
> >>> fixup_sst39vf_rev_b() ?
> >> 
> >> Hi
> >>  how about this attached patch.
> > 
> > If it works for you, I'll send a patch series for SST 39VF640xB and
> > 38VF640x, because both chips needs 0x50 as erase command.
> 
> Sorry, i cannot test it right now.  I will sent the result as soon as i
> can.
> 
> > --
> > Guillaume LECERF
> > GeeXboX developer - www.geexbox.org
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Cell. +39.335.83.50.919
www.aurion-tech.com


From vapier at gentoo.org  Fri Oct 22 15:42:09 2010
From: vapier at gentoo.org (Mike Frysinger)
Date: Fri, 22 Oct 2010 15:42:09 -0400
Subject: [Uclinux-dist-devel] [stable] [PATCH] mtd: Blackfin NFC: fix
	build error after nand_scan_ident() change
In-Reply-To: <20101022155416.GA18595@kroah.com>
References: <1282974300-11664-1-git-send-email-vapier@gentoo.org>
	<AANLkTiktR-zNsv4KrnOBh3PxXZTHa6UypzqnwSBpE1=R@mail.gmail.com>
	<20101022155416.GA18595@kroah.com>
Message-ID: <AANLkTinCXAw8JU3mjtWmLU8_JqmwXsyJ-6JS=_=5T9JY@mail.gmail.com>

On Fri, Oct 22, 2010 at 11:54, Greg KH wrote:
> On Sat, Oct 16, 2010 at 05:14:53AM -0400, Mike Frysinger wrote:
>> stable team: could you pick this up for 2.6.35.x ?
>>
>> it has been merged in mainline as eac15a429a27cb74115daaf4c1127c5e854d50e4
>
> But it doesn't apply at all to .35-stable. ?There is no call to
> nand_scan_ident() in that file in the .35 tree.
>
> So, no, sorry, I can't apply it :)

then the patch shouldnt be necessary and 2.6.35.x is OK.  sorry for the noise.
-mike


From w.sang at pengutronix.de  Sat Oct 23 06:24:49 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Sat, 23 Oct 2010 12:24:49 +0200
Subject: [PATCH 2/4] mtd: cfi_cmdset_0002: make sector erase command
	variable
In-Reply-To: <20101022154020.11097.4024.stgit@dev.siriade.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154020.11097.4024.stgit@dev.siriade.com>
Message-ID: <20101023102449.GB31623@pengutronix.de>

On Fri, Oct 22, 2010 at 05:40:20PM +0200, Guillaume LECERF wrote:
> Some old SST chips use 0x50 as sector erase command, instead
> of 0x30. Make this value variable to handle such chips.
> 
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
> ---
>  drivers/mtd/chips/cfi_cmdset_0002.c |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
> index 3e6c47b..209928b 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0002.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
> @@ -78,6 +78,7 @@ static struct mtd_chip_driver cfi_amdstd_chipdrv = {
>  	.module		= THIS_MODULE
>  };
>  
> +static map_word sector_erase_cmd = CMD(0x30);

Uh? A static one? Why not per device?

I'd also suggest to fold the next patch into this one, so the need for the
change is more obvious.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101023/8e441ac6/attachment.sig>

From eballetbo at gmail.com  Sat Oct 23 09:43:53 2010
From: eballetbo at gmail.com (Enric Balletbo i Serra)
Date: Sat, 23 Oct 2010 15:43:53 +0200
Subject: [PATCH 0/1] mtd: OneNAND: fix bufferram management. 
Message-ID: <1287841434-3349-1-git-send-email-eballetbo@gmail.com>


Hello,

Have a look at this patch, I've some problems with latest kernel from mainline
and a JFFS2 filesystem, the kernel reports various errors like

Header CRC failed on REF_PRISTINE node at 0x1e81315c: Read 0x000000e0, calculated 0x564fc9e8

Applying this patch solves the issue, but I  only have tested on IGEP v2 board with
a OneNAND from Numonyx. Please test with other OneNAND devices and point me if I'm
in the correct way to solve this issue. Thanks.

Cheers,
  Enric

$ git diff --stat origin/master
 drivers/mtd/onenand/onenand_base.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)


From eballetbo at gmail.com  Sat Oct 23 09:43:54 2010
From: eballetbo at gmail.com (Enric Balletbo i Serra)
Date: Sat, 23 Oct 2010 15:43:54 +0200
Subject: [PATCH 1/1] mtd: OneNAND: fix bufferram management when chip has
	2-planes.
In-Reply-To: <1287841434-3349-1-git-send-email-eballetbo@gmail.com>
References: <1287841434-3349-1-git-send-email-eballetbo@gmail.com>
Message-ID: <1287841434-3349-2-git-send-email-eballetbo@gmail.com>

This patch adds code that I think was lost when it was applied the commit
  5988af2319781bc8e0ce418affec4e09cfa77907 - mtd: Flex-OneNAND support

Test case:
 1. Stress a jffs2 filesystem using
    bonnie++ -u 0:0 -s 32 -m 16 -r 16
 2. dmesg shows various 'Header CRC failed' errors like:
    Header CRC failed on REF_PRISTINE node at 0x1e81315c: Read 0x000000e0,
    calculated 0x564fc9e8

Tested on IGEP v2 board with a Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58)
with 2 planes from Numonyx and CONFIG_MTD_ONENAND_2X_PROGRAM set to y

Signed-off-by: Enric Balletbo i Serra <eballetbo at gmail.com>
---
 drivers/mtd/onenand/onenand_base.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a2bb520..53aa13e 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1964,6 +1964,10 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
 
 			/* In partial page write we don't update bufferram */
 			onenand_update_bufferram(mtd, to, !ret && !subpage);
+			ONENAND_SET_BUFFERRAM1(this);
+			onenand_update_bufferram(mtd, to + this->writesize,
+				!ret && !subpage);
+
 			if (ret) {
 				printk(KERN_ERR "%s: write failed %d\n",
 					__func__, ret);
-- 
1.7.1



From thomaswoth at expey.com  Sat Oct 23 11:52:39 2010
From: thomaswoth at expey.com (Mr.Thomas Woth)
Date: Sat, 23 Oct 2010 11:52:39 -0400
Subject: =?US-ASCII?B?IEkgbG9vayBmb3J3YXJkIHRvIGhlYXJpbmcgZnJvbSB5b3Ugc29vbg==?=
Message-ID: <20101023155239.28709.qmail@lxb03033.hostcenter.com>


I believe we can do this transaction together in good faith. The share would be 30% for you and 70% for me. I would want to take care of the needy and less privileged, as this is my primary objective. It is a legacy of 4.4million pounds legacy. Upon the acknowledgement of this email, details of this proposal would be given to you. 

I look forward to hearing from you soon 

Yours truly 

Mr. Thomas Woth


From tarosa.y at gmail.com  Sat Oct 23 13:22:30 2010
From: tarosa.y at gmail.com (=?ISO-2022-JP?B?GyRCJD8kbSU1GyhC?=)
Date: Sun, 24 Oct 2010 02:22:30 +0900
Subject: where is the guideline of the development of the mtd layer
Message-ID: <AANLkTinM24JAP+ZQwZub1sCzNsGiiizGbF0EQngWNP1m@mail.gmail.com>

Hello. I am Tarosa.
I am studying the mechanism of the ubi layer.
Is there the one like the guideline of the development of the mtd
layer anywhere?
It concerns the interface of the mtd layer and the ubi layer.
I am looking for it.
My best regards.


From thomwoth at expey.com  Sat Oct 23 13:28:30 2010
From: thomwoth at expey.com (Mr.Thomas Woth)
Date: Sat, 23 Oct 2010 13:28:30 -0400
Subject: =?US-ASCII?B?IEkgbG9vayBmb3J3YXJkIHRvIGhlYXJpbmcgZnJvbSB5b3Ugc29vbg==?=
Message-ID: <20101023172830.10156.qmail@lxb03033.hostcenter.com>


I believe we can do this transaction together in good faith. The share would be 30% for you and 70% for me. I would want to take care of the needy and less privileged, as this is my primary objective. It is a legacy of 4.4million pounds legacy. Upon the acknowledgement of this email, details of this proposal would be given to you. 

I look forward to hearing from you soon 

Yours truly 

Mr. Thomas Woth


From dwmw2 at infradead.org  Sun Oct 24 19:11:49 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 00:11:49 +0100
Subject: [PATCH] mtd: add Broadcom BCM63xx image tag partition parser
In-Reply-To: <201009121553.01374.florian@openwrt.org>
References: <201009121553.01374.florian@openwrt.org>
Message-ID: <1287961909.5674.15.camel@macbook.infradead.org>

On Sun, 2010-09-12 at 15:52 +0200, Florian Fainelli wrote:
> 
> +       ret = master->read(master, master->erasesize, sizeof(struct bcm_tag),
> +                                                       &retlen, (void *)buf);
> +       if (retlen != sizeof(struct bcm_tag)) {
> +               vfree(buf);
> +               return -EIO;
> +       }
> +
> +       sscanf(buf->kernel_address, "%u", &kerneladdr);
> +       sscanf(buf->kernel_length, "%u", &kernellen);
> +       sscanf(buf->total_length, "%u", &totallen);
> +       tagversion = &(buf->tag_version[0]);
> +       boardid = &(buf->board_id[0]);
> +
> +       printk(KERN_INFO PFX "CFE boot tag found with version %s "
> +                               "and board type %s\n", tagversion, boardid); 

Um, that looks easy to crash, given that you aren't even checking the
CRC before you do this, and you aren't checking that any of these
strings are actually NUL-terminated.

I'm applying it as-is, since I'm extremely late -- I've been slacking.
But please could I have a fix?

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From dwmw2 at infradead.org  Sun Oct 24 19:28:20 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 00:28:20 +0100
Subject: [PATCH 1/2] MTD: generic FSMC NAND MTD driver
In-Reply-To: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
References: <1284330922-3569-1-git-send-email-linus.walleij@stericsson.com>
Message-ID: <1287962900.5674.21.camel@macbook.infradead.org>

On Mon, 2010-09-13 at 00:35 +0200, Linus Walleij wrote:
> 
> +#define PARTITION(n, off, sz)  {.name = n, .offset = off, .size = sz}
> +
> +/*
> + * Default partition layout for small page(= 512 bytes) devices
> + * Size for "Root file system" is updated in driver based on actual device size
> + */
> +static struct mtd_partition partition_info_16KB_blk[] = {
> +       PARTITION("X-loader", 0, 4 * 0x4000),
> +       PARTITION("U-Boot", 0x10000, 20 * 0x4000),
> +       PARTITION("Kernel", 0x60000, 256 * 0x4000),
> +       PARTITION("Root File System", 0x460000, 0),
> +}; 

Er, you use a macro just so that you can use order-dependent non-C99
structure initialisation? You realise that this would do the same thing:
 #define PARTITION(a,b,c) {a,c,b}

And no, I don't think *that* would be a good idea either :)

Please fix.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From dwmw2 at infradead.org  Sun Oct 24 20:01:49 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 01:01:49 +0100
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <4CAE2475.4090607@ti.com>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
	<20101007185630.GA26435@n2100.arm.linux.org.uk>
	<4CAE2475.4090607@ti.com>
Message-ID: <1287964909.5674.22.camel@macbook.infradead.org>

On Thu, 2010-10-07 at 14:50 -0500, Nishanth Menon wrote:
> my comment being that by moving {read,write}[wlb] to __raw versions dont 
> solve the real issue of namespace here. fix should be in 
> arch/arm/include/asm/io.h IMHO. so that there are no overlaps as this. 

Indeed. This patch is complete nonsense.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From dwmw2 at infradead.org  Sun Oct 24 20:11:25 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 01:11:25 +0100
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
Message-ID: <1287965485.5674.25.camel@macbook.infradead.org>

On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> 
> Test if it did and then abort.
> 
> Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> ---
>  fs/jffs2/nodemgmt.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
> index 694aa5b..49ee5de 100644
> --- a/fs/jffs2/nodemgmt.c
> +++ b/fs/jffs2/nodemgmt.c
> @@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
>                 spin_lock(&c->erase_completion_lock);
>  
>                 /* An erase may have failed, decreasing the
> -                  amount of free space available. So we must
> -                  restart from the beginning */
> -               return -EAGAIN;
> +                  amount of free space available. */
> +               if (list_empty(&c->free_list))
> +                       return -EAGAIN; /* restart from the beginning */ 

Hm, but there could have been more than one erase pending (or in
progress). And if one fails and another succeeds then you could have a
non-empty free_list but you could *also* now have run short of
free/freeable space so that a userspace write should now receive
-ENOSPC.

Is this really a performance issue? It should just come straight back if
the conditions are still met, surely?

And if we're hitting this code path that often, we should look at
erasing more aggressively so that we *don't* have to erase stuff on
demand.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From dwmw2 at infradead.org  Sun Oct 24 20:31:51 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 01:31:51 +0100
Subject: [PATCH 3/5] MTD: blktrans: fix a race vs kthread_stop.
In-Reply-To: <1287156047-17439-4-git-send-email-maximlevitsky@gmail.com>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
	<1287156047-17439-4-git-send-email-maximlevitsky@gmail.com>
Message-ID: <1287966711.5674.26.camel@macbook.infradead.org>

On Fri, 2010-10-15 at 17:20 +0200, Maxim Levitsky wrote:
> There is small race window that could make kthread_stop hang forever.
> I found that while hacking the IR subsystem.
> 
> Signed-off-by: Maxim Levitsky <maximlevisky at gmail.com>
> ---
>  drivers/mtd/mtd_blkdevs.c |    4 ++++
>  1 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
> index 040c2d9..a919587 100644
> --- a/drivers/mtd/mtd_blkdevs.c
> +++ b/drivers/mtd/mtd_blkdevs.c
> @@ -133,6 +133,10 @@ static int mtd_blktrans_thread(void *arg)
>  
>  		if (!req && !(req = blk_fetch_request(rq))) {
>  			set_current_state(TASK_INTERRUPTIBLE);
> +
> +			if (kthread_should_stop())
> +				set_current_state(TASK_RUNNING);
> +
>  			spin_unlock_irq(rq->queue_lock);
>  			schedule();
>  			spin_lock_irq(rq->queue_lock);


Shouldn't we add a break in there too, so it immediately breaks out of
the loop (with the lock held)?

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From zhangyd6 at gmail.com  Sun Oct 24 21:18:16 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 25 Oct 2010 09:18:16 +0800
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <20101022154030.11097.40767.stgit@dev.siriade.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154030.11097.40767.stgit@dev.siriade.com>
Message-ID: <AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>

On Fri, Oct 22, 2010 at 11:40 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> Add support for SST38VF640x chips in CFI mode.
>
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
> Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
> ---
> ?drivers/mtd/chips/cfi_cmdset_0002.c | ? 19 +++++++++++++++++++
> ?1 files changed, 19 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
> index a359967..0248253 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0002.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
> @@ -296,6 +296,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
> ? ? ? ?sector_erase_cmd = CMD(0x50);
> ?}
>
> +static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
> +{
> + ? ? ? struct map_info *map = mtd->priv;
> + ? ? ? struct cfi_private *cfi = map->fldrv_priv;
> +
> + ? ? ? fixup_sst39vf_rev_b(mtd, param);
> +
> + ? ? ? /*
> + ? ? ? ?* CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
> + ? ? ? ?* it should report a size of 8KBytes (0x0020 *256).
> + ? ? ? ?*/
> + ? ? ? cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
> + ? ? ? pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);
> +}
> +
> ?static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
> ?{
> ? ? ? ?struct map_info *map = mtd->priv;
> @@ -347,6 +362,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
> ? ? ? ?{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
> ? ? ? ?{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
> ? ? ? ?{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
> + ? ? ? { CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
> + ? ? ? { CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
> + ? ? ? { CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
> + ? ? ? { CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
> ?#if !FORCE_WORD_WRITE
> ? ? ? ?{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
> ?#endif
The SST38VF640x chips have no Extended Query table. I think we should
move them to the
 cfi_nopri_fixup_table.

>
>


From maximlevitsky at gmail.com  Sun Oct 24 21:44:54 2010
From: maximlevitsky at gmail.com (Maxim Levitsky)
Date: Mon, 25 Oct 2010 03:44:54 +0200
Subject: [PATCH 3/5] MTD: blktrans: fix a race vs kthread_stop.
In-Reply-To: <1287966711.5674.26.camel@macbook.infradead.org>
References: <1287156047-17439-1-git-send-email-maximlevitsky@gmail.com>
	<1287156047-17439-4-git-send-email-maximlevitsky@gmail.com>
	<1287966711.5674.26.camel@macbook.infradead.org>
Message-ID: <1287971094.5205.11.camel@maxim-laptop>

On Mon, 2010-10-25 at 01:31 +0100, David Woodhouse wrote:
> On Fri, 2010-10-15 at 17:20 +0200, Maxim Levitsky wrote:
> > There is small race window that could make kthread_stop hang forever.
> > I found that while hacking the IR subsystem.
> > 
> > Signed-off-by: Maxim Levitsky <maximlevisky at gmail.com>
> > ---
> >  drivers/mtd/mtd_blkdevs.c |    4 ++++
> >  1 files changed, 4 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
> > index 040c2d9..a919587 100644
> > --- a/drivers/mtd/mtd_blkdevs.c
> > +++ b/drivers/mtd/mtd_blkdevs.c
> > @@ -133,6 +133,10 @@ static int mtd_blktrans_thread(void *arg)
> >  
> >  		if (!req && !(req = blk_fetch_request(rq))) {
> >  			set_current_state(TASK_INTERRUPTIBLE);
> > +
> > +			if (kthread_should_stop())
> > +				set_current_state(TASK_RUNNING);
> > +
> >  			spin_unlock_irq(rq->queue_lock);
> >  			schedule();
> >  			spin_lock_irq(rq->queue_lock);
> 
> 
> Shouldn't we add a break in there too, so it immediately breaks out of
> the loop (with the lock held)?
It doesn't matter here, as schedule() won't make task sleep, so the
thread will break at next iteration.


Best regards
	Maxim Levitsky



From manjugk at ti.com  Mon Oct 25 01:34:57 2010
From: manjugk at ti.com (G, Manjunath Kondaiah)
Date: Mon, 25 Oct 2010 11:04:57 +0530
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <1287964909.5674.22.camel@macbook.infradead.org>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
	<20101007185630.GA26435@n2100.arm.linux.org.uk>
	<4CAE2475.4090607@ti.com>
	<1287964909.5674.22.camel@macbook.infradead.org>
Message-ID: <E0D41E29EB0DAC4E9F3FF173962E9E9402DBDDEFAA@dbde02.ent.ti.com>

David,

> -----Original Message-----
> From: David Woodhouse [mailto:dwmw2 at infradead.org] 
> Sent: Monday, October 25, 2010 5:32 AM
> To: Menon, Nishanth
> Cc: Russell King - ARM Linux; G, Manjunath Kondaiah; 
> linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; 
> linux-arm-kernel at lists.infradead.org
> Subject: Re: [PATCH v2 09/10] OMAP2/3: Convert write/read 
> functions to raw read/write
> 
> On Thu, 2010-10-07 at 14:50 -0500, Nishanth Menon wrote:
> > my comment being that by moving {read,write}[wlb] to __raw versions 
> > dont solve the real issue of namespace here. fix should be in 
> > arch/arm/include/asm/io.h IMHO. so that there are no 
> overlaps as this.
> 
> Indeed. This patch is complete nonsense.

nonsense? There are two types of fixes proposed to fix these sparse warnings.
1. with this patch
2. fixing in io.h
https://patchwork.kernel.org/patch/250171/

1st option is already merged with 2.6.37 merge window.

If 2 get accepted, all __raw_read/write will get replaced with readl/writel.

Apart from those two, do you have any other alternate idea to fix these sparse warnings?

-Manjunath

From joakim.tjernlund at transmode.se  Mon Oct 25 02:49:12 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Mon, 25 Oct 2010 08:49:12 +0200
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1287965485.5674.25.camel@macbook.infradead.org>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1287965485.5674.25.camel@macbook.infradead.org>
Message-ID: <OFC10FE113.61700EC9-ONC12577C7.002267AD-C12577C7.002576D4@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 02:11:25:
>
> On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> >
> > Test if it did and then abort.
> >
> > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> > ---
> >  fs/jffs2/nodemgmt.c |    6 +++---
> >  1 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
> > index 694aa5b..49ee5de 100644
> > --- a/fs/jffs2/nodemgmt.c
> > +++ b/fs/jffs2/nodemgmt.c
> > @@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
> >                 spin_lock(&c->erase_completion_lock);
> >
> >                 /* An erase may have failed, decreasing the
> > -                  amount of free space available. So we must
> > -                  restart from the beginning */
> > -               return -EAGAIN;
> > +                  amount of free space available. */
> > +               if (list_empty(&c->free_list))
> > +                       return -EAGAIN; /* restart from the beginning */
>
> Hm, but there could have been more than one erase pending (or in
> progress). And if one fails and another succeeds then you could have a
> non-empty free_list but you could *also* now have run short of
> free/freeable space so that a userspace write should now receive
> -ENOSPC.

I don't see how my patch changes that, if !list_empty(&c->free_list)
then you have at least one free block so you should not run into -ENOSPC

>
> Is this really a performance issue? It should just come straight back if
> the conditions are still met, surely?

Not a perf issue. It is something I noticed while looking for the
 jffs2: Fix serious write stall due to erase


>
> And if we're hitting this code path that often, we should look at
> erasing more aggressively so that we *don't* have to erase stuff on
> demand.
>



From aworkman at sbcglobal.net  Mon Oct 25 02:55:23 2010
From: aworkman at sbcglobal.net (aworkman at sbcglobal.net)
Date: Sun, 24 Oct 2010 23:55:23 -0700 (PDT)
Subject: You Won Seven Hundred And Fifty Thousand GBP in The Gnld Promo Send
Message-ID: <635208.25870.qm@web82001.mail.mud.yahoo.com>


Name:Address


From savary2782 at yahoo.com.tw  Mon Oct 25 03:11:50 2010
From: savary2782 at yahoo.com.tw (Ggokoj)
Date: Mon, 25 Oct 2010 15:11:50 +0800
Subject: =?GB2312?B?xKa2+9ev1LBQ?=
Message-ID: <19748.66133.qm@smtp106.mail.tp2.yahoo.com>

163.com

??
6.123.0.57
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Pkaqhi648.gif
Type: image/gif
Size: 7118 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101025/180dc939/attachment.gif>

From dedekind1 at gmail.com  Mon Oct 25 03:54:33 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 10:54:33 +0300
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <1287964909.5674.22.camel@macbook.infradead.org>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
	<20101007185630.GA26435@n2100.arm.linux.org.uk>
	<4CAE2475.4090607@ti.com>
	<1287964909.5674.22.camel@macbook.infradead.org>
Message-ID: <1287993273.2224.4.camel@localhost>

On Mon, 2010-10-25 at 01:01 +0100, David Woodhouse wrote:
> On Thu, 2010-10-07 at 14:50 -0500, Nishanth Menon wrote:
> > my comment being that by moving {read,write}[wlb] to __raw versions dont 
> > solve the real issue of namespace here. fix should be in 
> > arch/arm/include/asm/io.h IMHO. so that there are no overlaps as this. 
> 
> Indeed. This patch is complete nonsense.

Removing from my l2 tree.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Oct 25 04:01:49 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 11:01:49 +0300
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1287965485.5674.25.camel@macbook.infradead.org>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1287965485.5674.25.camel@macbook.infradead.org>
Message-ID: <1287993709.2224.6.camel@localhost>

On Mon, 2010-10-25 at 01:11 +0100, David Woodhouse wrote:
> On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> > 
> > Test if it did and then abort.
> > 
> > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> > ---
> >  fs/jffs2/nodemgmt.c |    6 +++---
> >  1 files changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
> > index 694aa5b..49ee5de 100644
> > --- a/fs/jffs2/nodemgmt.c
> > +++ b/fs/jffs2/nodemgmt.c
> > @@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
> >                 spin_lock(&c->erase_completion_lock);
> >  
> >                 /* An erase may have failed, decreasing the
> > -                  amount of free space available. So we must
> > -                  restart from the beginning */
> > -               return -EAGAIN;
> > +                  amount of free space available. */
> > +               if (list_empty(&c->free_list))
> > +                       return -EAGAIN; /* restart from the beginning */ 
> 
> Hm, but there could have been more than one erase pending (or in
> progress). And if one fails and another succeeds then you could have a
> non-empty free_list but you could *also* now have run short of
> free/freeable space so that a userspace write should now receive
> -ENOSPC.
> 
> Is this really a performance issue? It should just come straight back if
> the conditions are still met, surely?
> 
> And if we're hitting this code path that often, we should look at
> erasing more aggressively so that we *don't* have to erase stuff on
> demand.

David,

there are 2 patches which you seem to miss. I've re-based my l2 tree
against your today's mtd tree, and applied them on top. I've also
preserved this patch. Please, look at those.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Oct 25 04:05:45 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 11:05:45 +0300
Subject: [RFC] write bad block marker even with BBT
In-Reply-To: <4CC1A5EE.9080605@parrot.com>
References: <4CC1A5EE.9080605@parrot.com>
Message-ID: <1287993945.2224.9.camel@localhost>

> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index ddffe76..71052d0 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -409,7 +409,10 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  	/* Do we have a flash based bad block table ? */
>  	if (chip->options & NAND_USE_FLASH_BBT)
>  		ret = nand_update_bbt(mtd, ofs);
> -	else {
> +	/* put also the bad block marker in case we loose BBT or
> +	   the bootloader doesn't support reading it
> +	 */

Nitpick: please, use kernel commenting style:
/*
 * Multi-line
 * comment
 */

> +	{
>  		nand_get_device(chip, mtd, FL_WRITING);

I think this makes sense, but this may break some setups, so this should
be yet another chip->option.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Mon Oct 25 04:09:39 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Mon, 25 Oct 2010 10:09:39 +0200
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154030.11097.40767.stgit@dev.siriade.com>
	<AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>
Message-ID: <AANLkTi=s1AbuKGALhb6zjbo5KTRaTVY8B2P3-PwnZvsm@mail.gmail.com>

2010/10/25 yidong zhang <zhangyd6 at gmail.com>:
> The SST38VF640x chips have no Extended Query table. I think we should
> move them to the
> ?cfi_nopri_fixup_table.

According to the datasheet [1], it has.

[1] http://www.sst.com/dotAsset/39749.pdf, table 13
-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From glecerf at gmail.com  Mon Oct 25 04:11:21 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Mon, 25 Oct 2010 10:11:21 +0200
Subject: [PATCH 2/4] mtd: cfi_cmdset_0002: make sector erase command
	variable
In-Reply-To: <20101023102449.GB31623@pengutronix.de>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154020.11097.4024.stgit@dev.siriade.com>
	<20101023102449.GB31623@pengutronix.de>
Message-ID: <AANLkTim0ZnKoOmP3ZurS-wgZWTuB6QD5tXnYRsfyXqip@mail.gmail.com>

2010/10/23 Wolfram Sang <w.sang at pengutronix.de>:
>> +static map_word sector_erase_cmd = CMD(0x30);
>
> Uh? A static one? Why not per device?

Hi Wolfram.
I knew it was ugly, but where would you store this value ?

> I'd also suggest to fold the next patch into this one, so the need for the
> change is more obvious.

Done locally.

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From zhangyd6 at gmail.com  Mon Oct 25 04:38:38 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 25 Oct 2010 16:38:38 +0800
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <AANLkTi=s1AbuKGALhb6zjbo5KTRaTVY8B2P3-PwnZvsm@mail.gmail.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154030.11097.40767.stgit@dev.siriade.com>
	<AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>
	<AANLkTi=s1AbuKGALhb6zjbo5KTRaTVY8B2P3-PwnZvsm@mail.gmail.com>
Message-ID: <AANLkTinRiF4rnrhKDO79Cp9L=3=oS8-fsw6Y-f+x9N9-@mail.gmail.com>

On Mon, Oct 25, 2010 at 4:09 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/25 yidong zhang <zhangyd6 at gmail.com>:
>> The SST38VF640x chips have no Extended Query table. I think we should
>> move them to the
>> ?cfi_nopri_fixup_table.
>
> According to the datasheet [1], it has.
>
> [1] http://www.sst.com/dotAsset/39749.pdf, table 13

Oh, sorry, my mistake. I tested the patch right now. But it didn't
work, please the logs below.


Amd/Fujitsu Extended Query Table at 0x0040
  Unknown Amd/Fujitsu Extended Query version  .  (0xff/0xff).


> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>


From matthieu.castet at parrot.com  Mon Oct 25 04:38:59 2010
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Mon, 25 Oct 2010 10:38:59 +0200
Subject: [PATCH] write bad block marker even with BBT
Message-ID: <4CC54223.2050401@parrot.com>

Add a new flag to force writing bad block marker if we use bad block table.
This allow to solve problem where bootloader don't support reading BBT.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: mtd_btt.diff
Type: text/x-diff
Size: 1574 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101025/fe3b2e11/attachment.bin>

From glecerf at gmail.com  Mon Oct 25 05:17:25 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Mon, 25 Oct 2010 11:17:25 +0200
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <AANLkTinRiF4rnrhKDO79Cp9L=3=oS8-fsw6Y-f+x9N9-@mail.gmail.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154030.11097.40767.stgit@dev.siriade.com>
	<AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>
	<AANLkTi=s1AbuKGALhb6zjbo5KTRaTVY8B2P3-PwnZvsm@mail.gmail.com>
	<AANLkTinRiF4rnrhKDO79Cp9L=3=oS8-fsw6Y-f+x9N9-@mail.gmail.com>
Message-ID: <AANLkTinyoLrwmu63USS6OQXEuF3YXob95v30hggvvuKx@mail.gmail.com>

2010/10/25 yidong zhang <zhangyd6 at gmail.com>:
> Oh, sorry, my mistake. I tested the patch right now. But it didn't
> work, please the logs below.
>
> Amd/Fujitsu Extended Query Table at 0x0040
> ?Unknown Amd/Fujitsu Extended Query version ?. ?(0xff/0xff).

This chip does not have a valid Major/MinorVersion.
Could you please try the attached patch ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 03-sst38vf640x.patch
Type: application/octet-stream
Size: 2366 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101025/5459ffff/attachment.obj>

From dwmw2 at infradead.org  Mon Oct 25 05:50:01 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 10:50:01 +0100
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <OFC10FE113.61700EC9-ONC12577C7.002267AD-C12577C7.002576D4@transmode.se>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1287965485.5674.25.camel@macbook.infradead.org>
	<OFC10FE113.61700EC9-ONC12577C7.002267AD-C12577C7.002576D4@transmode.se>
Message-ID: <1288000201.26820.38.camel@i7.infradead.org>

On Mon, 2010-10-25 at 08:49 +0200, Joakim Tjernlund wrote:
> David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 02:11:25:
> >
> > On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> > >
> > > Test if it did and then abort.
> > >
> > > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> > > ---
> > >  fs/jffs2/nodemgmt.c |    6 +++---
> > >  1 files changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
> > > index 694aa5b..49ee5de 100644
> > > --- a/fs/jffs2/nodemgmt.c
> > > +++ b/fs/jffs2/nodemgmt.c
> > > @@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
> > >                 spin_lock(&c->erase_completion_lock);
> > >
> > >                 /* An erase may have failed, decreasing the
> > > -                  amount of free space available. So we must
> > > -                  restart from the beginning */
> > > -               return -EAGAIN;
> > > +                  amount of free space available. */
> > > +               if (list_empty(&c->free_list))
> > > +                       return -EAGAIN; /* restart from the beginning */
> >
> > Hm, but there could have been more than one erase pending (or in
> > progress). And if one fails and another succeeds then you could have a
> > non-empty free_list but you could *also* now have run short of
> > free/freeable space so that a userspace write should now receive
> > -ENOSPC.
> 
> I don't see how my patch changes that, if !list_empty(&c->free_list)
> then you have at least one free block so you should not run into -ENOSPC

Not for jffs2_reserve_space_gc(), you're right. But for non-GC
allocations it's different -- jffs2_reserve_space() will only allow an
allocation if you have more than a certain amount of freeable space,
according to the type of operation. And that amount of freeable space
can be reduced if an erase fails.

-- 
dwmw2



From zhangyd6 at gmail.com  Mon Oct 25 06:01:04 2010
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 25 Oct 2010 18:01:04 +0800
Subject: [PATCH 4/4] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <AANLkTinyoLrwmu63USS6OQXEuF3YXob95v30hggvvuKx@mail.gmail.com>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154030.11097.40767.stgit@dev.siriade.com>
	<AANLkTinTpHtLRU_cXYsvc0EmBCcxDG+e1i9bY1Es7=fp@mail.gmail.com>
	<AANLkTi=s1AbuKGALhb6zjbo5KTRaTVY8B2P3-PwnZvsm@mail.gmail.com>
	<AANLkTinRiF4rnrhKDO79Cp9L=3=oS8-fsw6Y-f+x9N9-@mail.gmail.com>
	<AANLkTinyoLrwmu63USS6OQXEuF3YXob95v30hggvvuKx@mail.gmail.com>
Message-ID: <AANLkTik8D4DyTvybO9N6-z2CMXO=mez8KLYyxniKQQg3@mail.gmail.com>

On Mon, Oct 25, 2010 at 5:17 PM, Guillaume LECERF <glecerf at gmail.com> wrote:
> 2010/10/25 yidong zhang <zhangyd6 at gmail.com>:
>> Oh, sorry, my mistake. I tested the patch right now. But it didn't
>> work, please the logs below.
>>
>> Amd/Fujitsu Extended Query Table at 0x0040
>> ?Unknown Amd/Fujitsu Extended Query version ?. ?(0xff/0xff).
>
> This chip does not have a valid Major/MinorVersion.
> Could you please try the attached patch ?

Passed my test. Using this patch, the driver can support the chips now.

>
> --
> Guillaume LECERF
> GeeXboX developer - www.geexbox.org
>


From joakim.tjernlund at transmode.se  Mon Oct 25 06:01:24 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Mon, 25 Oct 2010 12:01:24 +0200
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1288000201.26820.38.camel@i7.infradead.org>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>	
	<1287965485.5674.25.camel@macbook.infradead.org>
	<OFC10FE113.61700EC9-ONC12577C7.002267AD-C12577C7.002576D4@transmode.se>
	<1288000201.26820.38.camel@i7.infradead.org>
Message-ID: <OFEC5B9F23.EE0D161D-ONC12577C7.0036D8F4-C12577C7.00370F7B@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 11:50:01:
>
> On Mon, 2010-10-25 at 08:49 +0200, Joakim Tjernlund wrote:
> > David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 02:11:25:
> > >
> > > On Thu, 2010-10-07 at 18:29 +0200, Joakim Tjernlund wrote:
> > > >
> > > > Test if it did and then abort.
> > > >
> > > > Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund at transmode.se>
> > > > ---
> > > >  fs/jffs2/nodemgmt.c |    6 +++---
> > > >  1 files changed, 3 insertions(+), 3 deletions(-)
> > > >
> > > > diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
> > > > index 694aa5b..49ee5de 100644
> > > > --- a/fs/jffs2/nodemgmt.c
> > > > +++ b/fs/jffs2/nodemgmt.c
> > > > @@ -260,9 +260,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
> > > >                 spin_lock(&c->erase_completion_lock);
> > > >
> > > >                 /* An erase may have failed, decreasing the
> > > > -                  amount of free space available. So we must
> > > > -                  restart from the beginning */
> > > > -               return -EAGAIN;
> > > > +                  amount of free space available. */
> > > > +               if (list_empty(&c->free_list))
> > > > +                       return -EAGAIN; /* restart from the beginning */
> > >
> > > Hm, but there could have been more than one erase pending (or in
> > > progress). And if one fails and another succeeds then you could have a
> > > non-empty free_list but you could *also* now have run short of
> > > free/freeable space so that a userspace write should now receive
> > > -ENOSPC.
> >
> > I don't see how my patch changes that, if !list_empty(&c->free_list)
> > then you have at least one free block so you should not run into -ENOSPC
>
> Not for jffs2_reserve_space_gc(), you're right. But for non-GC
> allocations it's different -- jffs2_reserve_space() will only allow an
> allocation if you have more than a certain amount of freeable space,
> according to the type of operation. And that amount of freeable space
> can be reduced if an erase fails.

But jffs2_find_nextblock is only about finding ONE block, isn't it?

     Jocke



From dwmw2 at infradead.org  Mon Oct 25 06:11:30 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 11:11:30 +0100
Subject: [PATCH v2 09/10] OMAP2/3: Convert write/read functions to raw
	read/write
In-Reply-To: <E0D41E29EB0DAC4E9F3FF173962E9E9402DBDDEFAA@dbde02.ent.ti.com>
References: <1285063280-4057-1-git-send-email-manjugk@ti.com>
	<1285063280-4057-10-git-send-email-manjugk@ti.com>
	<7A436F7769CA33409C6B44B358BFFF0C014F74831E@dlee02.ent.ti.com>
	<20101007185630.GA26435@n2100.arm.linux.org.uk>
	<4CAE2475.4090607@ti.com>
	<1287964909.5674.22.camel@macbook.infradead.org>
	<E0D41E29EB0DAC4E9F3FF173962E9E9402DBDDEFAA@dbde02.ent.ti.com>
Message-ID: <1288001490.26820.46.camel@i7.infradead.org>

On Mon, 2010-10-25 at 11:04 +0530, G, Manjunath Kondaiah wrote:
> David,
> 
> > -----Original Message-----
> > From: David Woodhouse [mailto:dwmw2 at infradead.org] 
> > Sent: Monday, October 25, 2010 5:32 AM
> > To: Menon, Nishanth
> > Cc: Russell King - ARM Linux; G, Manjunath Kondaiah; 
> > linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; 
> > linux-arm-kernel at lists.infradead.org
> > Subject: Re: [PATCH v2 09/10] OMAP2/3: Convert write/read 
> > functions to raw read/write
> > 
> > On Thu, 2010-10-07 at 14:50 -0500, Nishanth Menon wrote:
> > > my comment being that by moving {read,write}[wlb] to __raw versions 
> > > dont solve the real issue of namespace here. fix should be in 
> > > arch/arm/include/asm/io.h IMHO. so that there are no 
> > overlaps as this.
> > 
> > Indeed. This patch is complete nonsense.
> 
> nonsense? There are two types of fixes proposed to fix these sparse warnings.
> 1. with this patch
> 2. fixing in io.h
> https://patchwork.kernel.org/patch/250171/
> 
> 1st option is already merged with 2.6.37 merge window.
> 
> If 2 get accepted, all __raw_read/write will get replaced with readl/writel.
> 
> Apart from those two, do you have any other alternate idea to fix these sparse warnings?

The latter is obviously the better approach. The problem that sparse is
complaining about is the fact that you have two nested C blocks, both of
which contain a local variable called '__v'. By changing the variable
names so that they're actually unique, we fix the real problem.

The answer is not that *all* drivers which call cpu_to_le16(readw())
must be changed, which is what you seem to have assumed. And you
*certainly* can't change them to use __raw_readw(), which has
*different* semantics (and endianness in some cases), without a clear
comment in the changelog entry saying *why* that change was OK.

-- 
dwmw2



From dwmw2 at infradead.org  Mon Oct 25 06:56:48 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 11:56:48 +0100
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1287993709.2224.6.camel@localhost>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1287965485.5674.25.camel@macbook.infradead.org>
	<1287993709.2224.6.camel@localhost>
Message-ID: <1288004208.26820.57.camel@i7.infradead.org>

On Mon, 2010-10-25 at 11:01 +0300, Artem Bityutskiy wrote:
> 
> there are 2 patches which you seem to miss. I've re-based my l2 tree
> against your today's mtd tree, and applied them on top. I've also
> preserved this patch. Please, look at those. 

The 'fix NAND pwrite in raw mode' patch is redundant -- the problem is
fixed by Jon Povey's patch in commit cdcf12b2, which looks almost
identical to the way I suggested it be fixed.

The callback from m25p80 was dropped by its author, and rightly so.

Thanks, again, for keeping track.

-- 
dwmw2



From joakim.tjernlund at transmode.se  Mon Oct 25 07:00:24 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Mon, 25 Oct 2010 13:00:24 +0200
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1288004208.26820.57.camel@i7.infradead.org>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>	
	<1287965485.5674.25.camel@macbook.infradead.org>
	<1287993709.2224.6.camel@localhost>
	<1288004208.26820.57.camel@i7.infradead.org>
Message-ID: <OF4C8420E7.4D35D741-ONC12577C7.003C4CDC-C12577C7.003C7659@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 12:56:48:
>
> On Mon, 2010-10-25 at 11:01 +0300, Artem Bityutskiy wrote:
> >
> > there are 2 patches which you seem to miss. I've re-based my l2 tree
> > against your today's mtd tree, and applied them on top. I've also
> > preserved this patch. Please, look at those.
>
> The 'fix NAND pwrite in raw mode' patch is redundant -- the problem is
> fixed by Jon Povey's patch in commit cdcf12b2, which looks almost
> identical to the way I suggested it be fixed.
>
> The callback from m25p80 was dropped by its author, and rightly so.
>
> Thanks, again, for keeping track.

But jffs2: Fix serious write stall due to erase
from me remains :)



From dwmw2 at infradead.org  Mon Oct 25 07:01:27 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 12:01:27 +0100
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <OF4C8420E7.4D35D741-ONC12577C7.003C4CDC-C12577C7.003C7659@transmode.se>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>
	<1287965485.5674.25.camel@macbook.infradead.org>
	<1287993709.2224.6.camel@localhost>
	<1288004208.26820.57.camel@i7.infradead.org>
	<OF4C8420E7.4D35D741-ONC12577C7.003C4CDC-C12577C7.003C7659@transmode.se>
Message-ID: <1288004487.26820.58.camel@i7.infradead.org>

On Mon, 2010-10-25 at 13:00 +0200, Joakim Tjernlund wrote:
> David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 12:56:48:
> >
> > On Mon, 2010-10-25 at 11:01 +0300, Artem Bityutskiy wrote:
> > >
> > > there are 2 patches which you seem to miss. I've re-based my l2 tree
> > > against your today's mtd tree, and applied them on top. I've also
> > > preserved this patch. Please, look at those.
> >
> > The 'fix NAND pwrite in raw mode' patch is redundant -- the problem is
> > fixed by Jon Povey's patch in commit cdcf12b2, which looks almost
> > identical to the way I suggested it be fixed.
> >
> > The callback from m25p80 was dropped by its author, and rightly so.
> >
> > Thanks, again, for keeping track.
> 
> But jffs2: Fix serious write stall due to erase
> from me remains :)

http://git.infradead.org/mtd-2.6.git/commitdiff/81cfc9f1

-- 
dwmw2



From joakim.tjernlund at transmode.se  Mon Oct 25 07:03:23 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Mon, 25 Oct 2010 13:03:23 +0200
Subject: [PATCH] jffs2: Do not assume erase will fail
In-Reply-To: <1288004487.26820.58.camel@i7.infradead.org>
References: <1286468986-24627-1-git-send-email-Joakim.Tjernlund@transmode.se>	
	<1287965485.5674.25.camel@macbook.infradead.org>
	<1287993709.2224.6.camel@localhost>	
	<1288004208.26820.57.camel@i7.infradead.org>
	<OF4C8420E7.4D35D741-ONC12577C7.003C4CDC-C12577C7.003C7659@transmode.se>
	<1288004487.26820.58.camel@i7.infradead.org>
Message-ID: <OF31271535.A37B9F46-ONC12577C7.003CAFBC-C12577C7.003CBC6B@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 13:01:27:
>
> On Mon, 2010-10-25 at 13:00 +0200, Joakim Tjernlund wrote:
> > David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/25 12:56:48:
> > >
> > > On Mon, 2010-10-25 at 11:01 +0300, Artem Bityutskiy wrote:
> > > >
> > > > there are 2 patches which you seem to miss. I've re-based my l2 tree
> > > > against your today's mtd tree, and applied them on top. I've also
> > > > preserved this patch. Please, look at those.
> > >
> > > The 'fix NAND pwrite in raw mode' patch is redundant -- the problem is
> > > fixed by Jon Povey's patch in commit cdcf12b2, which looks almost
> > > identical to the way I suggested it be fixed.
> > >
> > > The callback from m25p80 was dropped by its author, and rightly so.
> > >
> > > Thanks, again, for keeping track.
> >
> > But jffs2: Fix serious write stall due to erase
> > from me remains :)
>
> http://git.infradead.org/mtd-2.6.git/commitdiff/81cfc9f1

Oh, you had already taken it. Thanks

    Jocke



From vivenzio.pagliari at gmx.de  Mon Oct 25 07:58:54 2010
From: vivenzio.pagliari at gmx.de (Vivenzio Pagliari)
Date: Mon, 25 Oct 2010 13:58:54 +0200
Subject: [PATCH] mtd-utils: mkfs.ubifs: Fix typo in short options of mkfs.ubifs
Message-ID: <20101025115854.226600@gmx.net>

The short option for specifying the count of erase blocks for orphans '-p'
was not detected due to a typo.
    
Signed-off-by: Vivenzio Pagliari <vivenzio.pagliari at gmx.de>

diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index d83f6bd..bc0817f 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -132,7 +132,7 @@ static struct inum_mapping **hash_table;
 /* Inode creation sequence number */
 static unsigned long long creat_sqnum;
 
-static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:P:k:x:X:j:R:l:j:UQq";
+static const char *optstring = "d:r:m:o:D:h?vVe:c:g:f:p:k:x:X:j:R:l:j:UQq";
 
 static const struct option longopts[] = {
        {"root",               1, NULL, 'r'},

-- 
Neu: GMX De-Mail - Einfach wie E-Mail, sicher wie ein Brief!  
Jetzt De-Mail-Adresse reservieren: http://portal.gmx.net/de/go/demail


From dwmw2 at infradead.org  Mon Oct 25 10:15:27 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Mon, 25 Oct 2010 15:15:27 +0100
Subject: [PATCH 1/2] P4080/eLBC: Make Freescale elbc interrupt common
	to elbc	devices
In-Reply-To: <4CBC1775.6000706@windriver.com>
References: <1287386552-10647-1-git-send-email-tie-fei.zang@freescale.com>
	<4CBC0B95.9010300@windriver.com>
	<3850A844E6A3854C827AC5C0BEC7B60A2B0708@zch01exm23.fsl.freescale.net>
	<4CBC16FD.6030507@windriver.com>  <4CBC1775.6000706@windriver.com>
Message-ID: <1288016127.5674.45.camel@macbook.infradead.org>

On Mon, 2010-10-18 at 17:46 +0800, tiejun.chen wrote:
> 
> >>> Looks you always iounmap(fsl_lbc_ctrl_dev->regs) on position 'err' but here
> >>> of_iomap() is already failed you should skip iounmap() fsl_lbc_ctrl_dev->regs
> >>> again. So you should improve that as the following on 'err', or layout 'err'
> >>> in
> >>> gain.
> >>> ------
> >>>     if(fsl_lbc_ctrl_dev->regs)
> >>>             iounmap(fsl_lbc_ctrl_dev->regs);
> >>>
> >>> Tiejun
> >> You are right!
> >> How about
> >>  
> >>         if (!fsl_lbc_ctrl_dev->regs) {
> >>                 dev_err(&dev->dev, "failed to get memory region\n");
> >>                 kfree(fsl_lbc_ctrl_dev);
> >>                 return -ENOMEM;
> >>         }
> > 
> > Although this is a big problem, I prefer to return 'ENXIO' :)
>                 ^
>                 Typo: is not a ...... 

My God! Why did you *both* repeat over 400 lines of patch, over and over
again, just for this?

Please, make sure you quote *only* what you actually need to quote for
context. Don't make me implement a filter for the list which rejects
messages that are more than 90% quotation.

-- 
dwmw2



From dedekind1 at gmail.com  Mon Oct 25 15:03:36 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 22:03:36 +0300
Subject: Issues with ubi utils Makefile
In-Reply-To: <201010211643.33332.manningc2@actrix.gen.nz>
References: <201010211643.33332.manningc2@actrix.gen.nz>
Message-ID: <1288033416.1865.2.camel@brekeke>

On Thu, 2010-10-21 at 16:43 +1300, Charles Manning wrote:
> Hi All
> 
> I'm getting some errors trying to mount a ubinized volume with a more recent 
> kernel and think it might be due to problems in the ubi utils distributed 
> with Ubuntu Meerkat.
> 
> I thus thought I'd build from git
> 
> When I do a make install from inside the mtd-utils/ubi-utils it tries to place 
> the binaries in /usr/local//usr/sbin.
> 
> Same happens if I try make install from mtd-utils/
> 
> Is something broken or am I driving it incorrectly?

Looks like Mike's commit broke it:

commit 96a4f76f2e9dad7fdbd6fd7740de44bc90d5769e
Author: Mike Frysinger <vapier at gentoo.org>

    Unify all common build system parts

I've quickly cooked this fix, does it work for you? Mike, are you ok
with this?


From Artem.Bityutskiy at nokia.com  Mon Oct 25 14:54:47 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 21:54:47 +0300
Subject: [PATCH] mtd-utils: fix make install
Message-ID: <mailman.2.1288033431.1530.linux-mtd@lists.infradead.org>

Commit 96a4f76f2e9dad7fdbd6fd7740de44bc90d5769e broke 'make install'.
Before that commit, $DESTDIR was undefined, so  ${DESTDIR}/${SBINDIR}
was /usr/sbin, and after the commit $DESTDIR became /usr/local, so
${DESTDIR}/${SBINDIR} became /usr/local//usr/sbin, which is wrong.

Fix this by making $DESTDIR become the distination directory of installing,
i.e. 'DESTDIR ?= /usr' and making SBINDIR become just 'sbin'.

While we are on it, fix $MANDIR similarly, and remove $PREFIX and
$EXEC_PREFIX variables, which become unneeded.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Reported-by: Charles Manning <manningc2 at actrix.gen.nz>
---
 common.mk |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/common.mk b/common.mk
index a55c548..2e4452f 100644
--- a/common.mk
+++ b/common.mk
@@ -20,12 +20,9 @@ ifneq ($(WITHOUT_LARGEFILE), 1)
   CPPFLAGS += -D_FILE_OFFSET_BITS=64
 endif
 
-DESTDIR ?= /usr/local
-PREFIX=/usr
-EXEC_PREFIX=$(PREFIX)
-SBINDIR=$(EXEC_PREFIX)/sbin
-MANDIR=$(PREFIX)/share/man
-INCLUDEDIR=$(PREFIX)/include
+DESTDIR ?= /usr
+SBINDIR=sbin
+MANDIR=share/man
 
 ifndef BUILDDIR
 ifeq ($(origin CROSS),undefined)
-- 
1.7.2.3

-- 
Best Regards,
Artem Bityutskiy (???????????????? ??????????)



From dedekind1 at gmail.com  Mon Oct 25 15:15:12 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 22:15:12 +0300
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style,
	signed-ness, printing fixups
In-Reply-To: <1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <1288034112.1865.7.camel@brekeke>

On Thu, 2010-10-21 at 00:19 -0700, Brian Norris wrote:
> There were some signed/unsigned integer comparisons. Their types were
> changed for safety. Also, "strtol" was improperly used for unsigned
> data types.
> 
> Nanddump's pretty print options needed a slight reformat to prepare for
> printing offsets that are more than 32 bits (8 hex characters) wide.
> This prevents overlap of output and ensures that at least one space is
> printed between hex and ascii printouts. Perhaps this could use some
> better alignment in the future.
> 
> Other fixes:
> * Corrected several simple spacing issues
> * Changed indentation of some global variable declarations in
>   order to prepare for the next patch, which makes those
>   declarations longer
> * Used macro for PRETTY_ROW_SIZE instead of constant 16
> * Reformatted, edited a multi-line comment
> * Removed some unnecessary casts
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  nanddump.c  |   55 +++++++++++++++++++++++++++----------------------------
>  nandwrite.c |   28 ++++++++++++++--------------
>  2 files changed, 41 insertions(+), 42 deletions(-)

Mike is right, it is much better to separate functional and cleanup
changes, even split different clean-up changes into several patches.
Maintaining this stuff and reviewing patches takes time, and splitting
helps a lot. Let's push this patch but please, try to splint patches on
more smaller pieces. Yes, it'll be more work for you, but less for me.
But when submitters take more burden and maintainer less - the system
scales better. Take into account that I'm doing this stuff just because
I like MTD and do not like see people's patches lost, so little help in
form of perfectly split micro-patches is appreciated.

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Oct 25 15:20:27 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 22:20:27 +0300
Subject: [PATCH v2 2/2] mtd-utils: nanddump: add 64-bit support,
	utilize libmtd
In-Reply-To: <1287645577-13538-3-git-send-email-computersforpeace@gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-3-git-send-email-computersforpeace@gmail.com>
Message-ID: <1288034427.1865.9.camel@brekeke>

On Thu, 2010-10-21 at 00:19 -0700, Brian Norris wrote:
> Adds support for 64-bit offsets (i.e., devices larger than 4GB).
> Utilizes the "unsigned long long" data type as the standard type
> for 64-bit offsets throughout. Reformats a few printf statements
> to avoid casting and to properly handle "long long."
> 
> Calls to ioctls are mostly replaced by libmtd interfaces (which should
> choose the proper ioctls for us); however, a few remain and probably
> should be handled with more robust interfaces, as some of these
> ioctls are considered "legacy."
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  nanddump.c |   83 +++++++++++++++++++++++++++++-------------------------------
>  1 files changed, 40 insertions(+), 43 deletions(-)

Pushed, thanks.

Mike, thanks for reviewing. You did not provide formal "Reviewed-by"
though, so I did not add this tag, assuming you did this for purposes,
because for other patches you provide ready to copy-paste tags.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Oct 25 15:26:20 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 25 Oct 2010 22:26:20 +0300
Subject: [PATCH] mtd-utils: mkfs.ubifs: Fix typo in short options of
	mkfs.ubifs
In-Reply-To: <20101025115854.226600@gmx.net>
References: <20101025115854.226600@gmx.net>
Message-ID: <1288034780.1865.10.camel@brekeke>

On Mon, 2010-10-25 at 13:58 +0200, Vivenzio Pagliari wrote:
> The short option for specifying the count of erase blocks for orphans '-p'
> was not detected due to a typo.
>     
> Signed-off-by: Vivenzio Pagliari <vivenzio.pagliari at gmx.de>
> 
> diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
> index d83f6bd..bc0817f 100644
> --- a/mkfs.ubifs/mkfs.ubifs.c
> +++ b/mkfs.ubifs/mkfs.ubifs.c

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier.adi at gmail.com  Mon Oct 25 15:54:45 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 25 Oct 2010 15:54:45 -0400
Subject: [PATCH v2 2/2] mtd-utils: nanddump: add 64-bit support,
	utilize libmtd
In-Reply-To: <1288034427.1865.9.camel@brekeke>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-3-git-send-email-computersforpeace@gmail.com>
	<1288034427.1865.9.camel@brekeke>
Message-ID: <AANLkTikG52xr1sj9TabRckrCOLk9Np=PgsSidXR+TyZ6@mail.gmail.com>

On Mon, Oct 25, 2010 at 15:20, Artem Bityutskiy wrote:
> Mike, thanks for reviewing. You did not provide formal "Reviewed-by"
> though, so I did not add this tag, assuming you did this for purposes,
> because for other patches you provide ready to copy-paste tags.

i'm not in the habit of using that tag, so i dont remember to post it
-mike


From vapier.adi at gmail.com  Mon Oct 25 16:45:46 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 25 Oct 2010 16:45:46 -0400
Subject: Issues with ubi utils Makefile
In-Reply-To: <1288033416.1865.2.camel@brekeke>
References: <201010211643.33332.manningc2@actrix.gen.nz>
	<1288033416.1865.2.camel@brekeke>
Message-ID: <AANLkTikd9uTV+8bRhjKt8P0vXC6p0FUbWd=bb6k2FGKi@mail.gmail.com>

On Mon, Oct 25, 2010 at 15:03, Artem Bityutskiy wrote:
> Commit 96a4f76f2e9dad7fdbd6fd7740de44bc90d5769e broke 'make install'.
> Before that commit, $DESTDIR was undefined, so ?${DESTDIR}/${SBINDIR}
> was /usr/sbin, and after the commit $DESTDIR became /usr/local, so
> ${DESTDIR}/${SBINDIR} became /usr/local//usr/sbin, which is wrong.

that isnt really true.  DESTDIR had value in makefiles before my changes.

> Fix this by making $DESTDIR become the distination directory of installing,
> i.e. 'DESTDIR ?= /usr' and making SBINDIR become just 'sbin'.

i'd rather we change DESTDIR to match the standard -- it's a "root"
prefix only.  so the default should be:
DESTDIR ?=
-mike


From vapier.adi at gmail.com  Mon Oct 25 16:57:04 2010
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 25 Oct 2010 16:57:04 -0400
Subject: Issues with ubi utils Makefile
In-Reply-To: <AANLkTikd9uTV+8bRhjKt8P0vXC6p0FUbWd=bb6k2FGKi@mail.gmail.com>
References: <201010211643.33332.manningc2@actrix.gen.nz>
	<1288033416.1865.2.camel@brekeke>
	<AANLkTikd9uTV+8bRhjKt8P0vXC6p0FUbWd=bb6k2FGKi@mail.gmail.com>
Message-ID: <AANLkTinDuG62AapBDGvcjjJFUDxQDxcik3zEs2Gkm_st@mail.gmail.com>

On Mon, Oct 25, 2010 at 16:45, Mike Frysinger wrote:
> On Mon, Oct 25, 2010 at 15:03, Artem Bityutskiy wrote:
>> Commit 96a4f76f2e9dad7fdbd6fd7740de44bc90d5769e broke 'make install'.
>> Before that commit, $DESTDIR was undefined, so ?${DESTDIR}/${SBINDIR}
>> was /usr/sbin, and after the commit $DESTDIR became /usr/local, so
>> ${DESTDIR}/${SBINDIR} became /usr/local//usr/sbin, which is wrong.
>
> that isnt really true. ?DESTDIR had value in makefiles before my changes.
>
>> Fix this by making $DESTDIR become the distination directory of installing,
>> i.e. 'DESTDIR ?= /usr' and making SBINDIR become just 'sbin'.
>
> i'd rather we change DESTDIR to match the standard -- it's a "root"
> prefix only. ?so the default should be:
> DESTDIR ?=

i guess this is also why i never noticed before.  i never do plain
`make install` since i'm not root and i dont want it clobbering
things.  i always do `make install DESTDIR=$PWD/foo` when testing and
in that regard, it works fine.  so i guess we want this simple change:
--- a/common.mk
+++ b/common.mk
@@ -20,7 +20,7 @@ ifneq ($(WITHOUT_LARGEFILE), 1)
   CPPFLAGS += -D_FILE_OFFSET_BITS=64
 endif

-DESTDIR ?= /usr/local
+DESTDIR?=
 PREFIX=/usr
 EXEC_PREFIX=$(PREFIX)
 SBINDIR=$(EXEC_PREFIX)/sbin
-mike


From Frank.Li at freescale.com  Mon Oct 25 22:54:20 2010
From: Frank.Li at freescale.com (Frank Li)
Date: Tue, 26 Oct 2010 10:54:20 +0800
Subject: [PATCH 1/1] MTD: Fix MTD_MODE_RAW write fail
Message-ID: <1288061660-23363-1-git-send-email-Frank.Li@freescale.com>

mtdchar have not initilized all field of struct mtd_oob_ops
in mtd_write when mode is MTD_MODE_RAW.

function nand_do_write_ops
	if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
		return -EINVAL;

ooboffs is not initilized at mtd_write.
So random data cause nand_do_write_ops return fail.

Signed-off-by: Frank Li <Frank.Li at freescale.com>
---
 drivers/mtd/mtdchar.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index b7ed09c..58839fa 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -319,6 +319,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
 		case MTD_MODE_RAW:
 		{
 			struct mtd_oob_ops ops;
+			memset(&ops, 0, sizeof(struct mtd_oob_ops));
 
 			ops.mode = MTD_OOB_RAW;
 			ops.datbuf = kbuf;
-- 
1.7.1




From Frank.Li at freescale.com  Mon Oct 25 23:02:19 2010
From: Frank.Li at freescale.com (Frank Li)
Date: Tue, 26 Oct 2010 11:02:19 +0800
Subject: [PATCH 1/1] MTD: Fix wrong check register_blkdev return value
Message-ID: <1288062139-2192-1-git-send-email-Frank.Li@freescale.com>

register_blkdev return 1..255 when major = 0.

if (ret ) {
	printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
		tr->name, tr->major, ret);
	      mutex_unlock(&mtd_table_mutex);
	return ret;
}

Above code will return fail when register_blkdev return allocated major number.

Signed-off-by: Frank Li <Frank.Li at freescale.com>
---
 drivers/mtd/mtd_blkdevs.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index a919587..63790e9 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -502,13 +502,16 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
 	mutex_lock(&mtd_table_mutex);
 
 	ret = register_blkdev(tr->major, tr->name);
-	if (ret) {
+	if (ret < 0) {
 		printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
 		       tr->name, tr->major, ret);
 		mutex_unlock(&mtd_table_mutex);
 		return ret;
 	}
 
+	if (ret)
+		tr->major = ret;
+
 	tr->blkshift = ffs(tr->blksize) - 1;
 
 	INIT_LIST_HEAD(&tr->devs);
-- 
1.7.1




From Jon.Povey at racelogic.co.uk  Mon Oct 25 23:48:11 2010
From: Jon.Povey at racelogic.co.uk (Jon Povey)
Date: Tue, 26 Oct 2010 04:48:11 +0100
Subject: [PATCH 1/1] MTD: Fix MTD_MODE_RAW write fail
In-Reply-To: <1288061660-23363-1-git-send-email-Frank.Li@freescale.com>
Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093EEF8EAC@Cloud.RL.local>

linux-mtd-bounces at lists.infradead.org wrote:
> mtdchar have not initilized all field of struct mtd_oob_ops
> in mtd_write when mode is MTD_MODE_RAW.
>
> function nand_do_write_ops
>         if (ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
>                 return -EINVAL;
>
> ooboffs is not initilized at mtd_write.
> So random data cause nand_do_write_ops return fail.

Looks like you have found the same thing:

http://lists.infradead.org/pipermail/linux-mtd/2010-September/032453.html
http://lists.infradead.org/pipermail/linux-mtd/2010-October/032538.html

> Signed-off-by: Frank Li <Frank.Li at freescale.com>
> ---
>  drivers/mtd/mtdchar.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> index b7ed09c..58839fa 100644
> --- a/drivers/mtd/mtdchar.c
> +++ b/drivers/mtd/mtdchar.c
> @@ -319,6 +319,7 @@ static ssize_t mtd_write(struct file
> *file, const char __user *buf, size_t count
>                 case MTD_MODE_RAW:
>                 {
>                         struct mtd_oob_ops ops;
> +                       memset(&ops, 0, sizeof(struct mtd_oob_ops));
>
>                         ops.mode = MTD_OOB_RAW;
>                         ops.datbuf = kbuf;



--
Jon Povey
jon.povey at racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 .
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB .

The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network




From wd at denx.de  Tue Oct 26 01:53:32 2010
From: wd at denx.de (Wolfgang Denk)
Date: Tue, 26 Oct 2010 07:53:32 +0200
Subject: UBIFS: mount based on UUID?
Message-ID: <20101026055332.B14FD152451@gemini.denx.de>

Hi,

is there any way to mount UBIFS based on the UUID like we can do for
"normal" file systems, i. e. by using "UUID=..." instead of a device
name in /etc/fstab ?

I see there is a UUID in the file system's super block, but I can't
see it is exposed to any sort of regular user interface.

Am I missing something?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
People with narrow minds usually have broad tongues.


From glecerf at gmail.com  Tue Oct 26 04:34:51 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 10:34:51 +0200
Subject: [PATCH 2/4] mtd: cfi_cmdset_0002: make sector erase command
	variable
In-Reply-To: <20101023102449.GB31623@pengutronix.de>
References: <20101022154015.11097.94660.stgit@dev.siriade.com>
	<20101022154020.11097.4024.stgit@dev.siriade.com>
	<20101023102449.GB31623@pengutronix.de>
Message-ID: <AANLkTikv7nO3uUBtO=1zrxiPuyGEzwu1HoUNMAF9SfVy@mail.gmail.com>

2010/10/23 Wolfram Sang <w.sang at pengutronix.de>:
>> +static map_word sector_erase_cmd = CMD(0x30);
>
> Uh? A static one? Why not per device?

Something like that ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 02-mtd-cfi_cmdset_0002-make-secto.patch
Type: application/octet-stream
Size: 3677 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101026/86a9665d/attachment.obj>

From dedekind1 at gmail.com  Tue Oct 26 05:03:15 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 26 Oct 2010 12:03:15 +0300
Subject: UBIFS: mount based on UUID?
In-Reply-To: <20101026055332.B14FD152451@gemini.denx.de>
References: <20101026055332.B14FD152451@gemini.denx.de>
Message-ID: <1288083795.2227.28.camel@localhost>

On Tue, 2010-10-26 at 07:53 +0200, Wolfgang Denk wrote:
> Hi,
> 
> is there any way to mount UBIFS based on the UUID like we can do for
> "normal" file systems, i. e. by using "UUID=..." instead of a device
> name in /etc/fstab ?
> 
> I see there is a UUID in the file system's super block, but I can't
> see it is exposed to any sort of regular user interface.
> 
> Am I missing something?

No, you are right, we do have UUID, but we added it just in case we need
it in the future, e.g., for NFS support, but we do not use it currently
because we did not need it. And we did not look at mounting by UUID - it
should be possible to do.

I'm a bit overloaded at the moment, but if I have time later, I can look
at it.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Tue Oct 26 05:26:26 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 11:26:26 +0200
Subject: [PATCH 2 1/3] mtd: cfi_util: add support for switching SST 39VF640xB
	chips into QRY mode
Message-ID: <20101026092626.5790.91523.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_util.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c
index e503b2c..360525c 100644
--- a/drivers/mtd/chips/cfi_util.c
+++ b/drivers/mtd/chips/cfi_util.c
@@ -77,6 +77,13 @@ int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
 	cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
 	if (cfi_qry_present(map, base, cfi))
 		return 1;
+	/* SST 39VF640xB */
+	cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+	if (cfi_qry_present(map, base, cfi))
+		return 1;
 	/* QRY not found */
 	return 0;
 }



From glecerf at gmail.com  Tue Oct 26 05:26:31 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 11:26:31 +0200
Subject: [PATCH 2 2/3] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <20101026092626.5790.91523.stgit@dev.siriade.com>
References: <20101026092626.5790.91523.stgit@dev.siriade.com>
Message-ID: <20101026092631.5790.95453.stgit@dev.siriade.com>

Add support for SST38VF640x chips in CFI mode.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 1934476..1cdba02 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -293,6 +293,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 	cfi->addr_unlock2 = 0x2AA;
 }
 
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	fixup_sst39vf_rev_b(mtd, param);
+
+	/*
+	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
+	 * it should report a size of 8KBytes (0x0020 *256).
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);
+}
+
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
 {
 	struct map_info *map = mtd->priv;
@@ -344,6 +359,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
 	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+	{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
+	{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
+	{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
+	{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
@@ -374,6 +393,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
 	if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
 	    extp->MajorVersion == '0')
 		extp->MajorVersion = '1';
+	/*
+	 * SST 38VF640x chips report major=0xFF / minor=0xFF.
+	 */
+	if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) {
+		extp->MajorVersion = '1';
+		extp->MinorVersion = '0';
+	}
 }
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)



From glecerf at gmail.com  Tue Oct 26 05:26:36 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 11:26:36 +0200
Subject: [PATCH 2 3/3] mtd: cfi_cmdset_0002: make sector erase command variable
In-Reply-To: <20101026092626.5790.91523.stgit@dev.siriade.com>
References: <20101026092626.5790.91523.stgit@dev.siriade.com>
Message-ID: <20101026092636.5790.29589.stgit@dev.siriade.com>

Some old SST chips use 0x50 as sector erase command, instead
of 0x30. Make this value variable to handle such chips.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   10 ++++++----
 drivers/mtd/chips/cfi_probe.c       |    2 ++
 include/linux/mtd/cfi.h             |    1 +
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 1cdba02..a6b6a78 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -291,6 +291,8 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 
 	cfi->addr_unlock1 = 0x555;
 	cfi->addr_unlock2 = 0x2AA;
+
+	cfi->sector_erase_cmd = 0x50;
 }
 
 static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
@@ -691,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 				 * there was an error (so leave the erase
 				 * routine to recover from it) or we trying to
 				 * use the erase-in-progress sector. */
-				map_write(map, CMD(0x30), chip->in_progress_block_addr);
+				map_write(map, CMD(cfi->sector_erase_cmd), chip->in_progress_block_addr);
 				chip->state = FL_ERASING;
 				chip->oldstate = FL_READY;
 				printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
@@ -744,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 	switch(chip->oldstate) {
 	case FL_ERASING:
 		chip->state = chip->oldstate;
-		map_write(map, CMD(0x30), chip->in_progress_block_addr);
+		map_write(map, CMD(cfi->sector_erase_cmd), chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -887,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
 			local_irq_disable();
 
 			/* Resume the write or erase operation */
-			map_write(map, CMD(0x30), adr);
+			map_write(map, CMD(cfi->sector_erase_cmd), adr);
 			chip->state = oldstate;
 			start = xip_currtime();
 		} else if (usec >= 1000000/HZ) {
@@ -1670,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	map_write(map, CMD(0x30), adr);
+	map_write(map, CMD(cfi->sector_erase_cmd), adr);
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index 8f5b96a..f030300 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 
 	cfi->cfi_mode = CFI_MODE_CFI;
 
+	cfi->sector_erase_cmd = 0x30;
+
 	/* Read the CFI info structure */
 	xip_disable_qry(base, map, cfi);
 	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index d2118b0..b97a0f8 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -289,6 +289,7 @@ struct cfi_private {
 				  must be of the same type. */
 	int mfr, id;
 	int numchips;
+	int sector_erase_cmd;
 	unsigned long chipshift; /* Because they're of the same type */
 	const char *im_name;	 /* inter_module name for cmdset_setup */
 	struct flchip chips[0];  /* per-chip data structure for each chip */



From B20596 at freescale.com  Tue Oct 26 05:35:24 2010
From: B20596 at freescale.com (Li Frank-B20596)
Date: Tue, 26 Oct 2010 02:35:24 -0700
Subject: [PATCH 1/1] MTD: Fix MTD_MODE_RAW write fail
In-Reply-To: <70E876B0EA86DD4BAF101844BC814DFE093EEF8EAC@Cloud.RL.local>
References: <1288061660-23363-1-git-send-email-Frank.Li@freescale.com>
	<70E876B0EA86DD4BAF101844BC814DFE093EEF8EAC@Cloud.RL.local>
Message-ID: <09EC74FE2C9E8444BF2FF67BD36E1D69B03B@039-SN1MPN1-002.039d.mgd.msft.net>

> 
> Looks like you have found the same thing:
> 
>
http://lists.infradead.org/pipermail/linux-mtd/2010-September/032453.htm
l
>
http://lists.infradead.org/pipermail/linux-mtd/2010-October/032538.html
> 

Yes. That's the same. 




From Artem.Bityutskiy at nokia.com  Tue Oct 26 05:36:01 2010
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Tue, 26 Oct 2010 12:36:01 +0300
Subject: [PATCH 1/1] mtd: OneNAND: fix bufferram management when chip
	has 2-planes.
In-Reply-To: <1287841434-3349-2-git-send-email-eballetbo@gmail.com>
References: <1287841434-3349-1-git-send-email-eballetbo@gmail.com>
	<1287841434-3349-2-git-send-email-eballetbo@gmail.com>
Message-ID: <1288085761.2227.40.camel@localhost>

On Sat, 2010-10-23 at 15:43 +0200, Enric Balletbo i Serra wrote:
> This patch adds code that I think was lost when it was applied the commit
>   5988af2319781bc8e0ce418affec4e09cfa77907 - mtd: Flex-OneNAND support
> 
> Test case:
>  1. Stress a jffs2 filesystem using
>     bonnie++ -u 0:0 -s 32 -m 16 -r 16
>  2. dmesg shows various 'Header CRC failed' errors like:
>     Header CRC failed on REF_PRISTINE node at 0x1e81315c: Read 0x000000e0,
>     calculated 0x564fc9e8
> 
> Tested on IGEP v2 board with a Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58)
> with 2 planes from Numonyx and CONFIG_MTD_ONENAND_2X_PROGRAM set to y
> 
> Signed-off-by: Enric Balletbo i Serra <eballetbo at gmail.com>

Kyungmin, would be nice to have your ack/nack.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From glecerf at gmail.com  Tue Oct 26 05:45:23 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 11:45:23 +0200
Subject: [PATCH v3] mtd: cfi_cmdset_0002: make sector erase command variable
Message-ID: <20101026094523.6578.44863.stgit@dev.siriade.com>

Some old SST chips use 0x50 as sector erase command, instead
of 0x30. Make this value variable to handle such chips.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   10 ++++++----
 drivers/mtd/chips/cfi_probe.c       |    2 ++
 include/linux/mtd/cfi.h             |    1 +
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 1cdba02..730e815 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -291,6 +291,8 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 
 	cfi->addr_unlock1 = 0x555;
 	cfi->addr_unlock2 = 0x2AA;
+
+	cfi->sector_erase_cmd = CMD(0x50);
 }
 
 static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
@@ -691,7 +693,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
 				 * there was an error (so leave the erase
 				 * routine to recover from it) or we trying to
 				 * use the erase-in-progress sector. */
-				map_write(map, CMD(0x30), chip->in_progress_block_addr);
+				map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
 				chip->state = FL_ERASING;
 				chip->oldstate = FL_READY;
 				printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__);
@@ -744,7 +746,7 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 	switch(chip->oldstate) {
 	case FL_ERASING:
 		chip->state = chip->oldstate;
-		map_write(map, CMD(0x30), chip->in_progress_block_addr);
+		map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr);
 		chip->oldstate = FL_READY;
 		chip->state = FL_ERASING;
 		break;
@@ -887,7 +889,7 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
 			local_irq_disable();
 
 			/* Resume the write or erase operation */
-			map_write(map, CMD(0x30), adr);
+			map_write(map, cfi->sector_erase_cmd, adr);
 			chip->state = oldstate;
 			start = xip_currtime();
 		} else if (usec >= 1000000/HZ) {
@@ -1670,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
 	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
-	map_write(map, CMD(0x30), adr);
+	map_write(map, cfi->sector_erase_cmd, adr);
 
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index 8f5b96a..d255352 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -177,6 +177,8 @@ static int __xipram cfi_chip_setup(struct map_info *map,
 
 	cfi->cfi_mode = CFI_MODE_CFI;
 
+	cfi->sector_erase_cmd = CMD(0x30);
+
 	/* Read the CFI info structure */
 	xip_disable_qry(base, map, cfi);
 	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index d2118b0..4dd0c2c 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -289,6 +289,7 @@ struct cfi_private {
 				  must be of the same type. */
 	int mfr, id;
 	int numchips;
+	map_word sector_erase_cmd;
 	unsigned long chipshift; /* Because they're of the same type */
 	const char *im_name;	 /* inter_module name for cmdset_setup */
 	struct flchip chips[0];  /* per-chip data structure for each chip */



From dedekind1 at gmail.com  Tue Oct 26 05:45:11 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 26 Oct 2010 12:45:11 +0300
Subject: [PATCH v2 2/2] mtd-utils: nanddump: add 64-bit support,
	utilize libmtd
In-Reply-To: <AANLkTikG52xr1sj9TabRckrCOLk9Np=PgsSidXR+TyZ6@mail.gmail.com>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>
	<1287645577-13538-3-git-send-email-computersforpeace@gmail.com>
	<1288034427.1865.9.camel@brekeke>
	<AANLkTikG52xr1sj9TabRckrCOLk9Np=PgsSidXR+TyZ6@mail.gmail.com>
Message-ID: <1288086311.2227.44.camel@localhost>

On Mon, 2010-10-25 at 15:54 -0400, Mike Frysinger wrote:
> On Mon, Oct 25, 2010 at 15:20, Artem Bityutskiy wrote:
> > Mike, thanks for reviewing. You did not provide formal "Reviewed-by"
> > though, so I did not add this tag, assuming you did this for purposes,
> > because for other patches you provide ready to copy-paste tags.
> 
> i'm not in the habit of using that tag, so i dont remember to post it

Well, you did answer with proper Acked-by recently. But if you do not
provide tag, I cannot make it myself and add it to the patch, because
you might not want it.

Anyway, if you want to have your reviewed-by or acked by tags in any
patch I deal with, send them explicitly. and I'll add them.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From david.woodhouse at intel.com  Tue Oct 26 05:48:24 2010
From: david.woodhouse at intel.com (David Woodhouse)
Date: Tue, 26 Oct 2010 10:48:24 +0100
Subject: [PATCH v3] mtd: cfi_cmdset_0002: make sector erase command
	variable
In-Reply-To: <20101026094523.6578.44863.stgit@dev.siriade.com>
References: <20101026094523.6578.44863.stgit@dev.siriade.com>
Message-ID: <1288086504.29264.22.camel@macbook.infradead.org>

On Tue, 2010-10-26 at 10:45 +0100, Guillaume LECERF wrote:
> Some old SST chips use 0x50 as sector erase command, instead
> of 0x30. Make this value variable to handle such chips.
> 
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com> 


Looks good. Let me know when it's tested :)

Thanks.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From glecerf at gmail.com  Tue Oct 26 05:55:29 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 11:55:29 +0200
Subject: [PATCH] mtd: cfi_cmdset_0001: use defined value of
	P_ID_INTEL_PERFORMANCE instead of hardcoded one
Message-ID: <20101026095529.6964.80927.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0001.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 9e2b7e9..ad9268b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1496,7 +1496,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
 
 	switch (mode) {
 	case FL_WRITING:
-		write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41);
+		write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0x40) : CMD(0x41);
 		break;
 	case FL_OTP_WRITE:
 		write_cmd = CMD(0xc0);
@@ -1661,7 +1661,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 	cmd_adr = adr & ~(wbufsize-1);
 
 	/* Let's determine this according to the interleave only once */
-	write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9);
+	write_cmd = (cfi->cfiq->P_ID != P_ID_INTEL_PERFORMANCE) ? CMD(0xe8) : CMD(0xe9);
 
 	mutex_lock(&chip->mutex);
 	ret = get_chip(map, chip, cmd_adr, FL_WRITING);



From w.sang at pengutronix.de  Tue Oct 26 06:21:40 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Tue, 26 Oct 2010 12:21:40 +0200
Subject: [PATCH v3] mtd: cfi_cmdset_0002: make sector erase command
	variable
In-Reply-To: <20101026094523.6578.44863.stgit@dev.siriade.com>
References: <20101026094523.6578.44863.stgit@dev.siriade.com>
Message-ID: <20101026102140.GA31843@pengutronix.de>

On Tue, Oct 26, 2010 at 11:45:23AM +0200, Guillaume LECERF wrote:
> Some old SST chips use 0x50 as sector erase command, instead
> of 0x30. Make this value variable to handle such chips.
> 
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>

I like that :)

Acked-by: Wolfram Sang <w.sang at pengutronix.de>

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101026/f2dd9876/attachment.sig>

From w.sang at pengutronix.de  Tue Oct 26 06:25:48 2010
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Tue, 26 Oct 2010 12:25:48 +0200
Subject: [PATCH 2 2/3] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <20101026092631.5790.95453.stgit@dev.siriade.com>
References: <20101026092626.5790.91523.stgit@dev.siriade.com>
	<20101026092631.5790.95453.stgit@dev.siriade.com>
Message-ID: <20101026102548.GB31843@pengutronix.de>

On Tue, Oct 26, 2010 at 11:26:31AM +0200, Guillaume LECERF wrote:
> Add support for SST38VF640x chips in CFI mode.
> 
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
> Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
> ---
>  drivers/mtd/chips/cfi_cmdset_0002.c |   26 ++++++++++++++++++++++++++
>  1 files changed, 26 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
> index 1934476..1cdba02 100644
> --- a/drivers/mtd/chips/cfi_cmdset_0002.c
> +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
> @@ -293,6 +293,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
>  	cfi->addr_unlock2 = 0x2AA;
>  }
>  
> +static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
> +{
> +	struct map_info *map = mtd->priv;
> +	struct cfi_private *cfi = map->fldrv_priv;
> +
> +	fixup_sst39vf_rev_b(mtd, param);
> +
> +	/*
> +	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
> +	 * it should report a size of 8KBytes (0x0020 *256).

Spaces after operators?

> +	 */
> +	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
> +	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);

Should be "adjusting", otherwise it sounds like a task for the user to do.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101026/23a88365/attachment.sig>

From david.woodhouse at intel.com  Tue Oct 26 06:29:17 2010
From: david.woodhouse at intel.com (David Woodhouse)
Date: Tue, 26 Oct 2010 11:29:17 +0100
Subject: [PATCH 2 2/3] mtd: cfi_cmdset_0002: add CFI detection for SST
	38VF640x chips
In-Reply-To: <20101026102548.GB31843@pengutronix.de>
References: <20101026092626.5790.91523.stgit@dev.siriade.com>
	<20101026092631.5790.95453.stgit@dev.siriade.com>
	<20101026102548.GB31843@pengutronix.de>
Message-ID: <1288088957.29264.24.camel@macbook.infradead.org>

On Tue, 2010-10-26 at 11:25 +0100, Wolfram Sang wrote:
> > +	/*
> > +	 * CFI reports 1024 sectors (0x03ff +1) of 64KBytes (0x0100 *256) where
> > +	 * it should report a size of 8KBytes (0x0020 *256).
> 
> Spaces after operators?
> 
> > +	 */
> > +	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
> > +	pr_warning("%s: Bad 38VF640x CFI data, adjust sector size from 64 to 8KBytes\n", mtd->name);
> 
> Should be "adjusting", otherwise it sounds like a task for the user to do.

And s/KBytes/KiB/ while we're nitpicking.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From kyungmin.park at samsung.com  Tue Oct 26 06:29:38 2010
From: kyungmin.park at samsung.com (Kyungmin Park)
Date: Tue, 26 Oct 2010 19:29:38 +0900
Subject: [PATCH 1/1] mtd: OneNAND: fix bufferram management when chip has
	2-planes.
In-Reply-To: <1288085761.2227.40.camel@localhost>
References: <1287841434-3349-1-git-send-email-eballetbo@gmail.com>
	<1287841434-3349-2-git-send-email-eballetbo@gmail.com>
	<1288085761.2227.40.camel@localhost>
Message-ID: <AANLkTikKNNgnzYZ50XcB+TqEGs=RBXUet=L5PsVy+r02@mail.gmail.com>

On Tue, Oct 26, 2010 at 6:36 PM, Artem Bityutskiy
<Artem.Bityutskiy at nokia.com> wrote:
> On Sat, 2010-10-23 at 15:43 +0200, Enric Balletbo i Serra wrote:
>> This patch adds code that I think was lost when it was applied the commit
>> ? 5988af2319781bc8e0ce418affec4e09cfa77907 - mtd: Flex-OneNAND support
>>
>> Test case:
>> ?1. Stress a jffs2 filesystem using
>> ? ? bonnie++ -u 0:0 -s 32 -m 16 -r 16
>> ?2. dmesg shows various 'Header CRC failed' errors like:
>> ? ? Header CRC failed on REF_PRISTINE node at 0x1e81315c: Read 0x000000e0,
>> ? ? calculated 0x564fc9e8
>>
>> Tested on IGEP v2 board with a Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58)
>> with 2 planes from Numonyx and CONFIG_MTD_ONENAND_2X_PROGRAM set to y
>>
>> Signed-off-by: Enric Balletbo i Serra <eballetbo at gmail.com>
>
> Kyungmin, would be nice to have your ack/nack.
Sorry for late reply

One more check, it seems to use the invalidate instead of update bufferram.
In case of 2X PROGRAM, it always uses the BUFFERRAM0 so invalidate
another bufferram.

Don't set the bufferram index.

Thank you,
Kyungmin Park
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>


From glecerf at gmail.com  Tue Oct 26 06:31:55 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Tue, 26 Oct 2010 12:31:55 +0200
Subject: [PATCH] mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips
Message-ID: <20101026103155.8202.76596.stgit@dev.siriade.com>

Add support for SST38VF640x chips in CFI mode.

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
Signed-off-by: yidong zhang <zhangyd6 at gmail.com>
---
 drivers/mtd/chips/cfi_cmdset_0002.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 1934476..2da3818 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -293,6 +293,21 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
 	cfi->addr_unlock2 = 0x2AA;
 }
 
+static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	fixup_sst39vf_rev_b(mtd, param);
+
+	/*
+	 * CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where
+	 * it should report a size of 8KBytes (0x0020*256).
+	 */
+	cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
+	pr_warning("%s: Bad 38VF640x CFI data, adjusting sector size from 64 to 8KiB\n", mtd->name);
+}
+
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
 {
 	struct map_info *map = mtd->priv;
@@ -344,6 +359,10 @@ static struct cfi_fixup cfi_fixup_table[] = {
 	{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
 	{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
+	{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
+	{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
+	{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
+	{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
 #endif
@@ -374,6 +393,13 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi,
 	if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
 	    extp->MajorVersion == '0')
 		extp->MajorVersion = '1';
+	/*
+	 * SST 38VF640x chips report major=0xFF / minor=0xFF.
+	 */
+	if (cfi->mfr == CFI_MFR_SST && (cfi->id >> 4) == 0x0536) {
+		extp->MajorVersion = '1';
+		extp->MinorVersion = '0';
+	}
 }
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)



From wd at denx.de  Tue Oct 26 12:29:00 2010
From: wd at denx.de (Wolfgang Denk)
Date: Tue, 26 Oct 2010 18:29:00 +0200
Subject: UBIFS: mount based on UUID?
In-Reply-To: <1288083795.2227.28.camel@localhost>
References: <20101026055332.B14FD152451@gemini.denx.de>
	<1288083795.2227.28.camel@localhost>
Message-ID: <20101026162900.423EC1365D8@gemini.denx.de>

Dear Artem,

In message <1288083795.2227.28.camel at localhost> you wrote:
>
> No, you are right, we do have UUID, but we added it just in case we need
> it in the future, e.g., for NFS support, but we do not use it currently
> because we did not need it. And we did not look at mounting by UUID - it
> should be possible to do.

I see.

> I'm a bit overloaded at the moment, but if I have time later, I can look
> at it.

Thanks a lot.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Quote from a recent meeting:   "We are going to continue having these
meetings everyday until I find out why no work is getting done."


From kmpark at infradead.org  Wed Oct 27 01:34:24 2010
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 27 Oct 2010 14:34:24 +0900
Subject: UBIFS: mount based on UUID?
In-Reply-To: <20101026162900.423EC1365D8@gemini.denx.de>
References: <20101026055332.B14FD152451@gemini.denx.de>
	<1288083795.2227.28.camel@localhost>
	<20101026162900.423EC1365D8@gemini.denx.de>
Message-ID: <AANLkTikc8fpTtTUXs2KaF3h4Bd6TH6kjPr_F3pN=e5u=@mail.gmail.com>

On Wed, Oct 27, 2010 at 1:29 AM, Wolfgang Denk <wd at denx.de> wrote:
> Dear Artem,
>
> In message <1288083795.2227.28.camel at localhost> you wrote:
>>
>> No, you are right, we do have UUID, but we added it just in case we need
>> it in the future, e.g., for NFS support, but we do not use it currently
>> because we did not need it. And we did not look at mounting by UUID - it
>> should be possible to do.
>
> I see.
>
>> I'm a bit overloaded at the moment, but if I have time later, I can look
>> at it.

Hi Artem,
I'm also waiting this feature. now it used for script for parsing
mount ubifs. but if support UUID, I will use this one.

Thank you,
Kyungmin Park
>
> Thanks a lot.
>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH, ? ? MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> Quote from a recent meeting: ? "We are going to continue having these
> meetings everyday until I find out why no work is getting done."
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From g.liakhovetski at gmx.de  Wed Oct 27 02:52:29 2010
From: g.liakhovetski at gmx.de (Guennadi Liakhovetski)
Date: Wed, 27 Oct 2010 08:52:29 +0200 (CEST)
Subject: commit 432dc821 breaks machines
Message-ID: <Pine.LNX.4.64.1010270842580.7190@axis700.grange>

Hi

commit 432dc821c90114f9b0e00f6752a700e937516ade
Author: H Hartley Sweeten <hartleys at visionengravers.com>
Date:   Thu Aug 19 18:18:21 2010 -0700

    mtd: cleanup Kconfig dependencies

breaks machines by undefining macros like CONFIG_MTD_MAP_BANK_WIDTH_*. 
Previously the Kconfig entries like

config MTD_MAP_BANK_WIDTH_1
	bool "Support  8-bit buswidth" if MTD_CFI_GEOMETRY
	default y

meant, that if MTD_CFI_GEOMETRY is not selected, this config entry is not 
_displayed_, and default selections are used. Now, with that "if" removed 
and all these Kconfig entries put under a common

if MTD_CFI_GEOMETRY

none of these options get selected by default. Please, revert or otherwise 
fix this part.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/


From dwmw2 at infradead.org  Wed Oct 27 04:31:15 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Wed, 27 Oct 2010 09:31:15 +0100 (BST)
Subject: commit 432dc821 breaks machines
In-Reply-To: <Pine.LNX.4.64.1010270842580.7190@axis700.grange>
References: <Pine.LNX.4.64.1010270842580.7190@axis700.grange>
Message-ID: <alpine.LFD.2.00.1010270930230.23421@dwoodhou-mobl2.ger.corp.intel.com>

On Wed, 27 Oct 2010, Guennadi Liakhovetski wrote:

> Hi
>
> commit 432dc821c90114f9b0e00f6752a700e937516ade
> Author: H Hartley Sweeten <hartleys at visionengravers.com>
> Date:   Thu Aug 19 18:18:21 2010 -0700
>
>    mtd: cleanup Kconfig dependencies
>
> breaks machines by undefining macros like CONFIG_MTD_MAP_BANK_WIDTH_*.

Thanks. This should be fixed in today's linux-next.

-- 
dwmw2



From dedekind1 at gmail.com  Wed Oct 27 03:57:47 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 27 Oct 2010 10:57:47 +0300
Subject: UBIFS: mount based on UUID?
In-Reply-To: <AANLkTikc8fpTtTUXs2KaF3h4Bd6TH6kjPr_F3pN=e5u=@mail.gmail.com>
References: <20101026055332.B14FD152451@gemini.denx.de>
	<1288083795.2227.28.camel@localhost>
	<20101026162900.423EC1365D8@gemini.denx.de>
	<AANLkTikc8fpTtTUXs2KaF3h4Bd6TH6kjPr_F3pN=e5u=@mail.gmail.com>
Message-ID: <1288166267.2195.0.camel@localhost>

On Wed, 2010-10-27 at 14:34 +0900, Kyungmin Park wrote:
> On Wed, Oct 27, 2010 at 1:29 AM, Wolfgang Denk <wd at denx.de> wrote:
> > Dear Artem,
> >
> > In message <1288083795.2227.28.camel at localhost> you wrote:
> >>
> >> No, you are right, we do have UUID, but we added it just in case we need
> >> it in the future, e.g., for NFS support, but we do not use it currently
> >> because we did not need it. And we did not look at mounting by UUID - it
> >> should be possible to do.
> >
> > I see.
> >
> >> I'm a bit overloaded at the moment, but if I have time later, I can look
> >> at it.
> 
> Hi Artem,
> I'm also waiting this feature. now it used for script for parsing
> mount ubifs. but if support UUID, I will use this one.

I see. But there is always an option to just do it and submit a patch,
do not forget about this :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From hartleys at visionengravers.com  Wed Oct 27 12:18:50 2010
From: hartleys at visionengravers.com (H Hartley Sweeten)
Date: Wed, 27 Oct 2010 11:18:50 -0500
Subject: commit 432dc821 breaks machines
In-Reply-To: <Pine.LNX.4.64.1010270842580.7190@axis700.grange>
References: <Pine.LNX.4.64.1010270842580.7190@axis700.grange>
Message-ID: <0D753D10438DA54287A00B027084269764819C5D74@AUSP01VMBX24.collaborationhost.net>

On Tuesday, October 26, 2010 11:52 PM, Guennadi Liakhovetski wrote:
>
> Hi
>
> commit 432dc821c90114f9b0e00f6752a700e937516ade
> Author: H Hartley Sweeten <hartleys at visionengravers.com>
> Date:   Thu Aug 19 18:18:21 2010 -0700
>
>     mtd: cleanup Kconfig dependencies
>
> breaks machines by undefining macros like CONFIG_MTD_MAP_BANK_WIDTH_*. 
> Previously the Kconfig entries like
>
> config MTD_MAP_BANK_WIDTH_1
> 	bool "Support  8-bit buswidth" if MTD_CFI_GEOMETRY
> 	default y
>
> meant, that if MTD_CFI_GEOMETRY is not selected, this config entry is not 
> _displayed_, and default selections are used. Now, with that "if" removed 
> and all these Kconfig entries put under a common

Yah, I overlooked that part.

>
> if MTD_CFI_GEOMETRY
>
> none of these options get selected by default. Please, revert or otherwise 
> fix this part.

I believe David Woodhouse has already reverted the commit.

Sorry for the trouble,
Hartley

From dedekind1 at gmail.com  Wed Oct 27 14:26:25 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 27 Oct 2010 21:26:25 +0300
Subject: [PATCH] write bad block marker even with BBT
In-Reply-To: <4CC54223.2050401@parrot.com>
References: <4CC54223.2050401@parrot.com>
Message-ID: <1288203985.1766.6.camel@brekeke>

Sorry for being PITA, but

On Mon, 2010-10-25 at 10:38 +0200, Matthieu CASTET wrote:
> +
> +	/* Write the bad block marker if we don't have BBT, or driver
> +	 * request it (in case the bootloader doesn't support reading it
> +	 * or we loose BBT).
> +	 */

Still not proper comment :-)

> +	if (!(chip->options & NAND_USE_FLASH_BBT) || chip->options & NAND_WRITE_BB) {
>  		nand_get_device(chip, mtd, FL_WRITING);
>  
>  		/* Write to first two pages and to byte 1 and 6 if necessary.
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 102e12c..2efd2f9 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -215,6 +215,8 @@ typedef enum {
>  #define NAND_OWN_BUFFERS	0x00040000
>  /* Chip may not exist, so silence any errors in scan */
>  #define NAND_SCAN_SILENT_NODEV	0x00080000
> +/* in case of NAND_USE_FLASH_BBT, write also bad block marker */
> +#define NAND_WRITE_BB	0x00100000

I think the comment should be a bit more descriptive and tell that this
is about using BBT _and_ writing BB marker to OOB area. Use proper
comment style, start with capital letter.

Also, add a BUG_ON to catch misuse cases when NAND_WRITE_BB is used
without NAND_USE_FLASH_BBT - they should go in pair.

And also, how about cases when BBT is updated, but OOB did not because
of a power cut :-)) ?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Wed Oct 27 14:30:30 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 27 Oct 2010 21:30:30 +0300
Subject: Issues with ubi utils Makefile
In-Reply-To: <AANLkTinDuG62AapBDGvcjjJFUDxQDxcik3zEs2Gkm_st@mail.gmail.com>
References: <201010211643.33332.manningc2@actrix.gen.nz>
	<1288033416.1865.2.camel@brekeke>
	<AANLkTikd9uTV+8bRhjKt8P0vXC6p0FUbWd=bb6k2FGKi@mail.gmail.com>
	<AANLkTinDuG62AapBDGvcjjJFUDxQDxcik3zEs2Gkm_st@mail.gmail.com>
Message-ID: <1288204230.1766.7.camel@brekeke>

On Mon, 2010-10-25 at 16:57 -0400, Mike Frysinger wrote:
> On Mon, Oct 25, 2010 at 16:45, Mike Frysinger wrote:
> > On Mon, Oct 25, 2010 at 15:03, Artem Bityutskiy wrote:
> >> Commit 96a4f76f2e9dad7fdbd6fd7740de44bc90d5769e broke 'make install'.
> >> Before that commit, $DESTDIR was undefined, so  ${DESTDIR}/${SBINDIR}
> >> was /usr/sbin, and after the commit $DESTDIR became /usr/local, so
> >> ${DESTDIR}/${SBINDIR} became /usr/local//usr/sbin, which is wrong.
> >
> > that isnt really true.  DESTDIR had value in makefiles before my changes.
> >
> >> Fix this by making $DESTDIR become the distination directory of installing,
> >> i.e. 'DESTDIR ?= /usr' and making SBINDIR become just 'sbin'.
> >
> > i'd rather we change DESTDIR to match the standard -- it's a "root"
> > prefix only.  so the default should be:
> > DESTDIR ?=
> 
> i guess this is also why i never noticed before.  i never do plain
> `make install` since i'm not root and i dont want it clobbering
> things.  i always do `make install DESTDIR=$PWD/foo` when testing and
> in that regard, it works fine.  so i guess we want this simple change:
> --- a/common.mk
> +++ b/common.mk
> @@ -20,7 +20,7 @@ ifneq ($(WITHOUT_LARGEFILE), 1)
>    CPPFLAGS += -D_FILE_OFFSET_BITS=64
>  endif
> 
> -DESTDIR ?= /usr/local
> +DESTDIR?=
>  PREFIX=/usr
>  EXEC_PREFIX=$(PREFIX)
>  SBINDIR=$(EXEC_PREFIX)/sbin

Ok, pushed, made you the author, fabricated your signed-off-by as well.
Thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From computersforpeace at gmail.com  Wed Oct 27 21:08:59 2010
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 27 Oct 2010 18:08:59 -0700
Subject: [PATCH v2 1/2] mtd-utils: nanddump/nandwrite: style, signed-ness, 
	printing fixups
In-Reply-To: <1288034112.1865.7.camel@brekeke>
References: <1287645577-13538-1-git-send-email-computersforpeace@gmail.com>	
	<1287645577-13538-2-git-send-email-computersforpeace@gmail.com>
	<1288034112.1865.7.camel@brekeke>
Message-ID: <4CC8CD2B.2040801@gmail.com>

On 10/25/2010 12:15 PM, Artem Bityutskiy wrote:
> Mike is right, it is much better to separate functional and cleanup
> changes, even split different clean-up changes into several patches.
> Maintaining this stuff and reviewing patches takes time, and splitting
> helps a lot. Let's push this patch but please, try to splint patches on
> more smaller pieces. Yes, it'll be more work for you, but less for me.
> But when submitters take more burden and maintainer less - the system
> scales better. Take into account that I'm doing this stuff just because
> I like MTD and do not like see people's patches lost, so little help in
> form of perfectly split micro-patches is appreciated.
> 
> Pushed, thanks!

Right, this makes perfect sense. I will remind myself of this for future
patches. I certainly don't want to make things more difficult than
necessary for you!

Oh, and thanks for the push.

Brian


From B20596 at freescale.com  Wed Oct 27 21:30:01 2010
From: B20596 at freescale.com (Li Frank-B20596)
Date: Wed, 27 Oct 2010 18:30:01 -0700
Subject: [PATCH 1/1] MTD: Fix wrong check register_blkdev return value
In-Reply-To: <1288062139-2192-1-git-send-email-Frank.Li@freescale.com>
References: <1288062139-2192-1-git-send-email-Frank.Li@freescale.com>
Message-ID: <09EC74FE2C9E8444BF2FF67BD36E1D69CBB6@039-SN1MPN1-002.039d.mgd.msft.net>

Why no one review my patch? That's fix a bug when major is zero at mtd
blktrans layer.

> -----Original Message-----
> From: Li Frank-B20596
> Sent: Tuesday, October 26, 2010 11:02 AM
> To: linux-mtd at lists.infradead.org
> Cc: Li Frank-B20596
> Subject: [PATCH 1/1] MTD: Fix wrong check register_blkdev return value
> 
> register_blkdev return 1..255 when major = 0.
> 
> if (ret ) {
> 	printk(KERN_WARNING "Unable to register %s block device on
> major %d: %d\n",
> 		tr->name, tr->major, ret);
> 	      mutex_unlock(&mtd_table_mutex);
> 	return ret;
> }
> 
> Above code will return fail when register_blkdev return allocated
major
> number.
> 
> Signed-off-by: Frank Li <Frank.Li at freescale.com>
> ---
>  drivers/mtd/mtd_blkdevs.c |    5 ++++-
>  1 files changed, 4 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
> index a919587..63790e9 100644
> --- a/drivers/mtd/mtd_blkdevs.c
> +++ b/drivers/mtd/mtd_blkdevs.c
> @@ -502,13 +502,16 @@ int register_mtd_blktrans(struct
mtd_blktrans_ops
> *tr)
>  	mutex_lock(&mtd_table_mutex);
> 
>  	ret = register_blkdev(tr->major, tr->name);
> -	if (ret) {
> +	if (ret < 0) {
>  		printk(KERN_WARNING "Unable to register %s block device
on
> major %d: %d\n",
>  		       tr->name, tr->major, ret);
>  		mutex_unlock(&mtd_table_mutex);
>  		return ret;
>  	}
> 
> +	if (ret)
> +		tr->major = ret;
> +
>  	tr->blkshift = ffs(tr->blksize) - 1;
> 
>  	INIT_LIST_HEAD(&tr->devs);
> --
> 1.7.1





From schiele067979 at yahoo.es  Thu Oct 28 06:20:29 2010
From: schiele067979 at yahoo.es (Kyejou)
Date: Thu, 28 Oct 2010 18:20:29 +0800
Subject: Nrwbh Hotyc Fbglqvaf
Message-ID: <811368.40827.bm@smtp102.mail.ac4.yahoo.com>

???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????
???????????

From s-ghorai at ti.com  Thu Oct 28 10:11:53 2010
From: s-ghorai at ti.com (Ghorai, Sukumar)
Date: Thu, 28 Oct 2010 19:41:53 +0530
Subject: [PATCH v5 1/5] omap gpmc: enable irq mode in gpmc
References: <1285594634-19277-1-git-send-email-s-ghorai@ti.com>
	<1285594634-19277-2-git-send-email-s-ghorai@ti.com>
	<20100928222727.GS3117@atomide.com> 
Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B0356AEEDE2@dbde02.ent.ti.com>

Tony,

> -----Original Message-----
> From: Ghorai, Sukumar
> Sent: Wednesday, September 29, 2010 12:08 PM
> To: 'Tony Lindgren'
> Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; linux-arm-
> kernel at lists.infradead.org
> Subject: RE: [PATCH v5 1/5] omap gpmc: enable irq mode in gpmc
> 
> 
[..snip..]

> > > diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-
> > omap2/board-3430sdp.c
> > > index 67b95b5..549cd62 100644
> > > --- a/arch/arm/mach-omap2/board-3430sdp.c
> > > +++ b/arch/arm/mach-omap2/board-3430sdp.c
> > > @@ -328,6 +328,7 @@ static void __init omap_3430sdp_init_irq(void)
> > >  	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
> > >  	omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL);
> > >  	omap_init_irq();
> > > +	gpmc_init();
> > >  	omap_gpio_init();
> > >  }
> > ...
> >
> > You can avoid adding gpmc_init() by making it a subsys_initcall().
> > Just make sure you return early from it with if (!cpu_class_is_omap2()).
> [Ghorai] will do
> >
[Ghorai] I was trying this and no success, as nand_init() get called before  subsys_initcall(gpmc_init);

126 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board") 
..
130         .init_irq       = omap_zoom_init_irq,
131         .init_machine   = omap_zoom_init,
..

Step-(n):
	kernel_init() -> customize_machine() 
             -> omap_zoom_init() -> gpmc_nand_init() -> which call gpmc
                functions, that's crashing, as gpmc is not initialized.

Step-(n+1):
	Followed by subsys_initcall(gpmc_init)

So I will incorporate the other input and will re-submit.
[..snip..]


From joakim.tjernlund at transmode.se  Thu Oct 28 10:24:27 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 28 Oct 2010 16:24:27 +0200
Subject: Preventing FS full
Message-ID: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>


Is there any way to temporarily lower the FS full limit(preferably on a process basis)
on JFFS2?

I want to safeguard the OS from FS full due to some process filling up the disk.

    Jocke



From dwmw2 at infradead.org  Thu Oct 28 10:39:08 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Thu, 28 Oct 2010 15:39:08 +0100
Subject: Preventing FS full
In-Reply-To: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
References: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
Message-ID: <1288276748.1538.58.camel@macbook.infradead.org>

On Thu, 2010-10-28 at 16:24 +0200, Joakim Tjernlund wrote:
> Is there any way to temporarily lower the FS full limit(preferably on
> a process basis) on JFFS2?
> 
> I want to safeguard the OS from FS full due to some process filling up
> the disk.

The thresholds are in the resv_blocks_* variables and should be
relatively easy to tweak. I've toyed with the idea of exposing them in
sysfs. Tweaking them on a per-process basis is slightly less trivial but
shouldn't be that hard... you could add a certain number if the process
has CAP_SYS_RESOURCE or something.

Although it should *never* be possible to actually fill the space.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From dedekind1 at gmail.com  Thu Oct 28 10:52:10 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 28 Oct 2010 17:52:10 +0300
Subject: Preventing FS full
In-Reply-To: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
References: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
Message-ID: <1288277530.2083.56.camel@localhost>

On Thu, 2010-10-28 at 16:24 +0200, Joakim Tjernlund wrote:
> Is there any way to temporarily lower the FS full limit(preferably on a process basis)
> on JFFS2?
> 
> I want to safeguard the OS from FS full due to some process filling up the disk.

Mainstream FSes like ext3 can limit this on per-user or per-group basis,
and we had a similar thing for JFFS2, do not remember if we upstreamed
this, though. But I did send patches to the mtd ML.

FS has not idea about processes - the information about them is not
stored on the media, and it is very dynamic and unpredictable. I think
it is disaster to try to limit anything in the FS on per-process basis,
just makes little sense for me.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Oct 28 10:54:55 2010
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 28 Oct 2010 17:54:55 +0300
Subject: Preventing FS full
In-Reply-To: <1288277530.2083.56.camel@localhost>
References: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
	<1288277530.2083.56.camel@localhost>
Message-ID: <1288277695.2083.58.camel@localhost>

On Thu, 2010-10-28 at 17:52 +0300, Artem Bityutskiy wrote:
> On Thu, 2010-10-28 at 16:24 +0200, Joakim Tjernlund wrote:
> > Is there any way to temporarily lower the FS full limit(preferably on a process basis)
> > on JFFS2?
> > 
> > I want to safeguard the OS from FS full due to some process filling up the disk.
> 
> Mainstream FSes like ext3 can limit this on per-user or per-group basis,
> and we had a similar thing for JFFS2, do not remember if we upstreamed
> this, though. But I did send patches to the mtd ML.

Hmm, no, probably my memory is bad, but it seems ext3 only has the
reserve for root, see mkfs.ext3 -m option.

In UBIFS you can specify user ID or group ID of the owner of the
reserve. And we had done the same for JFFS2 long time ago.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From joakim.tjernlund at transmode.se  Thu Oct 28 11:31:37 2010
From: joakim.tjernlund at transmode.se (Joakim Tjernlund)
Date: Thu, 28 Oct 2010 17:31:37 +0200
Subject: Preventing FS full
In-Reply-To: <1288276748.1538.58.camel@macbook.infradead.org>
References: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
	<1288276748.1538.58.camel@macbook.infradead.org>
Message-ID: <OF3909837A.3650BEA2-ONC12577CA.0054F770-C12577CA.00554ADB@transmode.se>

David Woodhouse <dwmw2 at infradead.org> wrote on 2010/10/28 16:39:08:
>
> On Thu, 2010-10-28 at 16:24 +0200, Joakim Tjernlund wrote:
> > Is there any way to temporarily lower the FS full limit(preferably on
> > a process basis) on JFFS2?
> >
> > I want to safeguard the OS from FS full due to some process filling up
> > the disk.
>
> The thresholds are in the resv_blocks_* variables and should be
> relatively easy to tweak. I've toyed with the idea of exposing them in
> sysfs. Tweaking them on a per-process basis is slightly less trivial but
> shouldn't be that hard... you could add a certain number if the process
> has CAP_SYS_RESOURCE or something.

Will have a look.

>
> Although it should *never* be possible to actually fill the space.

hmm, don't quite get that. Isn't it possible to write until the FS is full.
Surley you must at some pint return ENOSPC to user space and then you
cannot write more files. or ...?

       Jocke



From dwmw2 at infradead.org  Thu Oct 28 17:34:57 2010
From: dwmw2 at infradead.org (David Woodhouse)
Date: Thu, 28 Oct 2010 22:34:57 +0100
Subject: Preventing FS full
In-Reply-To: <OF3909837A.3650BEA2-ONC12577CA.0054F770-C12577CA.00554ADB@transmode.se>
References: <OF2C2A2D93.9DE54A3F-ONC12577CA.004EC5B1-C12577CA.004F2498@transmode.se>
	<1288276748.1538.58.camel@macbook.infradead.org>
	<OF3909837A.3650BEA2-ONC12577CA.0054F770-C12577CA.00554ADB@transmode.se>
Message-ID: <1288301697.25013.10.camel@macbook.infradead.org>

On Thu, 2010-10-28 at 17:31 +0200, Joakim Tjernlund wrote:
> hmm, don't quite get that. Isn't it possible to write until the FS is
> full.
> Surley you must at some pint return ENOSPC to user space and then you
> cannot write more files. or ...?

Oh, yeah -- that kind of full. Just not the *broken* kind of "eep,
there's no more space for GC" full :)

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse at intel.com                              Intel Corporation



From Frisky.Li at Emerson.com  Fri Oct 29 01:23:08 2010
From: Frisky.Li at Emerson.com (Frisky.Li at Emerson.com)
Date: Fri, 29 Oct 2010 05:23:08 +0000
Subject: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found, on NAND flash
Message-ID: <608527F32EA5304EAFF29F54C602AA89CCA52B@usstlz-pmsgem09.emrsn.org>

Hi all,
I'm debugging JFFS2 file system on NAND FLASH NAND08GW3B2C (8-bit width) with Freescale QorQ P4080 silicon 2.0.

u-boot is 2010-06. The kernel is 2.6.34.6. Both are using 36-bit addressing. Using "nand erase clean" to format NAND FLASH:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-----------------------------------------
=> nand erase clean
NAND erase: device 0 whole chip
Bad block table found at page 524224, version 0x01
Bad block table found at page 524160, version 0x01
nand_read_bbt: Bad block at 0x000002be0000
Skipping bad block at  0x02be0000
Skipping bad block at  0x3ff80000
Skipping bad block at  0x3ffa0000
Skipping bad block at  0x3ffc0000
Skipping bad block at  0x3ffe0000
OK
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


Then boot the board with NFS boot. Boot log for MTD (the first 0x1000000 bytes are reserved):
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-----------------------------------------
fe8000000.flash: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
fe8000000.flash: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
RedBoot partition parsing not available
Creating 6 MTD partitions on "fe8000000.flash":
0x000000000000-0x000000200000 : "NOR (RO) RCW"
0x000000200000-0x000001000000 : "NOR (RO) FMAN uCode"
0x000001000000-0x000006000000 : "NOR (RO) RAMDISK"
0x000006000000-0x000007d00000 : "NOR (RO) Linux Kernel Image"
0x000007d00000-0x000007ee0000 : "NOR (RO) DTB Image"
0x000007ee0000-0x000008000000 : "NOR (RO) U-Boot Image"
NAND device: Manufacturer ID: 0x20, Chip ID: 0xd3 (ST Micro NAND 1GiB 3,3V 8-bit)
RedBoot partition parsing not available
Creating 2 MTD partitions on "ffa00000.flash":
0x000000000000-0x000001000000 : "NAND (RO) RESERVED"
0x000001000000-0x000040000000 : "NAND (RW) JFFS2"
eLBC NAND device at 0xfffa00000, bank 1
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


The NAND JFFS2 partition can be mounted successfully and I can read/write files on it. Then I re-mount it but error " jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found " happens and then I dumped the page at 0x3ed40000:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<----------------------------------------- [root at Blackadder-P4080 root]# uname -a
Linux Blackadder-P4080 2.6.34.6 #10 SMP Thu Oct 28 19:40:46 CST 2010 ppc GNU/Linux
[root at Blackadder-P4080 root]#
[root at Blackadder-P4080 root]# mount /dev/mtdblock7 /mnt/nand -t jffs2
[root at Blackadder-P4080 root]# cd /mnt/nand
[root at Blackadder-P4080 nand]# tar xjf /root/mtd-utils-1.4.1.tar.bz2
[root at Blackadder-P4080 nand]# tar xjf /root/mtd-utils-1.4.1.tar.bz2
[root at Blackadder-P4080 nand]# ls
mtd-utils-1.4.1
[root at Blackadder-P4080 nand]# cd -
/root
[root at Blackadder-P4080 root]# umount /mnt/nand
[root at Blackadder-P4080 root]# !mount
mount /dev/mtdblock7 /mnt/nand -t jffs2
Scanning NAND Flash blocks...
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed40000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed60000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed80000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eda0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3edc0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ede0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee00000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee20000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee40000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee60000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee80000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eea0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eec0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eee0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef00000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef20000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef40000: 0xe0ff instead
done
[root at Blackadder-P4080 root]# cd /mnt/nand
[root at Blackadder-P4080 nand]# cd mtd-utils-1.4.1/
[root at Blackadder-P4080 mtd-utils-1.4.1]# ls -l
total 383
-rw-rw-r-- 1 user user 18007 Oct 19 04:47 COPYING
-rwxrwxr-x 1 user user   786 Oct 19 04:47 MAKEDEV
-rw-rw-r-- 1 user user  1460 Oct 19 04:47 Makefile
-rw-rw-r-- 1 user user  1846 Oct 19 04:47 common.mk
-rw-rw-r-- 1 user user 14734 Oct 19 04:47 compr.c
-rw-rw-r-- 1 user user  3369 Oct 19 04:47 compr.h
-rw-rw-r-- 1 user user  2957 Oct 19 04:47 compr_lzo.c
-rw-rw-r-- 1 user user  2661 Oct 19 04:47 compr_rtime.c
-rw-rw-r-- 1 user user  3934 Oct 19 04:47 compr_zlib.c
-rw-rw-r-- 1 user user  4247 Oct 19 04:47 device_table.txt
-rw-rw-r-- 1 user user  3264 Oct 19 04:47 doc_loadbios.c
-rw-rw-r-- 1 user user  8869 Oct 19 04:47 docfdisk.c
-rw-rw-r-- 1 user user   366 Oct 19 04:47 feature-removal-schedule.txt
-rw-rw-r-- 1 user user  1980 Oct 19 04:47 fectest.c
-rw-rw-r-- 1 user user  3687 Oct 19 04:47 flash_erase.c
-rw-rw-r-- 1 user user  7137 Oct 19 04:47 flash_eraseall.c
-rw-rw-r-- 1 user user  1047 Oct 19 04:47 flash_info.c
-rw-rw-r-- 1 user user  1780 Oct 19 04:47 flash_lock.c
-rw-rw-r-- 1 user user  1041 Oct 19 04:47 flash_otp_dump.c
-rw-rw-r-- 1 user user  1264 Oct 19 04:47 flash_otp_info.c
-rw-rw-r-- 1 user user  1534 Oct 19 04:47 flash_otp_lock.c
-rw-rw-r-- 1 user user  1969 Oct 19 04:47 flash_otp_write.c
-rw-rw-r-- 1 user user  1418 Oct 19 04:47 flash_unlock.c
-rw-rw-r-- 1 user user 10932 Oct 19 04:47 flashcp.c
-rw-rw-r-- 1 user user  6536 Oct 19 04:47 ftl_check.c
-rw-rw-r-- 1 user user  9445 Oct 19 04:47 ftl_format.c
drwxrwxr-x 4 user user     0 Oct 19 04:47 include
-rw-rw-r-- 1 user user  8641 Oct 19 04:47 jffs-dump.c
-rw-rw-r-- 1 user user 22291 Oct 19 04:47 jffs2dump.c
-rw-rw-r-- 1 user user 21133 Oct 19 04:47 jffs2reader.c
drwxrwxr-x 2 user user     0 Oct 19 04:47 lib
-rwxrwxr-x 1 user user  4309 Oct 19 04:47 load_nandsim.sh
-rw-rw-r-- 1 user user  1539 Oct 19 04:47 mcast_image.h
-rw-rw-r-- 1 user user  6676 Oct 19 04:47 mkfs.jffs2.1
-rw-rw-r-- 1 user user 50632 Oct 19 04:47 mkfs.jffs2.c
drwxrwxr-x 3 user user     0 Oct 19 04:47 mkfs.ubifs
-rw-rw-r-- 1 user user   727 Oct 19 04:47 mtd-utils.spec
-rw-rw-r-- 1 user user  9525 Oct 19 04:47 mtd_debug.c
-rw-rw-r-- 1 user user 13386 Oct 19 04:47 nanddump.c
-rw-rw-r-- 1 user user  6085 Oct 19 04:47 nandtest.c
-rw-rw-r-- 1 user user 18464 Oct 19 04:47 nandwrite.c
-rw-rw-r-- 1 user user 12414 Oct 19 04:47 nftl_format.c
-rw-rw-r-- 1 user user  7788 Oct 19 04:47 nftldump.c
-rw-rw-r-- 1 user user  8624 Oct 19 04:47 rbtree.c
-rw-rw-r-- 1 user user  5173 Oct 19 04:47 rbtree.h
-rw-rw-r-- 1 user user 14842 Oct 19 04:47 recv_image.c
-rw-rw-r-- 1 user user  7281 Oct 19 04:47 rfddump.c
-rw-rw-r-- 1 user user  3388 Oct 19 04:47 rfdformat.c
-rw-rw-r-- 1 user user  7823 Oct 19 04:47 serve_image.c
-rw-rw-r-- 1 user user  4860 Oct 19 04:47 summary.h
-rw-rw-r-- 1 user user 27167 Oct 19 04:47 sumtool.c
drwxrwxr-x 6 user user     0 Oct 19 04:47 tests
drwxrwxr-x 5 user user     0 Oct 19 04:47 ubi-utils
[root at Blackadder-P4080 mtd-utils-1.4.1]#
[root at Blackadder-P4080 mtd-utils-1.4.1]# nanddump -p -s 0x3ed40000 /dev/mtd7
ECC failed: 0
ECC corrected: 0
Number of bad blocks: 5
Number of bbt blocks: 0
Block size 131072, page size 2048, OOB size 64
Dumping data starting at 0x3ed40000 and ending at 0x3f000000...
0x3ed40000: e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40110: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40120: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40130: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40140: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40150: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40190: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40210: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40220: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40230: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40240: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40250: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40260: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40270: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40280: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40290: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40300: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40310: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40320: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40330: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40340: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40350: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40360: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40370: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40390: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40400: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40410: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40420: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40430: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40440: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40450: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40460: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40470: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40490: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40510: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40520: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40530: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40540: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40550: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40560: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40570: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40590: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40610: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40620: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40630: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40640: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40650: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40660: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40670: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40690: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40700: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40710: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40720: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40730: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40740: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40750: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40760: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40770: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40790: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff 19 85 20 03 00 00 00 aa aa 6a 08 ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...........
...........
...........
...........
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



I have worked on trying to fix it for whole week, but failed. Please help, thank u!




Frisky



From postmaster at lists.infradead.org  Fri Oct 29 02:05:16 2010
From: postmaster at lists.infradead.org (Post Office)
Date: Fri, 29 Oct 2010 11:35:16 +0530
Subject: Returned mail: see transcript for details
Message-ID: <mailman.7.1288332840.1530.linux-mtd@lists.infradead.org>

This message was not delivered due to the following reason(s):

Your message could not be delivered because the destination server was
not reachable within the allowed queue period. The amount of time
a message is queued before it is returned depends on local configura-
tion parameters.

Most likely there is a network problem that prevented delivery, but
it is also possible that the computer is turned off, or does not
have a mail system running right now.

Your message was not delivered within 8 days:
Host 174.72.41.103 is not responding.

The following recipients did not receive this message:
<linux-mtd at lists.infradead.org>

Please reply to postmaster at lists.infradead.org
if you feel this message to be in error.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: message.zip
Type: application/octet-stream
Size: 49432 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101029/7f9ae7e3/attachment.obj>

From viresh.kumar at st.com  Fri Oct 29 07:49:44 2010
From: viresh.kumar at st.com (viresh kumar)
Date: Fri, 29 Oct 2010 17:19:44 +0530
Subject: [PATCH V2 25/69] ST SPEAr: Add smi driver for serial NOR flash
In-Reply-To: <4CBD32EB.5050409@st.com>
References: <cover.1285933331.git.viresh.kumar@st.com>
	<238bd0ff57f8530c597157bc07f6c46dc362e1bc.1285933331.git.viresh.kumar@st.com>
	<4CBD32EB.5050409@st.com>
Message-ID: <4CCAB4D8.90807@st.com>

On 10/19/2010 11:25 AM, viresh kumar wrote:
> On 10/01/2010 05:25 PM, Viresh KUMAR wrote:
>> From: Shiraz Hashim <shiraz.hashim at st.com>
>>
>> SPEAr platforms(spear3xx/spear6xx/spear13xx) provide SMI(Serial Memory
>> Interface) controller to access serial NOR flash. SMI provides a simple
>> interface for SPI/serial NOR flashes and has certain inbuilt commands
>> and features to support these flashes easily. It also makes it possible
>> to map an address range in order to directly access (read/write) the SNOR
>> over address bus. This patch intends to provide serial nor driver support
>> for spear platforms which are accessed through SMI.
>>
>> Signed-off-by: Shiraz Hashim <shiraz.hashim at st.com>
>> Signed-off-by: Viresh Kumar <viresh.kumar at st.com>
>> ---
>>  arch/arm/plat-spear/include/plat/smi.h |   68 ++
>>  drivers/mtd/devices/Kconfig            |    7 +
>>  drivers/mtd/devices/Makefile           |    1 +
>>  drivers/mtd/devices/spear_smi.c        | 1122 ++++++++++++++++++++++++++++++++
>>  4 files changed, 1198 insertions(+), 0 deletions(-)
>>  create mode 100644 arch/arm/plat-spear/include/plat/smi.h
>>  create mode 100644 drivers/mtd/devices/spear_smi.c
> 
> David,
> 
> Any review comments on this patch??
> 

David,

Any review comments??

-- 
viresh


From ketil at froyn.name  Fri Oct 29 08:35:42 2010
From: ketil at froyn.name (Ketil Froyn)
Date: Fri, 29 Oct 2010 14:35:42 +0200
Subject: Cross compiling mtd-utils for Android and pread errors
Message-ID: <AANLkTinNUrQKg_8EgwW5k7BZFiik5ish6-z+qK-=3qpU@mail.gmail.com>

Hi,

I'm trying to cross compile the mtd-utils package for Android, and I
was wondering if anyone has been able to do this before, because I'm
finding it difficult.

I have a working cross compiler toolchain (works with agcc, a wrapper
that takes care of all the necessary compiler flags) but I'm having
trouble getting this working to compile mtd-utils. I have been able to
compile single programs manually with the agcc wrapper, for example:

agcc -I include -o nanddump nanddump.c

but when I transfer this executable to the device and run it, I get:

/ # /sdcard/nanddump -a /dev/mtd/mtd0
ECC failed: 0
ECC corrected: 0
Number of bad blocks: 0
Number of bbt blocks: 0
Block size 131072, page size 2048, OOB size 56
Dumping data starting at 0x00000000 and ending at 0x0a5c0000...
pread: Unknown error: 0
/ #

or

/ # /sdcard/nanddump -f /sdcard/testdump /dev/mtd/mtd0
ECC failed: 0
ECC corrected: 0
Number of bad blocks: 0
Number of bbt blocks: 0
Block size 131072, page size 2048, OOB size 56
Dumping data starting at 0x00000000 and ending at 0x00040000...
pread: Not a typewriter
/ #

I'm grateful for any tips that can nudge me in the right direction.

Cheers, Ketil


From Jon.Povey at racelogic.co.uk  Fri Oct 29 09:18:37 2010
From: Jon.Povey at racelogic.co.uk (Jon Povey)
Date: Fri, 29 Oct 2010 14:18:37 +0100
Subject: Cross compiling mtd-utils for Android and pread errors
In-Reply-To: <AANLkTinNUrQKg_8EgwW5k7BZFiik5ish6-z+qK-=3qpU@mail.gmail.com>
Message-ID: <70E876B0EA86DD4BAF101844BC814DFE093EEF9619@Cloud.RL.local>

linux-mtd-bounces at lists.infradead.org wrote:
> pread: Not a typewriter / #
>
> I'm grateful for any tips that can nudge me in the right direction.

"Not a typewriter" is ENOTTY, i.e. ioctl not supported.

Seems your android mtd devices don't support those ioctls.


--
Jon Povey
jon.povey at racelogic.co.uk

Racelogic is a limited company registered in England. Registered number 2743719 .
Registered Office Unit 10, Swan Business Centre, Osier Way, Buckingham, Bucks, MK18 1TB .

The information contained in this electronic mail transmission is intended by Racelogic Ltd for the use of the named individual or entity to which it is directed and may contain information that is confidential or privileged. If you have received this electronic mail transmission in error, please delete it from your system without copying or forwarding it, and notify the sender of the error by reply email so that the sender's address records can be corrected. The views expressed by the sender of this communication do not necessarily represent those of Racelogic Ltd. Please note that Racelogic reserves the right to monitor e-mail communications passing through its network




From glecerf at gmail.com  Fri Oct 29 10:17:49 2010
From: glecerf at gmail.com (Guillaume LECERF)
Date: Fri, 29 Oct 2010 16:17:49 +0200
Subject: [PATCH] mtd: bcm963xx-flash: try JEDEC probe if CFI fails
Message-ID: <20101029141749.23774.90495.stgit@dev.siriade.com>

Signed-off-by: Guillaume LECERF <glecerf at gmail.com>
---
 drivers/mtd/maps/bcm963xx-flash.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/maps/bcm963xx-flash.c b/drivers/mtd/maps/bcm963xx-flash.c
index d175c12..1f30495 100644
--- a/drivers/mtd/maps/bcm963xx-flash.c
+++ b/drivers/mtd/maps/bcm963xx-flash.c
@@ -196,10 +196,15 @@ static int bcm963xx_probe(struct platform_device *pdev)
 	bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
 	if (!bcm963xx_mtd_info) {
 		dev_err(&pdev->dev, "failed to probe using CFI\n");
+		bcm963xx_mtd_info = do_map_probe("jedec_probe", &bcm963xx_map);
+		if (bcm963xx_mtd_info)
+			goto probe_ok;
+		dev_err(&pdev->dev, "failed to probe using JEDEC\n");
 		err = -EIO;
 		goto err_probe;
 	}
 
+probe_ok:
 	bcm963xx_mtd_info->owner = THIS_MODULE;
 
 	/* This is mutually exclusive */



From florian at openwrt.org  Fri Oct 29 12:32:40 2010
From: florian at openwrt.org (Florian Fainelli)
Date: Fri, 29 Oct 2010 18:32:40 +0200
Subject: [PATCH] mtd: bcm963xx-flash: try JEDEC probe if CFI fails
In-Reply-To: <20101029141749.23774.90495.stgit@dev.siriade.com>
References: <20101029141749.23774.90495.stgit@dev.siriade.com>
Message-ID: <201010291832.40560.florian@openwrt.org>

On Friday 29 October 2010 16:17:49 Guillaume LECERF wrote:
> Signed-off-by: Guillaume LECERF <glecerf at gmail.com>

Acked-by: Florian Fainelli <florian at openwrt.org>

> ---
>  drivers/mtd/maps/bcm963xx-flash.c |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/maps/bcm963xx-flash.c
> b/drivers/mtd/maps/bcm963xx-flash.c index d175c12..1f30495 100644
> --- a/drivers/mtd/maps/bcm963xx-flash.c
> +++ b/drivers/mtd/maps/bcm963xx-flash.c
> @@ -196,10 +196,15 @@ static int bcm963xx_probe(struct platform_device
> *pdev) bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
>  	if (!bcm963xx_mtd_info) {
>  		dev_err(&pdev->dev, "failed to probe using CFI\n");
> +		bcm963xx_mtd_info = do_map_probe("jedec_probe", &bcm963xx_map);
> +		if (bcm963xx_mtd_info)
> +			goto probe_ok;
> +		dev_err(&pdev->dev, "failed to probe using JEDEC\n");
>  		err = -EIO;
>  		goto err_probe;
>  	}
> 
> +probe_ok:
>  	bcm963xx_mtd_info->owner = THIS_MODULE;
> 
>  	/* This is mutually exclusive */


From kernelccrazy at gmail.com  Fri Oct 29 14:53:09 2010
From: kernelccrazy at gmail.com (y bhanu)
Date: Fri, 29 Oct 2010 11:53:09 -0700
Subject: kernel-crash: mounted root (jffs2 filesystem) on device 31:9
Message-ID: <AANLkTinLCCw1raGKV+Q8f-5qWMrLiOZMyP1kx5x0ma9X@mail.gmail.com>

Hi have a weird situation.
I have a working 2.6.32 kernel and the nand rootfs which I am able to
boot fine and operate.

I upgrade my kernel to 2.6.35-7 and by keeping rootfs and dtb files are same.
I got everything working except the NAND rootfs working.
I can boot and mount a ramdisk but I need a NAND rootfs working too.

I am using the same dtb file as before.
./arch/powerpc/boot/dts/p1011rdb.dts (which has the NAND layout info)

The only thing that changed is the Linux kernel.
So, are there an other place in the kernel where the nand layout gets
redefined or so forth. somewhere in mtd maps.

Should I change the MTD maps(don't know which one??) too??
How can I debug this?


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.8.1288378395.1530.linux-mtd@lists.infradead.org>

Kernel crash log:
unable to open rtc device (rtc0)
JFFS2 notice: (1) jffs2_build_xattr_subsystem: complete building xattr
subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead,
0 orphan) found.
VFS: Mounted root (jffs2 filesystem) on device 31:9.
Freeing unused kernel memory: 176k init
Kernel panic - not syncing: No init found.  Try passing init= option
to kernel. See Linux Documentation/init.txt for guidance.
Call Trace:
[df839f20] [c0007d88] show_stack+0x4c/0x178 (unreliable)
[df839f60] [c03d7604] panic+0xa8/0x130
[df839fb0] [c0002054] init_post+0xe0/0x144
[df839fd0] [c0510260] kernel_init+0x140/0x17c
[df839ff0] [c00104fc] kernel_thread+0x4c/0x68
Rebooting in 180 seconds..
NAND boot... transfering control

Thanks
Mukund


From dilinger at queued.net  Sat Oct 30 00:04:19 2010
From: dilinger at queued.net (Andres Salomon)
Date: Fri, 29 Oct 2010 21:04:19 -0700
Subject: mtd: fix build error in m25p80.c
Message-ID: <20101029210419.70f99e96@queued.net>


While building an x86 distro kernel, I hit the following:

Kernel: arch/x86/boot/bzImage is ready  (#7)
ERROR: "of_mtd_parse_partitions" [drivers/mtd/devices/m25p80.ko]
undefined!

of_mtd_parse_partitions is defined with MTD_OF_PARTS, and that's only
built on PPC and microblaze.  The code in question should be wrapped w/
a stricter #ifdef.

Signed-off-by: Andres Salomon <dilinger at queued.net>
---
 drivers/mtd/devices/m25p80.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index ea22520..184ddd5 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -924,7 +924,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 			nr_parts = data->nr_parts;
 		}
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_MTD_OF_PARTS
 		if (nr_parts <= 0 && spi->dev.of_node) {
 			nr_parts = of_mtd_parse_partitions(&spi->dev,
 					spi->dev.of_node, &parts);
-- 
1.7.1



From grant.likely at secretlab.ca  Sat Oct 30 01:57:37 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Sat, 30 Oct 2010 06:57:37 +0100
Subject: mtd: fix build error in m25p80.c
In-Reply-To: <20101029210419.70f99e96@queued.net>
References: <20101029210419.70f99e96@queued.net>
Message-ID: <20101030055737.GA2456@angua.secretlab.ca>

On Fri, Oct 29, 2010 at 09:04:19PM -0700, Andres Salomon wrote:
> 
> While building an x86 distro kernel, I hit the following:
> 
> Kernel: arch/x86/boot/bzImage is ready  (#7)
> ERROR: "of_mtd_parse_partitions" [drivers/mtd/devices/m25p80.ko]
> undefined!
> 
> of_mtd_parse_partitions is defined with MTD_OF_PARTS, and that's only
> built on PPC and microblaze.  The code in question should be wrapped w/
> a stricter #ifdef.
> 
> Signed-off-by: Andres Salomon <dilinger at queued.net>
> ---
>  drivers/mtd/devices/m25p80.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index ea22520..184ddd5 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -924,7 +924,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
>  			nr_parts = data->nr_parts;
>  		}
>  
> -#ifdef CONFIG_OF
> +#ifdef CONFIG_MTD_OF_PARTS
>  		if (nr_parts <= 0 && spi->dev.of_node) {
>  			nr_parts = of_mtd_parse_partitions(&spi->dev,
>  					spi->dev.of_node, &parts);

True; but CONFIG_MTD_OF_PARTS should be built on all architectures
when CONFIG_OF & CONFIG_MTD_PARTITIONS is set.  I'll craft a patch.

g.


From grant.likely at secretlab.ca  Sat Oct 30 02:35:02 2010
From: grant.likely at secretlab.ca (Grant Likely)
Date: Sat, 30 Oct 2010 07:35:02 +0100
Subject: [RFC] mtd: Fix MTD_OF_PARTS for all arch and minor tidy of
	MTD_PARTITIONS
Message-ID: <20101030063425.22588.76571.stgit@localhost6.localdomain6>

MTD_OF_PARTS should be possible on all architectures, not just
powerpc and microblaze, and it probably should not be a user
selectable option.  Neither does it need to be in a separate module.

Also, rework MTD Kconfig to group options dependant on MTD_PARTITIONS
into a if/endif block.  Do the same for MTD_REDBOOT_PARTS.

Signed-off-by: Grant Likely <grant.likely at secretlab.ca>
---

Compile tested only.

 drivers/mtd/Kconfig  |   19 +++++++++++--------
 drivers/mtd/Makefile |    2 +-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 1e2cbf5..7741470 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -53,9 +53,10 @@ config MTD_PARTITIONS
 	  devices. Partitioning on NFTL 'devices' is a different - that's the
 	  'normal' form of partitioning used on a block device.
 
+if MTD_PARTITIONS
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
-	depends on MTD_PARTITIONS
 	---help---
 	  RedBoot is a ROM monitor and bootloader which deals with multiple
 	  'images' in flash devices by putting a table one of the erase
@@ -72,9 +73,10 @@ config MTD_REDBOOT_PARTS
 	  SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
 	  example.
 
+if MTD_REDBOOT_PARTS
+
 config MTD_REDBOOT_DIRECTORY_BLOCK
 	int "Location of RedBoot partition table"
-	depends on MTD_REDBOOT_PARTS
 	default "-1"
 	---help---
 	  This option is the Linux counterpart to the
@@ -91,18 +93,18 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
 
 config MTD_REDBOOT_PARTS_UNALLOCATED
 	bool "Include unallocated flash regions"
-	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to register each unallocated flash region as a MTD
 	  'partition', enable this option.
 
 config MTD_REDBOOT_PARTS_READONLY
 	bool "Force read-only for RedBoot system images"
-	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to force read-only for 'RedBoot', 'RedBoot Config' and
 	  'FIS directory' images, enable this option.
 
+endif # MTD_REDBOOT_PARTS
+
 config MTD_CMDLINE_PARTS
 	bool "Command line partition table parsing"
 	depends on MTD_PARTITIONS = "y" && MTD = "y"
@@ -142,7 +144,7 @@ config MTD_CMDLINE_PARTS
 
 config MTD_AFS_PARTS
 	tristate "ARM Firmware Suite partition parsing"
-	depends on ARM && MTD_PARTITIONS
+	depends on ARM
 	---help---
 	  The ARM Firmware Suite allows the user to divide flash devices into
 	  multiple 'images'. Each such image has a header containing its name
@@ -158,8 +160,8 @@ config MTD_AFS_PARTS
 	  example.
 
 config MTD_OF_PARTS
-	tristate "Flash partition map based on OF description"
-	depends on (MICROBLAZE || PPC_OF) && MTD_PARTITIONS
+	def_bool y
+	depends on OF
 	help
 	  This provides a partition parsing function which derives
 	  the partition map from the children of the flash node,
@@ -167,10 +169,11 @@ config MTD_OF_PARTS
 
 config MTD_AR7_PARTS
 	tristate "TI AR7 partitioning support"
-	depends on MTD_PARTITIONS
 	---help---
 	  TI AR7 partitioning support
 
+endif # MTD_PARTITIONS
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 760abc5..d4e7f25 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -6,13 +6,13 @@
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o
 mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
+mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
 obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
-obj-$(CONFIG_MTD_OF_PARTS)      += ofpart.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o



From Frisky.Li at Emerson.com  Sat Oct 30 06:05:27 2010
From: Frisky.Li at Emerson.com (Frisky.Li at Emerson.com)
Date: Sat, 30 Oct 2010 10:05:27 +0000
Subject: jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found
Message-ID: <608527F32EA5304EAFF29F54C602AA89CB788D@usstlz-pmsgem09.emrsn.org>


Hi all,
I?m debugging JFFS2 file system on NAND FLASH NAND08GW3B2C (8-bit width) with Freescale QorQ P4080 silicon 2.0.

u-boot is 2010-06. The kernel is 2.6.34.6. Both are using 36-bit addressing. Using "nand erase clean" to format NAND FLASH:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-----------------------------------------
=> nand erase clean
NAND erase: device 0 whole chip
Bad block table found at page 524224, version 0x01
Bad block table found at page 524160, version 0x01
nand_read_bbt: Bad block at 0x000002be0000
Skipping bad block at  0x02be0000
Skipping bad block at  0x3ff80000
Skipping bad block at  0x3ffa0000
Skipping bad block at  0x3ffc0000
Skipping bad block at  0x3ffe0000
OK
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


Then boot the board with NFS boot. Boot log for MTD (the first 0x1000000 bytes are reserved):
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<-----------------------------------------
fe8000000.flash: Found 1 x16 devices at 0x0 in 16-bit bank
 Amd/Fujitsu Extended Query Table at 0x0040
fe8000000.flash: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
RedBoot partition parsing not available
Creating 6 MTD partitions on "fe8000000.flash":
0x000000000000-0x000000200000 : "NOR (RO) RCW"
0x000000200000-0x000001000000 : "NOR (RO) FMAN uCode"
0x000001000000-0x000006000000 : "NOR (RO) RAMDISK"
0x000006000000-0x000007d00000 : "NOR (RO) Linux Kernel Image"
0x000007d00000-0x000007ee0000 : "NOR (RO) DTB Image"
0x000007ee0000-0x000008000000 : "NOR (RO) U-Boot Image"
NAND device: Manufacturer ID: 0x20, Chip ID: 0xd3 (ST Micro NAND 1GiB 3,3V 8-bit)
RedBoot partition parsing not available
Creating 2 MTD partitions on "ffa00000.flash":
0x000000000000-0x000001000000 : "NAND (RO) RESERVED"
0x000001000000-0x000040000000 : "NAND (RW) JFFS2"
eLBC NAND device at 0xfffa00000, bank 1
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


The NAND JFFS2 partition can be mounted successfully and I can read/write files on it. Then I re-mount it but error " jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found " happens and then I dumped the page at 0x3ed40000:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<----------------------------------------- [root at Blackadder-P4080 root]# uname -a
Linux Blackadder-P4080 2.6.34.6 #10 SMP Thu Oct 28 19:40:46 CST 2010 ppc GNU/Linux
[root at Blackadder-P4080 root]#
[root at Blackadder-P4080 root]# mount /dev/mtdblock7 /mnt/nand -t jffs2
[root at Blackadder-P4080 root]# cd /mnt/nand
[root at Blackadder-P4080 nand]# tar xjf /root/mtd-utils-1.4.1.tar.bz2
[root at Blackadder-P4080 nand]# tar xjf /root/mtd-utils-1.4.1.tar.bz2
[root at Blackadder-P4080 nand]# ls
mtd-utils-1.4.1
[root at Blackadder-P4080 nand]# cd -
/root
[root at Blackadder-P4080 root]# umount /mnt/nand
[root at Blackadder-P4080 root]# !mount
mount /dev/mtdblock7 /mnt/nand -t jffs2
Scanning NAND Flash blocks...
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed40000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed60000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ed80000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eda0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3edc0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ede0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee00000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee20000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee40000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee60000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ee80000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eea0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eec0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3eee0000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef00000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef20000: 0xe0ff instead
jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x3ef40000: 0xe0ff instead
done
[root at Blackadder-P4080 root]# cd /mnt/nand
[root at Blackadder-P4080 nand]# cd mtd-utils-1.4.1/
[root at Blackadder-P4080 mtd-utils-1.4.1]# ls -l
total 383
-rw-rw-r-- 1 user user 18007 Oct 19 04:47 COPYING
-rwxrwxr-x 1 user user   786 Oct 19 04:47 MAKEDEV
-rw-rw-r-- 1 user user  1460 Oct 19 04:47 Makefile
-rw-rw-r-- 1 user user  1846 Oct 19 04:47 common.mk
-rw-rw-r-- 1 user user 14734 Oct 19 04:47 compr.c
-rw-rw-r-- 1 user user  3369 Oct 19 04:47 compr.h
-rw-rw-r-- 1 user user  2957 Oct 19 04:47 compr_lzo.c
-rw-rw-r-- 1 user user  2661 Oct 19 04:47 compr_rtime.c
-rw-rw-r-- 1 user user  3934 Oct 19 04:47 compr_zlib.c
-rw-rw-r-- 1 user user  4247 Oct 19 04:47 device_table.txt
-rw-rw-r-- 1 user user  3264 Oct 19 04:47 doc_loadbios.c
-rw-rw-r-- 1 user user  8869 Oct 19 04:47 docfdisk.c
-rw-rw-r-- 1 user user   366 Oct 19 04:47 feature-removal-schedule.txt
-rw-rw-r-- 1 user user  1980 Oct 19 04:47 fectest.c
-rw-rw-r-- 1 user user  3687 Oct 19 04:47 flash_erase.c
-rw-rw-r-- 1 user user  7137 Oct 19 04:47 flash_eraseall.c
-rw-rw-r-- 1 user user  1047 Oct 19 04:47 flash_info.c
-rw-rw-r-- 1 user user  1780 Oct 19 04:47 flash_lock.c
-rw-rw-r-- 1 user user  1041 Oct 19 04:47 flash_otp_dump.c
-rw-rw-r-- 1 user user  1264 Oct 19 04:47 flash_otp_info.c
-rw-rw-r-- 1 user user  1534 Oct 19 04:47 flash_otp_lock.c
-rw-rw-r-- 1 user user  1969 Oct 19 04:47 flash_otp_write.c
-rw-rw-r-- 1 user user  1418 Oct 19 04:47 flash_unlock.c
-rw-rw-r-- 1 user user 10932 Oct 19 04:47 flashcp.c
-rw-rw-r-- 1 user user  6536 Oct 19 04:47 ftl_check.c
-rw-rw-r-- 1 user user  9445 Oct 19 04:47 ftl_format.c
drwxrwxr-x 4 user user     0 Oct 19 04:47 include
-rw-rw-r-- 1 user user  8641 Oct 19 04:47 jffs-dump.c
-rw-rw-r-- 1 user user 22291 Oct 19 04:47 jffs2dump.c
-rw-rw-r-- 1 user user 21133 Oct 19 04:47 jffs2reader.c
drwxrwxr-x 2 user user     0 Oct 19 04:47 lib
-rwxrwxr-x 1 user user  4309 Oct 19 04:47 load_nandsim.sh
-rw-rw-r-- 1 user user  1539 Oct 19 04:47 mcast_image.h
-rw-rw-r-- 1 user user  6676 Oct 19 04:47 mkfs.jffs2.1
-rw-rw-r-- 1 user user 50632 Oct 19 04:47 mkfs.jffs2.c
drwxrwxr-x 3 user user     0 Oct 19 04:47 mkfs.ubifs
-rw-rw-r-- 1 user user   727 Oct 19 04:47 mtd-utils.spec
-rw-rw-r-- 1 user user  9525 Oct 19 04:47 mtd_debug.c
-rw-rw-r-- 1 user user 13386 Oct 19 04:47 nanddump.c
-rw-rw-r-- 1 user user  6085 Oct 19 04:47 nandtest.c
-rw-rw-r-- 1 user user 18464 Oct 19 04:47 nandwrite.c
-rw-rw-r-- 1 user user 12414 Oct 19 04:47 nftl_format.c
-rw-rw-r-- 1 user user  7788 Oct 19 04:47 nftldump.c
-rw-rw-r-- 1 user user  8624 Oct 19 04:47 rbtree.c
-rw-rw-r-- 1 user user  5173 Oct 19 04:47 rbtree.h
-rw-rw-r-- 1 user user 14842 Oct 19 04:47 recv_image.c
-rw-rw-r-- 1 user user  7281 Oct 19 04:47 rfddump.c
-rw-rw-r-- 1 user user  3388 Oct 19 04:47 rfdformat.c
-rw-rw-r-- 1 user user  7823 Oct 19 04:47 serve_image.c
-rw-rw-r-- 1 user user  4860 Oct 19 04:47 summary.h
-rw-rw-r-- 1 user user 27167 Oct 19 04:47 sumtool.c
drwxrwxr-x 6 user user     0 Oct 19 04:47 tests
drwxrwxr-x 5 user user     0 Oct 19 04:47 ubi-utils
[root at Blackadder-P4080 mtd-utils-1.4.1]#
[root at Blackadder-P4080 mtd-utils-1.4.1]# nanddump -p -s 0x3ed40000 /dev/mtd7
ECC failed: 0
ECC corrected: 0
Number of bad blocks: 5
Number of bbt blocks: 0
Block size 131072, page size 2048, OOB size 64
Dumping data starting at 0x3ed40000 and ending at 0x3f000000...
0x3ed40000: e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40030: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed400f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40110: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40120: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40130: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40140: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40150: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40160: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40170: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40190: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed401f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40210: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40220: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40230: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40240: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40250: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40260: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40270: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40280: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40290: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed402f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40300: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40310: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40320: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40330: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40340: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40350: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40360: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40370: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40390: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed403f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40400: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40410: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40420: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40430: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40440: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40450: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40460: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40470: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40490: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed404f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40510: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40520: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40530: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40540: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40550: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40560: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40570: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40590: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed405f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40610: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40620: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40630: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40640: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40650: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40660: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40670: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40690: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed406f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40700: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40710: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40720: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40730: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40740: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40750: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40760: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40770: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed40790: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0x3ed407f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff 19 85 20 03 00 00 00 aa aa 6a 08 ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
...........
...........
...........
...........
----------------------------------------->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



I have worked on trying to fix it for whole week, but failed. Please help, thank u!




Frisky


From cernekee at gmail.com  Sun Oct 31 00:11:02 2010
From: cernekee at gmail.com (Kevin Cernekee)
Date: Sat, 30 Oct 2010 21:11:02 -0700
Subject: [PATCH 1/3] mtd: m25p80: Reinstate error print on unrecognized flash
Message-ID: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>

Commit b34bc037b26e621e5fc13466767e4da110a7b3d3 removed the
"unrecognized JEDEC id" error message, causing the probe function to
silently abort if the flash ID is unrecognized.

It is desirable to produce diagnostic output in this situation so that
the user has some idea what went wrong.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 drivers/mtd/devices/m25p80.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index bf5a002..80404e1 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -764,6 +764,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
 			return &m25p_ids[tmp];
 		}
 	}
+	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
 	return ERR_PTR(-ENODEV);
 }
 
-- 
1.7.0.4



From cernekee at gmail.com  Sun Oct 31 00:11:03 2010
From: cernekee at gmail.com (Kevin Cernekee)
Date: Sat, 30 Oct 2010 21:11:03 -0700
Subject: [PATCH 2/3] mtd: m25p80: Add support for Macronix MX256L25635E
In-Reply-To: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>
References: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>
Message-ID: <a4a2512bcf19341d19db73534412250e@localhost>

This is a 256Mbit (32MiB) part so minor changes were made to support
4-byte addressing.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   31 ++++++++++++++++++++++++++++---
 1 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 80404e1..96ae54e 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -51,6 +51,10 @@
 #define	OPCODE_WRDI		0x04	/* Write disable */
 #define	OPCODE_AAI_WP		0xad	/* Auto address increment word program */
 
+/* Used for Macronix flashes only. */
+#define	OPCODE_EN4B		0xb7	/* Enter 4-byte mode */
+#define	OPCODE_EX4B		0xe9	/* Exit 4-byte mode */
+
 /* Status Register bits. */
 #define	SR_WIP			1	/* Write in progress */
 #define	SR_WEL			2	/* Write enable latch */
@@ -62,7 +66,7 @@
 
 /* Define max times to check status register before we give up. */
 #define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
-#define	MAX_CMD_SIZE		4
+#define	MAX_CMD_SIZE		5
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define OPCODE_READ 	OPCODE_FAST_READ
@@ -152,6 +156,16 @@ static inline int write_disable(struct m25p *flash)
 }
 
 /*
+ * Enable/disable 4-byte addressing mode.
+ */
+static inline int set_4byte(struct m25p *flash, int enable)
+{
+	u8	code = enable ? OPCODE_EN4B : OPCODE_EX4B;
+
+	return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
+}
+
+/*
  * Service routine to read status register until ready, or timeout occurs.
  * Returns non-zero if error.
  */
@@ -207,6 +221,7 @@ static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
 	cmd[1] = addr >> (flash->addr_width * 8 -  8);
 	cmd[2] = addr >> (flash->addr_width * 8 - 16);
 	cmd[3] = addr >> (flash->addr_width * 8 - 24);
+	cmd[4] = addr >> (flash->addr_width * 8 - 32);
 }
 
 static int m25p_cmdsz(struct m25p *flash)
@@ -607,7 +622,6 @@ struct flash_info {
 		.sector_size = (_sector_size),				\
 		.n_sectors = (_n_sectors),				\
 		.page_size = 256,					\
-		.addr_width = 3,					\
 		.flags = (_flags),					\
 	})
 
@@ -653,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
 	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
 
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
@@ -884,7 +899,17 @@ static int __devinit m25p_probe(struct spi_device *spi)
 
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
-	flash->addr_width = info->addr_width;
+
+	if (info->addr_width)
+		flash->addr_width = info->addr_width;
+	else {
+		/* enable 4-byte addressing if the device exceeds 16MiB */
+		if (flash->mtd.size > 0x1000000) {
+			flash->addr_width = 4;
+			set_4byte(flash, 1);
+		} else
+			flash->addr_width = 3;
+	}
 
 	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)flash->mtd.size >> 10);
-- 
1.7.0.4



From cernekee at gmail.com  Sun Oct 31 00:11:04 2010
From: cernekee at gmail.com (Kevin Cernekee)
Date: Sat, 30 Oct 2010 21:11:04 -0700
Subject: [PATCH 3/3] mtd: m25p80: Add support for Macronix MX25L25655E
In-Reply-To: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>
References: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>
Message-ID: <9a14705b0b0416694a40a2eef55aac5b@localhost>

Untested, but expected to be compatible with MX25L25635E which I did
test.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 drivers/mtd/devices/m25p80.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 96ae54e..eabe5fb 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -668,6 +668,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
 	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
-- 
1.7.0.4



From cernekee at gmail.com  Sun Oct 31 03:47:19 2010
From: cernekee at gmail.com (Kevin Cernekee)
Date: Sun, 31 Oct 2010 00:47:19 -0700
Subject: [PATCH 2/3] mtd: m25p80: Add support for Macronix MX256L25635E
In-Reply-To: <a4a2512bcf19341d19db73534412250e@localhost>
References: <fbcf2b0a4d8ebff3378b9522ce81ad82@localhost>
	<a4a2512bcf19341d19db73534412250e@localhost>
Message-ID: <AANLkTi=CqWzxN7e6S6kUDqNgCodEt08caTAqW5em0XOd@mail.gmail.com>

Corrected subject line:

[PATCH 2/3] mtd: m25p80: Add support for Macronix MX25L25635E

"MX256L25635E" is incorrect.


From suppa628113 at yahoo.no  Sun Oct 31 06:35:43 2010
From: suppa628113 at yahoo.no (Cwbhms)
Date: Sun, 31 Oct 2010 18:35:43 +0800
Subject: 8567-X
Message-ID: <248446.73445.bm@smtp104.mail.gq1.yahoo.com>

163.com
357913589145791
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Vaflra8811.gif
Type: image/gif
Size: 5313 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101031/ceefed75/attachment.gif>

From manojkdi at gmail.com  Sun Oct 31 15:41:58 2010
From: manojkdi at gmail.com (Manoj Rajashekaraiah)
Date: Mon, 1 Nov 2010 01:11:58 +0530
Subject: Initialising Nand driver Failed error
Message-ID: <AANLkTikXefmK7qDMRL5tV-OWpnERkLPHYYREm1GDT-Fi@mail.gmail.com>

Hello,

I am Manoj a student of ME Embedded Systems at BITS Pilani, INDIA.
I kindly request for your help in solving one of the issues related to NAND
driver on STB810 set top boxes.

I have *searched  the archive* and could not get much information addressing
this issue.


I am  working with NXP STB810(currently owned by TRIDENT Microsystems) set
top boxes from philips.I have got three boxes among them 2 boxes are showing
an error as shown below(the boxes are not booting)

error shown hyperterminal
--------------------------

MicroBTM, Compiled Aug 22 2006 10:50:29
Using Uart 1
Initialising NAND driver...Failed! (0x10052803)

---------------------------------------

These STB810 boxes have Samsung K9F5616U0C nand flash
I have attached the pnx8550_nand.c which iam using in this mail.


Please let me know if you have any idea on this error.
Looking forward for hearing from you.

Best Regards

Manoj R
BITS, Pilani
INDIA
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101101/8e0342df/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pnx8550_nand.c
Type: application/octet-stream
Size: 30415 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20101101/8e0342df/attachment-0001.obj>

From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.19.1290047906.1530.linux-mtd@lists.infradead.org>

To        : raja at ricostones.com
Subject   : [***SPAM*** Score/Req: 09.1/5.0] Returned mail: see transcript for details
Message-ID:

---------------------
Attachment(s) removed
---------------------
raja at ricostones.com.zip (raja at ricostones.com.txt                                                                                                                                                                  .pif)

**************************************************************
Scanned by VisNetic MailScan for SMTP Servers.
Visit http://www.deerfield.com/products/visnetic_mailscan.
**************************************************************





From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.32.1291263053.1530.linux-mtd@lists.infradead.org>

driver that allows higher bus throughput during erase cycles.  There's
a chance that this is applicable to other NAND controllers, but my
experience is limited.  I'd be more than happy to share my work with
someone who has an interest in the 83xx, and I promise that I will do
a better job at the details than I did with the CPUs in question.


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.132.1296043760.1530.linux-mtd@lists.infradead.org>

owner of this part of filetree.


To make this situation more clean: My flash has 2 partitions
/ and /opt

And I also create two jffs2 files, one for each partition: root.jffs2
and opt.jffs2

If I mount /opt - the ownership of /opt is root, although it has been
"user" in the tree I generated the jffs2 files from.

As I am not familiar with internal design, I hope you can fix this bug.

Best regards
Arno


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.143.1297778435.1530.linux-mtd@lists.infradead.org>

(hundreds of thousands or millions) prior to an erase. Currently my
testing is using nandtestc.c and mtd_stresstest.ko - the former tests
one cycle before re-programming and the latter is random but not
expected to be more than tens of reads before a re-programme becomes
statistically likely. Potentially program disturb sounds like it
_could_ be the behaviour I observe but it's not clear.

My general take on this is that only the permanent type failures i.e.
those involving permanently stuck bits, require marking as bad blocks.
The recovery recommended for the other scenarios is always to erase
and re-programme. This potentially opens up a whole can of worms... My
interpretation of this is that if we verify a write and we've had a
(correctable and non-permanent) single bit error the Right Thing To Do
would be to erase and re-programme the block, probably with a very
small retry limit. We could argue that it's the responsibility of the
file-system to do this but programatically I think nand_write_page()
is best placed to be able to do this.

Certainly the verify failures we see here with a raw read are
occasional (and not consistently the same blocks) and hence not
indicative of stuck bits and generally after the block is re-written
the read is correct. What do you reckon?

Cheers,

~Pev

On 15 February 2011 13:02, Ricard Wanderlof <ricard.wanderlof at axis.com> wro=
te:
>
> On Tue, 15 Feb 2011, David Peverley wrote:
>
>> I've noticed that some of the problems we see are exacerbated further by
>> us having CONFIG_MTD_NAND_VERIFY_WRITE enabled. In the case where blocks
>> have occasional 1-bit ECC failures (i.e. normally correctable and not en=
ough
>> to warrant marking as bad) the generic verify routine will cause
>> nand_write_page() to return failure. I've prototyped a verify routine th=
at
>> uses an ECC corrected read in our driver and it seems to do the job
>> correctly.
>
> I may be wrong here, but as I understand, normally, bit read errors occur
> after a while (often called 'read disturb' in the literature) as the
> contents of certain bit cells leak away (either over time, or by accessin=
g),
> first causing random data, and then after a while settling down into a
> permanently inverted state, until the data is rewritten.
>
> If this is the case, then a verify performed just after a write (which I'=
m
> assuming is when it is performed) should yield correct data, unless a giv=
en
> bit cell is in a really bad condition, in which case the block should
> probably not be used anyway, as there as not been enough time for the bit=
 to
> decay for whatever reason.
>
> Of course, if there are bit cells which have other failure modes, your id=
ea
> might help, but again, if a bit is in such a bad state as to not being ab=
le
> to retain data between write and verify, the block should probably be
> discarded (marked as bad) anyway.
>
> One rationale would be that if you have one more or less permanently bad
> bit, although it can be handled by ECC, as soon the contents of another b=
it
> cell decays, the ECC won't be effective, so in practice, the ECC strength=
 is
> severely reduced for the page (or sub-page more likely, as ECC usually
> operates over less-than-page sizes in modern flashes) in question.
>
> /Ricard
> --
> Ricard Wolf Wanderl=F6f =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 ricardw(at)axis.com
> Axis Communications AB, Lund, Sweden =A0 =A0 =A0 =A0 =A0 =A0www.axis.com
> Phone +46 46 272 2016 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 Fax +46 46 13 61 30
>


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.157.1299057925.1530.linux-mtd@lists.infradead.org>

seems to hang the system in a live lock.

Situation:
=A0* immediately after boot an executable is started which calls mlockall()
   to commit all pages into RAM (this is a real time application)
=A0* the executable is read from a JFFS2 file system on NOR flash
=A0* mlockall() never terminates
=A0* console output is 'Data CRC f7e8ddd1 !=3D calculated CRC 47cee9c9
   for node at 00edc5cc' in an endless loop

My investigations are so far:
=A0* during boot some log output is written into a log file on the JFFS2
   that manipulates the file system --> no read only mount possible
=A0* the system is switched off at arbitrary times without clean unmount
   --> this clearly may leave behind blocks with data CRC errors
=A0* due to some reorganization (garbage collector?) my executable file
   data is moved across the flash
=A0* if such a move takes place exactly during power off two data frags
   carrying a portion of my executable file data are left behind, one "old"
   and correct frag and one "new" and incomplete frag with CRC error
=A0* during next boot mlockall() tries to read in all pages from the
   executable and fails on this point of CRC error

My questions:
=A0* is this a known behavior?
=A0* why is the fragment which has the CRC error relevant although
   the old and correct fragment is still in place?
=A0* are there relevant fixes in newer kernel versions which I should
   use? (I cannot update the kernel, but I may apply a patch)

Thanks a lot in advance!
Thommy


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.158.1299059569.1530.linux-mtd@lists.infradead.org>

seems to hang the system in a live lock.

Situation:
 * immediately after boot an executable is started which calls mlockall()
  to commit all pages into RAM (this is a real time application)
 * the executable is read from a JFFS2 file system on NOR flash
 * mlockall() never terminates
 * console output is 'Data CRC f7e8ddd1 != calculated CRC 47cee9c9
  for node at 00edc5cc' in an endless loop

My investigations are so far:
 * during boot some log output is written into a log file on the JFFS2
  that manipulates the file system --> no read only mount possible
 * the system is switched off at arbitrary times without clean unmount
  --> this clearly may leave behind blocks with data CRC errors
 * due to some reorganization (garbage collector?) my executable file
  data is moved across the flash
 * if such a move takes place exactly during power off two data frags
  carrying a portion of my executable file data are left behind, one "old"
  and correct frag and one "new" and incomplete frag with CRC error
 * during next boot mlockall() tries to read in all pages from the
  executable and fails on this point of CRC error

My questions:
 * is this a known behavior?
 * why is the fragment which has the CRC error relevant although
  the old and correct fragment is still in place?
 * are there relevant fixes in newer kernel versions which I should
  use? (I cannot update the kernel, but I may apply a patch)

Thanks a lot in advance!
Thommy


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.199.1302535112.1530.linux-mtd@lists.infradead.org>

I went down to the kernel and found the following problem. I will start in =
jffs2_flash_writev() from fs/jffs2/wbuf.c. There is a for loop running thro=
ugh a vector invec. Inside the loop data is written to the write buffer (wb=
uf). If the buffer is full __jffs2_flush_wbuf will be called. If now an una=
ligned amount of data was written the next call c->mtd->write() inside the =
next condition will fail, because the pointer (v) is not aligned. This poin=
ter is directly written to the dma. This results in the crash above.

I suggest the following patch. For me this works fine.

--- linux-2.6.33.7.orig/drivers/mtd/nand/omap2.c 2010-08-02 19:27:18.000000=
000 +0200
+++ linux-2.6.33.7/drivers/mtd/nand/omap2.c 2011-04-11 17:11:53.000000000 +=
0200
@@ -503,9 +506,11 @@
=C2=A0{
=C2=A0 if (len <=3D mtd->oobsize)
=C2=A0 omap_write_buf_pref(mtd, buf, len);
+ else if (!IS_ALIGNED((unsigned long)buf, 4))
+ omap_write_buf_pref(mtd, buf, len);
=C2=A0 else
=C2=A0 /* start transfer in DMA mode */
- omap_nand_dma_transfer(mtd, buf, len, 0x1);
+ omap_nand_dma_transfer(mtd, (void*)buf, len, 0x1);
=C2=A0}
=C2=A0
=C2=A0/**
Thanks very much!


=C2=A0
___________________________________________________________
Empfehlen Sie WEB.DE DSL Ihren Freunden und Bekannten und wir  =20
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.web.de


From bogus@does.not.exist.com  Fri Oct 22 17:57:35 2010
From: bogus@does.not.exist.com ()
Date: Fri, 22 Oct 2010 21:57:35 -0000
Subject: No subject
Message-ID: <mailman.229.1305291914.1530.linux-mtd@lists.infradead.org>

1. Since 2009, the bfin_nand.c NAND driver has been replaced with
plat_nand.c 
2. Unlike bfin_nand.c, plat_nand.c only contains code 
3. Board resources should now only live in the board driver, ip0x.c in
this case 

So, after checking bfin_nand.c, ip0x.c, and the BF537's stamp.c, I
came up with this updated ip0x.c: 

www.pastebin.com/fqwr9Qev 

I also slightly edited nand_base.c to display the values of
Manufacture ID and Device ID: 
============ 
/* Read manufacturer and device IDs */ 
*maf_id = chip->read_byte(mtd); 
dev_id = chip->read_byte(mtd); 
//Added by me 
printk("*********\n First read\nMaf ID %d \n Dev ID
%d\n",*maf_id,dev_id); 

chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); 

/* Read manufacturer and device IDs */ 
tmp_manf = chip->read_byte(mtd); 
tmp_id = chip->read_byte(mtd); 
//Added by me 
printk("*********\n Second read\nMaf ID %d \n Dev ID
%d\n",tmp_manf,tmp_id); 
============ 

Here's what dmesg says about NAND: 
============ 
... 
Found mtd parition at 0x0020a000, (len=0x800000), moving to 0x03700000
... 
ip0x_init(): registering device resources 
CLE is 4 and ALE is 2 
... 
uclinux[mtd]: RAM probe address=0x3700000 size=0x800000 
Creating 1 MTD partitions on "RAM": 
0x000000000000-0x000000800000 : "ROMfs" 
mtd: Giving out device 0 to ROMfs 
Generic platform RAM MTD, (c) 2004 Simtec Electronics 
********* 
First read 
Maf ID 15 
Dev ID 15 
********* 
Second read 
Maf ID 15 
Dev ID 15 
No NAND device found. 
... 
mtdblock_open 
ok 
============ 

As shown in ip0x.c, I've tried playing with start/end in
bfin_plat_nand_resources, to no avail. 

I'm also told to check that the ready pin is correctly declared, and
that the async timings aren't too fast for the NAND. 

With very little knowledge of NAND, I have no idea what else to try. 

What could prevent uClinux from accessing the NAND and reading its
partitions?

Thank you for any help.



