16c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
26c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * drivers/mtd/nand/fsmc_nand.c
36c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
46c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * ST Microelectronics
56c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Flexible Static Memory Controller (FSMC)
66c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Driver for NAND portions
76c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
86c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Copyright © 2010 ST Microelectronics
96c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Vipin Kumar <vipin.kumar@st.com>
106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Ashish Priyadarshi
116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Based on drivers/mtd/nand/nomadik_nand.c
136c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
146c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * This file is licensed under the terms of the GNU General Public
156c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * License version 2. This program is licensed "as is" without any
166c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * warranty of any kind, whether express or implied.
176c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
186c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
196c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/clk.h>
204774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar#include <linux/completion.h>
214774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar#include <linux/dmaengine.h>
224774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar#include <linux/dma-direction.h>
234774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar#include <linux/dma-mapping.h>
246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/err.h>
256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/init.h>
266c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/module.h>
276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/resource.h>
286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/sched.h>
296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/types.h>
306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/mtd/mtd.h>
316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/mtd/nand.h>
326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/mtd/nand_ecc.h>
336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/platform_device.h>
34eea628199d5b12429c47db17035a954b0062e554Stefan Roese#include <linux/of.h>
356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/mtd/partitions.h>
366c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/io.h>
376c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/slab.h>
386c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <linux/mtd/fsmc.h>
39593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij#include <linux/amba/bus.h>
406c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij#include <mtd/mtd-abi.h>
416c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
42e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc1_128_layout = {
436c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccbytes = 24,
446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52,
456c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		66, 67, 68, 82, 83, 84, 98, 99, 100, 114, 115, 116},
466c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.oobfree = {
476c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 8, .length = 8},
486c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 24, .length = 8},
496c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 40, .length = 8},
506c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 56, .length = 8},
516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 72, .length = 8},
526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 88, .length = 8},
536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 104, .length = 8},
546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 120, .length = 8}
556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
566c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
576c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
58e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc1_64_layout = {
59e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccbytes = 12,
60e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccpos = {2, 3, 4, 18, 19, 20, 34, 35, 36, 50, 51, 52},
61e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.oobfree = {
62e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 8, .length = 8},
63e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 24, .length = 8},
64e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 40, .length = 8},
65e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 56, .length = 8},
66e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	}
67e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav};
68e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav
69e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc1_16_layout = {
70e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccbytes = 3,
71e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccpos = {2, 3, 4},
72e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.oobfree = {
73e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 8, .length = 8},
74e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	}
75e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav};
76e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav
77e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav/*
78e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * ECC4 layout for NAND of pagesize 8192 bytes & OOBsize 256 bytes. 13*16 bytes
79e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * of OB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block and 46
80e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * bytes are free for use.
81e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav */
82e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc4_256_layout = {
83e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccbytes = 208,
84e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccpos = {  2,   3,   4,   5,   6,   7,   8,
85e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		9,  10,  11,  12,  13,  14,
86e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		18,  19,  20,  21,  22,  23,  24,
87e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		25,  26,  27,  28,  29,  30,
88e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		34,  35,  36,  37,  38,  39,  40,
89e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		41,  42,  43,  44,  45,  46,
90e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		50,  51,  52,  53,  54,  55,  56,
91e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		57,  58,  59,  60,  61,  62,
92e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		66,  67,  68,  69,  70,  71,  72,
93e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		73,  74,  75,  76,  77,  78,
94e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		82,  83,  84,  85,  86,  87,  88,
95e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		89,  90,  91,  92,  93,  94,
96e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		98,  99, 100, 101, 102, 103, 104,
97e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		105, 106, 107, 108, 109, 110,
98e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		114, 115, 116, 117, 118, 119, 120,
99e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		121, 122, 123, 124, 125, 126,
100e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		130, 131, 132, 133, 134, 135, 136,
101e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		137, 138, 139, 140, 141, 142,
102e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		146, 147, 148, 149, 150, 151, 152,
103e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		153, 154, 155, 156, 157, 158,
104e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		162, 163, 164, 165, 166, 167, 168,
105e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		169, 170, 171, 172, 173, 174,
106e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		178, 179, 180, 181, 182, 183, 184,
107e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		185, 186, 187, 188, 189, 190,
108e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		194, 195, 196, 197, 198, 199, 200,
109e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		201, 202, 203, 204, 205, 206,
110e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		210, 211, 212, 213, 214, 215, 216,
111e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		217, 218, 219, 220, 221, 222,
112e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		226, 227, 228, 229, 230, 231, 232,
113e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		233, 234, 235, 236, 237, 238,
114e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		242, 243, 244, 245, 246, 247, 248,
115e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		249, 250, 251, 252, 253, 254
116e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	},
117e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.oobfree = {
118e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 15, .length = 3},
119e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 31, .length = 3},
120e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 47, .length = 3},
121e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 63, .length = 3},
122e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 79, .length = 3},
123e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 95, .length = 3},
124e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 111, .length = 3},
125e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 127, .length = 3},
126e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 143, .length = 3},
127e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 159, .length = 3},
128e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 175, .length = 3},
129e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 191, .length = 3},
130e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 207, .length = 3},
131e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 223, .length = 3},
132e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 239, .length = 3},
133e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 255, .length = 1}
134e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	}
135e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav};
136e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav
137e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav/*
1380c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes. 13*8 bytes
1390c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 118
1400c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti * bytes are free for use.
1410c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti */
1420c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Viscontistatic struct nand_ecclayout fsmc_ecc4_224_layout = {
1430c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti	.eccbytes = 104,
1440c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti	.eccpos = {  2,   3,   4,   5,   6,   7,   8,
1450c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		9,  10,  11,  12,  13,  14,
1460c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		18,  19,  20,  21,  22,  23,  24,
1470c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		25,  26,  27,  28,  29,  30,
1480c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		34,  35,  36,  37,  38,  39,  40,
1490c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		41,  42,  43,  44,  45,  46,
1500c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		50,  51,  52,  53,  54,  55,  56,
1510c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		57,  58,  59,  60,  61,  62,
1520c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		66,  67,  68,  69,  70,  71,  72,
1530c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		73,  74,  75,  76,  77,  78,
1540c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		82,  83,  84,  85,  86,  87,  88,
1550c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		89,  90,  91,  92,  93,  94,
1560c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		98,  99, 100, 101, 102, 103, 104,
1570c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		105, 106, 107, 108, 109, 110,
1580c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		114, 115, 116, 117, 118, 119, 120,
1590c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		121, 122, 123, 124, 125, 126
1600c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti	},
1610c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti	.oobfree = {
1620c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 15, .length = 3},
1630c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 31, .length = 3},
1640c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 47, .length = 3},
1650c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 63, .length = 3},
1660c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 79, .length = 3},
1670c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 95, .length = 3},
1680c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 111, .length = 3},
1690c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		{.offset = 127, .length = 97}
1700c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti	}
1710c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti};
1720c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti
1730c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti/*
174e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 128 bytes. 13*8 bytes
175e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * of OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block & 22
176e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * bytes are free for use.
177e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav */
178e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc4_128_layout = {
1796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccbytes = 104,
1806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccpos = {  2,   3,   4,   5,   6,   7,   8,
1816c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		9,  10,  11,  12,  13,  14,
1826c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		18,  19,  20,  21,  22,  23,  24,
1836c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		25,  26,  27,  28,  29,  30,
1846c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		34,  35,  36,  37,  38,  39,  40,
1856c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		41,  42,  43,  44,  45,  46,
1866c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		50,  51,  52,  53,  54,  55,  56,
1876c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		57,  58,  59,  60,  61,  62,
1886c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		66,  67,  68,  69,  70,  71,  72,
1896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		73,  74,  75,  76,  77,  78,
1906c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		82,  83,  84,  85,  86,  87,  88,
1916c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		89,  90,  91,  92,  93,  94,
1926c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		98,  99, 100, 101, 102, 103, 104,
1936c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		105, 106, 107, 108, 109, 110,
1946c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		114, 115, 116, 117, 118, 119, 120,
1956c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		121, 122, 123, 124, 125, 126
1966c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	},
1976c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.oobfree = {
1986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 15, .length = 3},
1996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 31, .length = 3},
2006c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 47, .length = 3},
2016c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 63, .length = 3},
2026c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 79, .length = 3},
2036c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 95, .length = 3},
2046c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 111, .length = 3},
2056c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 127, .length = 1}
2066c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
2076c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
2086c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
2096c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
210e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * ECC4 layout for NAND of pagesize 2048 bytes & OOBsize 64 bytes. 13*4 bytes of
211e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * OOB size is reserved for ECC, Byte no. 0 & 1 reserved for bad block and 10
212e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * bytes are free for use.
213e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav */
214e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc4_64_layout = {
215e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccbytes = 52,
216e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccpos = {  2,   3,   4,   5,   6,   7,   8,
217e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		9,  10,  11,  12,  13,  14,
218e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		18,  19,  20,  21,  22,  23,  24,
219e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		25,  26,  27,  28,  29,  30,
220e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		34,  35,  36,  37,  38,  39,  40,
221e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		41,  42,  43,  44,  45,  46,
222e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		50,  51,  52,  53,  54,  55,  56,
223e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		57,  58,  59,  60,  61,  62,
224e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	},
225e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.oobfree = {
226e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 15, .length = 3},
227e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 31, .length = 3},
228e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 47, .length = 3},
229e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 63, .length = 1},
230e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	}
231e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav};
232e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav
233e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav/*
234e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * ECC4 layout for NAND of pagesize 512 bytes & OOBsize 16 bytes. 13 bytes of
235e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * OOB size is reserved for ECC, Byte no. 4 & 5 reserved for bad block and One
236e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav * byte is free for use.
237e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav */
238e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadavstatic struct nand_ecclayout fsmc_ecc4_16_layout = {
239e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccbytes = 13,
240e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.eccpos = { 0,  1,  2,  3,  6,  7, 8,
241e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		9, 10, 11, 12, 13, 14
242e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	},
243e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	.oobfree = {
244e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		{.offset = 15, .length = 1},
245e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav	}
246e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav};
247e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav
248e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav/*
2496c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * ECC placement definitions in oobfree type format.
2506c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * There are 13 bytes of ecc for every 512 byte block and it has to be read
2516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * consecutively and immediately after the 512 byte data block for hardware to
2526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * generate the error bit offsets in 512 byte data.
2536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Managing the ecc bytes in the following way makes it easier for software to
2546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * read ecc bytes consecutive to data bytes. This way is similar to
2556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * oobfree structure maintained already in generic nand driver
2566c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
2576c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic struct fsmc_eccplace fsmc_ecc4_lp_place = {
2586c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccplace = {
2596c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 2, .length = 13},
2606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 18, .length = 13},
2616c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 34, .length = 13},
2626c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 50, .length = 13},
2636c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 66, .length = 13},
2646c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 82, .length = 13},
2656c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 98, .length = 13},
2666c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 114, .length = 13}
2676c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
2686c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
2696c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
2706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic struct fsmc_eccplace fsmc_ecc4_sp_place = {
2716c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.eccplace = {
2726c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 0, .length = 4},
2736c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		{.offset = 6, .length = 9}
2746c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
2756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
2766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
2776c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/**
278593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij * struct fsmc_nand_data - structure for FSMC NAND device state
2796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
280593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij * @pid:		Part ID on the AMBA PrimeCell format
2816c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @mtd:		MTD info for a NAND flash.
2826c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @nand:		Chip related info for a NAND flash.
2837147032485293fc24751e4dede98ff29050fd3bdVipin Kumar * @partitions:		Partition info for a NAND Flash.
2847147032485293fc24751e4dede98ff29050fd3bdVipin Kumar * @nr_partitions:	Total number of partition of a NAND flash.
2856c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
2866c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @ecc_place:		ECC placing locations in oobfree type format.
2876c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @bank:		Bank number for probed device.
2886c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @clk:		Clock structure for FSMC.
2896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
2904774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @read_dma_chan:	DMA channel for read access
2914774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @write_dma_chan:	DMA channel for write access to NAND
2924774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @dma_access_complete: Completion structure
2934774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar *
2944774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @data_pa:		NAND Physical port for Data.
2956c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @data_va:		NAND port for Data.
2966c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @cmd_va:		NAND port for Command.
2976c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @addr_va:		NAND port for Address.
2986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @regs_va:		FSMC regs base address.
2996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
3006c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstruct fsmc_nand_data {
301593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	u32			pid;
3026c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct mtd_info		mtd;
3036c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct nand_chip	nand;
3047147032485293fc24751e4dede98ff29050fd3bdVipin Kumar	struct mtd_partition	*partitions;
3057147032485293fc24751e4dede98ff29050fd3bdVipin Kumar	unsigned int		nr_partitions;
3066c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3076c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_eccplace	*ecc_place;
3086c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	unsigned int		bank;
309712c4add03277197168210bb628b8273e36adf76Vipin Kumar	struct device		*dev;
3104774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	enum access_mode	mode;
3116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct clk		*clk;
3126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3134774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	/* DMA related objects */
3144774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct dma_chan		*read_dma_chan;
3154774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct dma_chan		*write_dma_chan;
3164774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct completion	dma_access_complete;
3174774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
318e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	struct fsmc_nand_timings *dev_timings;
319e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar
3204774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_addr_t		data_pa;
3216c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	void __iomem		*data_va;
3226c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	void __iomem		*cmd_va;
3236c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	void __iomem		*addr_va;
3246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	void __iomem		*regs_va;
3256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3266c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	void			(*select_chip)(uint32_t bank, uint32_t busw);
3276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
3286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/* Assert CS signal based on chipnr */
3306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
3316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
3326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct nand_chip *chip = mtd->priv;
3336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host;
3346c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host = container_of(mtd, struct fsmc_nand_data, mtd);
3366c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3376c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	switch (chipnr) {
3386c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	case -1:
3396c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
3406c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		break;
3416c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	case 0:
3426c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	case 1:
3436c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	case 2:
3446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	case 3:
3456c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		if (host->select_chip)
3466c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			host->select_chip(chipnr,
3476c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					chip->options & NAND_BUSWIDTH_16);
3486c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		break;
3496c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3506c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	default:
3516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		BUG();
3526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
3536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
3546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
3566c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_cmd_ctrl - For facilitaing Hardware access
3576c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * This routine allows hardware specific access to control-lines(ALE,CLE)
3586c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
3596c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
3606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
3616c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct nand_chip *this = mtd->priv;
3626c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
3636c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
364605add7db6e84ff78f7ca96541c0880f0166e387Vipin Kumar	void __iomem *regs = host->regs_va;
3656c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	unsigned int bank = host->bank;
3666c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3676c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (ctrl & NAND_CTRL_CHANGE) {
3682a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar		u32 pc;
3692a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar
3706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		if (ctrl & NAND_CLE) {
3712a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_R = host->cmd_va;
3722a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_W = host->cmd_va;
3736c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		} else if (ctrl & NAND_ALE) {
3742a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_R = host->addr_va;
3752a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_W = host->addr_va;
3766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		} else {
3772a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_R = host->data_va;
3782a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			this->IO_ADDR_W = host->data_va;
3796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		}
3806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3812a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar		pc = readl(FSMC_NAND_REG(regs, bank, PC));
3822a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar		if (ctrl & NAND_NCE)
3832a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			pc |= FSMC_ENABLE;
3842a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar		else
3852a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			pc &= ~FSMC_ENABLE;
386a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar		writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
3876c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
3886c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	mb();
3906c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3916c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (cmd != NAND_CMD_NONE)
392a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar		writeb_relaxed(cmd, this->IO_ADDR_W);
3936c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
3946c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
3956c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
3966c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_nand_setup - FSMC (Flexible Static Memory Controller) init routine
3976c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
3986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * This routine initializes timing parameters related to NAND memory access in
3996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * FSMC registers
4006c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
4012a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumarstatic void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
402e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar			   uint32_t busw, struct fsmc_nand_timings *timings)
4036c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
4046c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
405e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	uint32_t tclr, tar, thiz, thold, twait, tset;
406e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	struct fsmc_nand_timings *tims;
407e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	struct fsmc_nand_timings default_timings = {
408e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.tclr	= FSMC_TCLR_1,
409e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.tar	= FSMC_TAR_1,
410e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.thiz	= FSMC_THIZ_1,
411e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.thold	= FSMC_THOLD_4,
412e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.twait	= FSMC_TWAIT_6,
413e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		.tset	= FSMC_TSET_0,
414e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	};
415e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar
416e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	if (timings)
417e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		tims = timings;
418e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	else
419e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar		tims = &default_timings;
420e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar
421e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
422e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
423e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	thiz = (tims->thiz & FSMC_THIZ_MASK) << FSMC_THIZ_SHIFT;
424e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	thold = (tims->thold & FSMC_THOLD_MASK) << FSMC_THOLD_SHIFT;
425e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	twait = (tims->twait & FSMC_TWAIT_MASK) << FSMC_TWAIT_SHIFT;
426e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
4276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
4286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (busw)
429a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar		writel_relaxed(value | FSMC_DEVWID_16,
430a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar				FSMC_NAND_REG(regs, bank, PC));
4316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	else
432a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar		writel_relaxed(value | FSMC_DEVWID_8,
433a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar				FSMC_NAND_REG(regs, bank, PC));
4346c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
435a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
4362a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			FSMC_NAND_REG(regs, bank, PC));
437a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(thiz | thold | twait | tset,
438a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			FSMC_NAND_REG(regs, bank, COMM));
439a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(thiz | thold | twait | tset,
440a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			FSMC_NAND_REG(regs, bank, ATTRIB));
4416c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
4426c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
4436c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
4446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers
4456c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
4466c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
4476c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
4486c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
4496c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
4502a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar	void __iomem *regs = host->regs_va;
4516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t bank = host->bank;
4526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
453a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
4542a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			FSMC_NAND_REG(regs, bank, PC));
455a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
4562a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			FSMC_NAND_REG(regs, bank, PC));
457a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
4582a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			FSMC_NAND_REG(regs, bank, PC));
4596c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
4606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
4616c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
4626c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by
46325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to
4646c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * max of 8-bits)
4656c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
4666c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
4676c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij				uint8_t *ecc)
4686c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
4696c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
4706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
4712a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar	void __iomem *regs = host->regs_va;
4726c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t bank = host->bank;
4736c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t ecc_tmp;
4746c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
4756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
4766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	do {
477a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar		if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
4786c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			break;
4796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		else
4806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			cond_resched();
4816c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	} while (!time_after_eq(jiffies, deadline));
4826c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
483712c4add03277197168210bb628b8273e36adf76Vipin Kumar	if (time_after_eq(jiffies, deadline)) {
484712c4add03277197168210bb628b8273e36adf76Vipin Kumar		dev_err(host->dev, "calculate ecc timed out\n");
485712c4add03277197168210bb628b8273e36adf76Vipin Kumar		return -ETIMEDOUT;
486712c4add03277197168210bb628b8273e36adf76Vipin Kumar	}
487712c4add03277197168210bb628b8273e36adf76Vipin Kumar
488a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
4896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[0] = (uint8_t) (ecc_tmp >> 0);
4906c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[1] = (uint8_t) (ecc_tmp >> 8);
4916c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[2] = (uint8_t) (ecc_tmp >> 16);
4926c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[3] = (uint8_t) (ecc_tmp >> 24);
4936c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
494a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
4956c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[4] = (uint8_t) (ecc_tmp >> 0);
4966c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[5] = (uint8_t) (ecc_tmp >> 8);
4976c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[6] = (uint8_t) (ecc_tmp >> 16);
4986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[7] = (uint8_t) (ecc_tmp >> 24);
4996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
500a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
5016c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[8] = (uint8_t) (ecc_tmp >> 0);
5026c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[9] = (uint8_t) (ecc_tmp >> 8);
5036c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[10] = (uint8_t) (ecc_tmp >> 16);
5046c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[11] = (uint8_t) (ecc_tmp >> 24);
5056c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
506a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
5076c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[12] = (uint8_t) (ecc_tmp >> 16);
5086c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
5096c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
5106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
5116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
5126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
5136c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by
51425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to
5156c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * max of 1-bit)
5166c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
5176c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
5186c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij				uint8_t *ecc)
5196c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
5206c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
5216c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
5222a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar	void __iomem *regs = host->regs_va;
5236c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t bank = host->bank;
5246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t ecc_tmp;
5256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
526a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
5276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[0] = (uint8_t) (ecc_tmp >> 0);
5286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[1] = (uint8_t) (ecc_tmp >> 8);
5296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	ecc[2] = (uint8_t) (ecc_tmp >> 16);
5306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
5316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
5326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
5336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
534519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar/* Count the number of 0's in buff upto a max of max_bits */
535519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumarstatic int count_written_bits(uint8_t *buff, int size, int max_bits)
536519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar{
537519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	int k, written_bits = 0;
538519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
539519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	for (k = 0; k < size; k++) {
540519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		written_bits += hweight8(~buff[k]);
541519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		if (written_bits > max_bits)
542519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar			break;
543519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	}
544519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
545519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	return written_bits;
546519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar}
547519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
5484774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarstatic void dma_complete(void *param)
5494774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar{
5504774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct fsmc_nand_data *host = param;
5514774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5524774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	complete(&host->dma_access_complete);
5534774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar}
5544774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5554774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarstatic int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
5564774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		enum dma_data_direction direction)
5574774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar{
5584774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct dma_chan *chan;
5594774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct dma_device *dma_dev;
5604774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct dma_async_tx_descriptor *tx;
5614774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_addr_t dma_dst, dma_src, dma_addr;
5624774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_cookie_t cookie;
5634774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
5644774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	int ret;
5654774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5664774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (direction == DMA_TO_DEVICE)
5674774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		chan = host->write_dma_chan;
5684774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	else if (direction == DMA_FROM_DEVICE)
5694774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		chan = host->read_dma_chan;
5704774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	else
5714774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		return -EINVAL;
5724774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5734774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_dev = chan->device;
5744774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction);
5754774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5764774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (direction == DMA_TO_DEVICE) {
5774774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_src = dma_addr;
5784774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_dst = host->data_pa;
5794774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	} else {
5804774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_src = host->data_pa;
5814774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_dst = dma_addr;
5824774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	}
5834774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5844774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	tx = dma_dev->device_prep_dma_memcpy(chan, dma_dst, dma_src,
5854774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			len, flags);
5864774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (!tx) {
5874774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dev_err(host->dev, "device_prep_dma_memcpy error\n");
588d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz		ret = -EIO;
589d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz		goto unmap_dma;
5904774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	}
5914774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5924774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	tx->callback = dma_complete;
5934774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	tx->callback_param = host;
5944774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	cookie = tx->tx_submit(tx);
5954774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
5964774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	ret = dma_submit_error(cookie);
5974774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (ret) {
5984774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dev_err(host->dev, "dma_submit_error %d\n", cookie);
599d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz		goto unmap_dma;
6004774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	}
6014774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6024774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_async_issue_pending(chan);
6034774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6044774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	ret =
605928aa2aeb7269292ca1e3d0e5e2e5d08af13da3dVipin Kumar	wait_for_completion_timeout(&host->dma_access_complete,
6064774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar				msecs_to_jiffies(3000));
6074774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (ret <= 0) {
608b177ea341a588ab270c31496f34c503c31589649Vinod Koul		dmaengine_terminate_all(chan);
6094774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dev_err(host->dev, "wait_for_completion_timeout\n");
610d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz		if (!ret)
611d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz			ret = -ETIMEDOUT;
612d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz		goto unmap_dma;
6134774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	}
6144774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
615d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz	ret = 0;
616d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz
617d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewiczunmap_dma:
618d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz	dma_unmap_single(dma_dev->dev, dma_addr, len, direction);
619d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz
620d1806a5c4d2248d2799f4367dbdb1800be94a26fBartlomiej Zolnierkiewicz	return ret;
6214774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar}
6224774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6236c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
624604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * fsmc_write_buf - write buffer to chip
625604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @mtd:	MTD device structure
626604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @buf:	data buffer
627604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @len:	number of bytes to write
628604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar */
629604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumarstatic void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
630604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar{
631604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	int i;
632604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	struct nand_chip *chip = mtd->priv;
633604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar
634604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
635604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar			IS_ALIGNED(len, sizeof(uint32_t))) {
636604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		uint32_t *p = (uint32_t *)buf;
637604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		len = len >> 2;
638604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		for (i = 0; i < len; i++)
639a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			writel_relaxed(p[i], chip->IO_ADDR_W);
640604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	} else {
641604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		for (i = 0; i < len; i++)
642a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			writeb_relaxed(buf[i], chip->IO_ADDR_W);
643604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	}
644604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar}
645604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar
646604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar/*
647604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * fsmc_read_buf - read chip data into buffer
648604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @mtd:	MTD device structure
649604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @buf:	buffer to store date
650604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar * @len:	number of bytes to read
651604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar */
652604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumarstatic void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
653604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar{
654604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	int i;
655604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	struct nand_chip *chip = mtd->priv;
656604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar
657604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
658604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar			IS_ALIGNED(len, sizeof(uint32_t))) {
659604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		uint32_t *p = (uint32_t *)buf;
660604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		len = len >> 2;
661604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		for (i = 0; i < len; i++)
662a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			p[i] = readl_relaxed(chip->IO_ADDR_R);
663604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	} else {
664604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		for (i = 0; i < len; i++)
665a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar			buf[i] = readb_relaxed(chip->IO_ADDR_R);
666604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	}
667604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar}
668604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar
669604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar/*
6704774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * fsmc_read_buf_dma - read chip data into buffer
6714774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @mtd:	MTD device structure
6724774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @buf:	buffer to store date
6734774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @len:	number of bytes to read
6744774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar */
6754774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarstatic void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len)
6764774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar{
6774774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct fsmc_nand_data *host;
6784774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6794774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	host = container_of(mtd, struct fsmc_nand_data, mtd);
6804774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_xfer(host, buf, len, DMA_FROM_DEVICE);
6814774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar}
6824774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6834774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar/*
6844774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * fsmc_write_buf_dma - write buffer to chip
6854774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @mtd:	MTD device structure
6864774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @buf:	data buffer
6874774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar * @len:	number of bytes to write
6884774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar */
6894774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarstatic void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
6904774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		int len)
6914774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar{
6924774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	struct fsmc_nand_data *host;
6934774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6944774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	host = container_of(mtd, struct fsmc_nand_data, mtd);
6954774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
6964774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar}
6974774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
6984774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar/*
6996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_read_page_hwecc
7006c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @mtd:	mtd info structure
7016c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @chip:	nand chip info structure
7026c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @buf:	buffer to store read data
7031fbb938dff5b6bb4514a4e7600276b03c7f08e25Brian Norris * @oob_required:	caller expects OOB data read to chip->oob_poi
7046c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @page:	page number to read
7056c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
70625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * This routine is needed for fsmc version 8 as reading from NAND chip has to be
7076c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * performed in a strict sequence as follows:
7086c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * data(512 byte) -> ecc(13 byte)
70925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * After this read, fsmc hardware generates and reports error data bits(up to a
7106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * max of 8 bits)
7116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
7126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
7131fbb938dff5b6bb4514a4e7600276b03c7f08e25Brian Norris				 uint8_t *buf, int oob_required, int page)
7146c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
7156c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
7166c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
7176c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_eccplace *ecc_place = host->ecc_place;
7186c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	int i, j, s, stat, eccsize = chip->ecc.size;
7196c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	int eccbytes = chip->ecc.bytes;
7206c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	int eccsteps = chip->ecc.steps;
7216c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint8_t *p = buf;
7226c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint8_t *ecc_calc = chip->buffers->ecccalc;
7236c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint8_t *ecc_code = chip->buffers->ecccode;
7246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	int off, len, group = 0;
7256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/*
7266c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we
7276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * end up reading 14 bytes (7 words) from oob. The local array is
7286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * to maintain word alignment
7296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 */
7306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint16_t ecc_oob[7];
7316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint8_t *oob = (uint8_t *)&ecc_oob[0];
7323f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn	unsigned int max_bitflips = 0;
7336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7346c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
7356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		chip->cmdfunc(mtd, NAND_CMD_READ0, s * eccsize, page);
7366c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		chip->ecc.hwctl(mtd, NAND_ECC_READ);
7376c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		chip->read_buf(mtd, p, eccsize);
7386c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7396c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		for (j = 0; j < eccbytes;) {
7406c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			off = ecc_place->eccplace[group].offset;
7416c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			len = ecc_place->eccplace[group].length;
7426c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			group++;
7436c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			/*
7454cbe1bf07a4dfc3ec2d81c4e8aee832384997bc4Vipin Kumar			 * length is intentionally kept a higher multiple of 2
7464cbe1bf07a4dfc3ec2d81c4e8aee832384997bc4Vipin Kumar			 * to read at least 13 bytes even in case of 16 bit NAND
7474cbe1bf07a4dfc3ec2d81c4e8aee832384997bc4Vipin Kumar			 * devices
7484cbe1bf07a4dfc3ec2d81c4e8aee832384997bc4Vipin Kumar			 */
749aea686b47c0cf97e0c6941799b523b6df87fc234Vipin Kumar			if (chip->options & NAND_BUSWIDTH_16)
750aea686b47c0cf97e0c6941799b523b6df87fc234Vipin Kumar				len = roundup(len, 2);
751aea686b47c0cf97e0c6941799b523b6df87fc234Vipin Kumar
7526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
7536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			chip->read_buf(mtd, oob + j, len);
7546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			j += len;
7556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		}
7566c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
757519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		memcpy(&ecc_code[i], oob, chip->ecc.bytes);
7586c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
7596c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
7613f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn		if (stat < 0) {
7626c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			mtd->ecc_stats.failed++;
7633f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn		} else {
7646c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			mtd->ecc_stats.corrected += stat;
7653f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn			max_bitflips = max_t(unsigned int, max_bitflips, stat);
7663f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn		}
7676c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
7686c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7693f91e94f7f511de74c0d2abe08672ccdbdd1961cMike Dunn	return max_bitflips;
7706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
7716c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
7726c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
773753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti * fsmc_bch8_correct_data
7746c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @mtd:	mtd info structure
7756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @dat:	buffer of read data
7766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @read_ecc:	ecc read from device spare area
7776c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @calc_ecc:	ecc calculated from read data
7786c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij *
7796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * calc_ecc is a 104 bit information containing maximum of 8 error
7806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * offset informations of 13 bits each in 512 bytes of read data.
7816c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
782753e0139e5569946056a8d5960111665a7f8f6f1Armando Viscontistatic int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
7836c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			     uint8_t *read_ecc, uint8_t *calc_ecc)
7846c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
7856c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = container_of(mtd,
7866c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij					struct fsmc_nand_data, mtd);
787519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	struct nand_chip *chip = mtd->priv;
7882a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar	void __iomem *regs = host->regs_va;
7896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	unsigned int bank = host->bank;
790a612c2ae483ee7e4d40c31d5374edf8a8b025f2aArmando Visconti	uint32_t err_idx[8];
7916c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	uint32_t num_err, i;
792753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	uint32_t ecc1, ecc2, ecc3, ecc4;
7936c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
794a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
795519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
796519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	/* no bit flipping */
797519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	if (likely(num_err == 0))
798519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		return 0;
799519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
800519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	/* too many errors */
801519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	if (unlikely(num_err > 8)) {
802519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		/*
803519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * This is a temporary erase check. A newly erased page read
804519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * would result in an ecc error because the oob data is also
805519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * erased to FF and the calculated ecc for an FF data is not
806519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * FF..FF.
807519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * This is a workaround to skip performing correction in case
808519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * data is FF..FF
809519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 *
810519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * Logic:
811519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * For every page, each bit written as 0 is counted until these
812519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * number of bits are greater than 8 (the maximum correction
813519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 * capability of FSMC for each 512 + 13 bytes)
814519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		 */
815519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
816519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		int bits_ecc = count_written_bits(read_ecc, chip->ecc.bytes, 8);
817519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		int bits_data = count_written_bits(dat, chip->ecc.size, 8);
818519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
819519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		if ((bits_ecc + bits_data) <= 8) {
820519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar			if (bits_data)
821519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar				memset(dat, 0xff, chip->ecc.size);
822519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar			return bits_data;
823519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		}
824519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
825519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar		return -EBADMSG;
826519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar	}
827519300cfe18ee8dcf0b1e7a38564b61b70e4ee86Vipin Kumar
8286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/*
8296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * ------------------- calc_ecc[] bit wise -----------|--13 bits--|
8306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--|
8316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 *
8326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * calc_ecc is a 104 bit information containing maximum of 8 error
8336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * offset informations of 13 bits each. calc_ecc is copied into a
8346c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * uint64_t array and error offset indexes are populated in err_idx
8356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * array
8366c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 */
837a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
838a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
839a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
840a4742d515071b8b7889a6b608da48d36c1dfcc71Vipin Kumar	ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
841753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti
842753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[0] = (ecc1 >> 0) & 0x1FFF;
843753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[1] = (ecc1 >> 13) & 0x1FFF;
844753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[2] = (((ecc2 >> 0) & 0x7F) << 6) | ((ecc1 >> 26) & 0x3F);
845753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[3] = (ecc2 >> 7) & 0x1FFF;
846753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[4] = (((ecc3 >> 0) & 0x1) << 12) | ((ecc2 >> 20) & 0xFFF);
847753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[5] = (ecc3 >> 1) & 0x1FFF;
848753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[6] = (ecc3 >> 14) & 0x1FFF;
849753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti	err_idx[7] = (((ecc4 >> 16) & 0xFF) << 5) | ((ecc3 >> 27) & 0x1F);
8506c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
8516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	i = 0;
8526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	while (num_err--) {
8536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		change_bit(0, (unsigned long *)&err_idx[i]);
8546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		change_bit(1, (unsigned long *)&err_idx[i]);
8556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
856b533f8d84f4f0807bf1bcf52017c6a267c8c4405Vipin Kumar		if (err_idx[i] < chip->ecc.size * 8) {
8576c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			change_bit(err_idx[i], (unsigned long *)dat);
8586c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			i++;
8596c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		}
8606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
8616c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return i;
8626c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
8636c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
8644774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarstatic bool filter(struct dma_chan *chan, void *slave)
8654774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar{
8664774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	chan->private = slave;
8674774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	return true;
8684774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar}
8694774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
870eea628199d5b12429c47db17035a954b0062e554Stefan Roese#ifdef CONFIG_OF
87106f25510692385ed4dadd23f7d3d064d1ab11c2dBill Pembertonstatic int fsmc_nand_probe_config_dt(struct platform_device *pdev,
872d8929942806270801023c90d78885e5347be718fGreg Kroah-Hartman				     struct device_node *np)
873eea628199d5b12429c47db17035a954b0062e554Stefan Roese{
874eea628199d5b12429c47db17035a954b0062e554Stefan Roese	struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
875eea628199d5b12429c47db17035a954b0062e554Stefan Roese	u32 val;
876eea628199d5b12429c47db17035a954b0062e554Stefan Roese
877eea628199d5b12429c47db17035a954b0062e554Stefan Roese	/* Set default NAND width to 8 bits */
878eea628199d5b12429c47db17035a954b0062e554Stefan Roese	pdata->width = 8;
879eea628199d5b12429c47db17035a954b0062e554Stefan Roese	if (!of_property_read_u32(np, "bank-width", &val)) {
880eea628199d5b12429c47db17035a954b0062e554Stefan Roese		if (val == 2) {
881eea628199d5b12429c47db17035a954b0062e554Stefan Roese			pdata->width = 16;
882eea628199d5b12429c47db17035a954b0062e554Stefan Roese		} else if (val != 1) {
883eea628199d5b12429c47db17035a954b0062e554Stefan Roese			dev_err(&pdev->dev, "invalid bank-width %u\n", val);
884eea628199d5b12429c47db17035a954b0062e554Stefan Roese			return -EINVAL;
885eea628199d5b12429c47db17035a954b0062e554Stefan Roese		}
886eea628199d5b12429c47db17035a954b0062e554Stefan Roese	}
887eea628199d5b12429c47db17035a954b0062e554Stefan Roese	if (of_get_property(np, "nand-skip-bbtscan", NULL))
888eea628199d5b12429c47db17035a954b0062e554Stefan Roese		pdata->options = NAND_SKIP_BBTSCAN;
889eea628199d5b12429c47db17035a954b0062e554Stefan Roese
89064ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	pdata->nand_timings = devm_kzalloc(&pdev->dev,
89164ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab				sizeof(*pdata->nand_timings), GFP_KERNEL);
892d9a21ae8e5f3fe2d940f54e45386b35b98cbcc35Jingoo Han	if (!pdata->nand_timings)
89364ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab		return -ENOMEM;
89464ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
89564ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab						sizeof(*pdata->nand_timings));
89664ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab
89764ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	/* Set default NAND bank to 0 */
89864ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	pdata->bank = 0;
89964ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	if (!of_property_read_u32(np, "bank", &val)) {
90064ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab		if (val > 3) {
90164ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab			dev_err(&pdev->dev, "invalid bank %u\n", val);
90264ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab			return -EINVAL;
90364ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab		}
90464ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab		pdata->bank = val;
90564ddba4d8a381b65bebee24c8da4eb80080c64a4Mian Yousaf Kaukab	}
906eea628199d5b12429c47db17035a954b0062e554Stefan Roese	return 0;
907eea628199d5b12429c47db17035a954b0062e554Stefan Roese}
908eea628199d5b12429c47db17035a954b0062e554Stefan Roese#else
90906f25510692385ed4dadd23f7d3d064d1ab11c2dBill Pembertonstatic int fsmc_nand_probe_config_dt(struct platform_device *pdev,
910d8929942806270801023c90d78885e5347be718fGreg Kroah-Hartman				     struct device_node *np)
911eea628199d5b12429c47db17035a954b0062e554Stefan Roese{
912eea628199d5b12429c47db17035a954b0062e554Stefan Roese	return -ENOSYS;
913eea628199d5b12429c47db17035a954b0062e554Stefan Roese}
914eea628199d5b12429c47db17035a954b0062e554Stefan Roese#endif
915eea628199d5b12429c47db17035a954b0062e554Stefan Roese
9166c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
9176c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * fsmc_nand_probe - Probe function
9186c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * @pdev:       platform device structure
9196c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
9206c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int __init fsmc_nand_probe(struct platform_device *pdev)
9216c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
9226c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
923eea628199d5b12429c47db17035a954b0062e554Stefan Roese	struct device_node __maybe_unused *np = pdev->dev.of_node;
924eea628199d5b12429c47db17035a954b0062e554Stefan Roese	struct mtd_part_parser_data ppdata = {};
9256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host;
9266c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct mtd_info *mtd;
9276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct nand_chip *nand;
9286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct resource *res;
9294774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	dma_cap_mask_t mask;
9304ad916bca7c372110815e77c2db95fb2eb2f8ab3Linus Walleij	int ret = 0;
931593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	u32 pid;
932593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	int i;
9336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
934eea628199d5b12429c47db17035a954b0062e554Stefan Roese	if (np) {
935eea628199d5b12429c47db17035a954b0062e554Stefan Roese		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
936eea628199d5b12429c47db17035a954b0062e554Stefan Roese		pdev->dev.platform_data = pdata;
937eea628199d5b12429c47db17035a954b0062e554Stefan Roese		ret = fsmc_nand_probe_config_dt(pdev, np);
938eea628199d5b12429c47db17035a954b0062e554Stefan Roese		if (ret) {
939eea628199d5b12429c47db17035a954b0062e554Stefan Roese			dev_err(&pdev->dev, "no platform data\n");
940eea628199d5b12429c47db17035a954b0062e554Stefan Roese			return -ENODEV;
941eea628199d5b12429c47db17035a954b0062e554Stefan Roese		}
942eea628199d5b12429c47db17035a954b0062e554Stefan Roese	}
943eea628199d5b12429c47db17035a954b0062e554Stefan Roese
9446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (!pdata) {
9456c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		dev_err(&pdev->dev, "platform data is NULL\n");
9466c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		return -EINVAL;
9476c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
9486c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9496c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/* Allocate memory for the device structure (and zero it) */
95082b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumar	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
951d9a21ae8e5f3fe2d940f54e45386b35b98cbcc35Jingoo Han	if (!host)
9526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		return -ENOMEM;
9536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
955b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	host->data_va = devm_ioremap_resource(&pdev->dev, res);
956b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	if (IS_ERR(host->data_va))
957b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding		return PTR_ERR(host->data_va);
958b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding
9596d7b42a447f92eb3e7e410bbf62042693eb040f7Jean-Christophe PLAGNIOL-VILLARD	host->data_pa = (dma_addr_t)res->start;
9606c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9616d7b42a447f92eb3e7e410bbf62042693eb040f7Jean-Christophe PLAGNIOL-VILLARD	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
962b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	host->addr_va = devm_ioremap_resource(&pdev->dev, res);
963b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	if (IS_ERR(host->addr_va))
964b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding		return PTR_ERR(host->addr_va);
9656c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9666d7b42a447f92eb3e7e410bbf62042693eb040f7Jean-Christophe PLAGNIOL-VILLARD	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
967b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	host->cmd_va = devm_ioremap_resource(&pdev->dev, res);
968b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	if (IS_ERR(host->cmd_va))
969b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding		return PTR_ERR(host->cmd_va);
9706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9716c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
972b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	host->regs_va = devm_ioremap_resource(&pdev->dev, res);
973b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding	if (IS_ERR(host->regs_va))
974b0de774c6334dccdcd43a7ef46155a1f3a52a954Thierry Reding		return PTR_ERR(host->regs_va);
9756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
9766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host->clk = clk_get(&pdev->dev, NULL);
9776c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (IS_ERR(host->clk)) {
9786c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		dev_err(&pdev->dev, "failed to fetch block clock\n");
97982b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumar		return PTR_ERR(host->clk);
9806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
9816c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
982e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar	ret = clk_prepare_enable(host->clk);
9836c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (ret)
984e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar		goto err_clk_prepare_enable;
9856c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
986593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	/*
987593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	 * This device ID is actually a common AMBA ID as used on the
988593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	 * AMBA PrimeCell bus. However it is not a PrimeCell.
989593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	 */
990593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	for (pid = 0, i = 0; i < 4; i++)
991593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij		pid |= (readl(host->regs_va + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
992593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	host->pid = pid;
993593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, "
994593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij		 "revision %02x, config %02x\n",
995593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij		 AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid),
996593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij		 AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid));
997593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij
9986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host->bank = pdata->bank;
9996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host->select_chip = pdata->select_bank;
10007147032485293fc24751e4dede98ff29050fd3bdVipin Kumar	host->partitions = pdata->partitions;
10017147032485293fc24751e4dede98ff29050fd3bdVipin Kumar	host->nr_partitions = pdata->nr_partitions;
1002712c4add03277197168210bb628b8273e36adf76Vipin Kumar	host->dev = &pdev->dev;
1003e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar	host->dev_timings = pdata->nand_timings;
10044774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	host->mode = pdata->mode;
10054774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
10064774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (host->mode == USE_DMA_ACCESS)
10074774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		init_completion(&host->dma_access_complete);
10084774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
10096c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/* Link all private pointers */
10106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	mtd = &host->mtd;
10116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand = &host->nand;
10126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	mtd->priv = nand;
10136c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->priv = host;
10146c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
10156c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host->mtd.owner = THIS_MODULE;
10166c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->IO_ADDR_R = host->data_va;
10176c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->IO_ADDR_W = host->data_va;
10186c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->cmd_ctrl = fsmc_cmd_ctrl;
10196c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->chip_delay = 30;
10206c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
10216c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->ecc.mode = NAND_ECC_HW;
10226c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->ecc.hwctl = fsmc_enable_hwecc;
10236c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->ecc.size = 512;
10246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->options = pdata->options;
10256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	nand->select_chip = fsmc_select_chip;
1026467e6e7be2e26fd5bbaabd849717d37de99df8f1Vipin Kumar	nand->badblockbits = 7;
10276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
10286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (pdata->width == FSMC_NAND_BW16)
10296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->options |= NAND_BUSWIDTH_16;
10306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
10314774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	switch (host->mode) {
10324774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	case USE_DMA_ACCESS:
10334774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_cap_zero(mask);
10344774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_cap_set(DMA_MEMCPY, mask);
10354774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		host->read_dma_chan = dma_request_channel(mask, filter,
10364774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar				pdata->read_dma_priv);
10374774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		if (!host->read_dma_chan) {
10384774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			dev_err(&pdev->dev, "Unable to get read dma channel\n");
10394774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			goto err_req_read_chnl;
10404774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		}
10414774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		host->write_dma_chan = dma_request_channel(mask, filter,
10424774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar				pdata->write_dma_priv);
10434774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		if (!host->write_dma_chan) {
10444774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			dev_err(&pdev->dev, "Unable to get write dma channel\n");
10454774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			goto err_req_write_chnl;
10464774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		}
10474774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		nand->read_buf = fsmc_read_buf_dma;
10484774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		nand->write_buf = fsmc_write_buf_dma;
10494774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		break;
10504774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
10514774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	default:
10524774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	case USE_WORD_ACCESS:
1053604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		nand->read_buf = fsmc_read_buf;
1054604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar		nand->write_buf = fsmc_write_buf;
10554774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		break;
1056604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar	}
1057604e75444fa82cfdcba339e3bd4da1dfd6947539Vipin Kumar
10582a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar	fsmc_nand_setup(host->regs_va, host->bank,
10592a5dbead29a7c081a47133eb428440147a6d8d5aVipin Kumar			nand->options & NAND_BUSWIDTH_16,
1060e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar			host->dev_timings);
10616c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
1062593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	if (AMBA_REV_BITS(host->pid) >= 8) {
10636c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.read_page = fsmc_read_page_hwecc;
10646c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.calculate = fsmc_read_hwecc_ecc4;
1065753e0139e5569946056a8d5960111665a7f8f6f1Armando Visconti		nand->ecc.correct = fsmc_bch8_correct_data;
10666c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.bytes = 13;
10676a918bade9dab40aaef80559bd1169c69e8d69cbMike Dunn		nand->ecc.strength = 8;
10686c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	} else {
10696c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.calculate = fsmc_read_hwecc_ecc1;
10706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.correct = nand_correct_data;
10716c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		nand->ecc.bytes = 3;
10726a918bade9dab40aaef80559bd1169c69e8d69cbMike Dunn		nand->ecc.strength = 1;
10736c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
10746c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
10756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/*
107625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * Scan to find existence of the device
10776c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 */
10786c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (nand_scan_ident(&host->mtd, 1, NULL)) {
10796c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		ret = -ENXIO;
10806c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		dev_err(&pdev->dev, "No NAND Device found!\n");
108182b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumar		goto err_scan_ident;
10826c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
10836c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
1084593cd8711221c9661dbf9beb2fb42fecca03e693Linus Walleij	if (AMBA_REV_BITS(host->pid) >= 8) {
1085e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		switch (host->mtd.oobsize) {
1086e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 16:
1087e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc4_16_layout;
10886c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			host->ecc_place = &fsmc_ecc4_sp_place;
1089e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1090e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 64:
1091e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc4_64_layout;
1092e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			host->ecc_place = &fsmc_ecc4_lp_place;
1093e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1094e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 128:
1095e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc4_128_layout;
1096e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			host->ecc_place = &fsmc_ecc4_lp_place;
1097e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
10980c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti		case 224:
10990c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti			nand->ecc.layout = &fsmc_ecc4_224_layout;
11000c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti			host->ecc_place = &fsmc_ecc4_lp_place;
11010c78e93b44f39d4e5dfd4ebfc529cd74ac2a9bbbArmando Visconti			break;
1102e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 256:
1103e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc4_256_layout;
11046c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij			host->ecc_place = &fsmc_ecc4_lp_place;
1105e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1106e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		default:
110767b19a631eb0a21584ff179f93c0dd93f94f8ce0Jingoo Han			dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
110867b19a631eb0a21584ff179f93c0dd93f94f8ce0Jingoo Han				 mtd->oobsize);
1109e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			BUG();
11106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		}
11116c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	} else {
1112e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		switch (host->mtd.oobsize) {
1113e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 16:
1114e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc1_16_layout;
1115e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1116e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 64:
1117e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc1_64_layout;
1118e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1119e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		case 128:
1120e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			nand->ecc.layout = &fsmc_ecc1_128_layout;
1121e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			break;
1122e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		default:
112367b19a631eb0a21584ff179f93c0dd93f94f8ce0Jingoo Han			dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
112467b19a631eb0a21584ff179f93c0dd93f94f8ce0Jingoo Han				 mtd->oobsize);
1125e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav			BUG();
1126e29ee57b1d33abf119cb332a3d8fa69c9cd39096Bhavna Yadav		}
11276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
11286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11296c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/* Second stage of scan to fill MTD data-structures */
11306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (nand_scan_tail(&host->mtd)) {
11316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		ret = -ENXIO;
11326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		goto err_probe;
11336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
11346c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/*
11366c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * The partition information can is accessed by (in the same precedence)
11376c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 *
11386c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * command line through Bootloader,
11396c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * platform data,
11406c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 * default partition information present in driver.
11416c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 */
11426c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	/*
11438d3f8bb8093080d4e2b1de096af444b694a16766Dmitry Eremin-Solenikov	 * Check for partition info passed
11446c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	 */
11456c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	host->mtd.name = "nand";
1146eea628199d5b12429c47db17035a954b0062e554Stefan Roese	ppdata.of_node = np;
1147eea628199d5b12429c47db17035a954b0062e554Stefan Roese	ret = mtd_device_parse_register(&host->mtd, NULL, &ppdata,
11487147032485293fc24751e4dede98ff29050fd3bdVipin Kumar					host->partitions, host->nr_partitions);
114999335d0002439b92917512dd8baeff60f774809fJamie Iles	if (ret)
11506c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		goto err_probe;
11516c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11526c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	platform_set_drvdata(pdev, host);
11536c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	dev_info(&pdev->dev, "FSMC NAND driver registration successful\n");
11546c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
11556c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11566c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijerr_probe:
115782b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumarerr_scan_ident:
11584774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (host->mode == USE_DMA_ACCESS)
11594774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_release_channel(host->write_dma_chan);
11604774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarerr_req_write_chnl:
11614774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar	if (host->mode == USE_DMA_ACCESS)
11624774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		dma_release_channel(host->read_dma_chan);
11634774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumarerr_req_read_chnl:
1164e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar	clk_disable_unprepare(host->clk);
1165e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumarerr_clk_prepare_enable:
116682b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumar	clk_put(host->clk);
11676c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return ret;
11686c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
11696c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11706c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij/*
11716c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij * Clean up routine
11726c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij */
11736c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_nand_remove(struct platform_device *pdev)
11746c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
11756c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = platform_get_drvdata(pdev);
11766c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
11776c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (host) {
117882e023ab4e144da7f83fe7e6c93a09be2f30ff07Axel Lin		nand_release(&host->mtd);
11794774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar
11804774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		if (host->mode == USE_DMA_ACCESS) {
11814774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			dma_release_channel(host->write_dma_chan);
11824774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar			dma_release_channel(host->read_dma_chan);
11834774fb0a48aacfec206e6d54ecf58706f6a5320aVipin Kumar		}
1184e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar		clk_disable_unprepare(host->clk);
11856c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		clk_put(host->clk);
11866c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	}
118782b9dbe2e0f6870bf385b759b91e403b62a60c5eVipin Kumar
11886c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
11896c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
11906c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
119180ce4dde2f4fa75cec71790d8f582a4ca00dbdb0Jingoo Han#ifdef CONFIG_PM_SLEEP
11926c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_nand_suspend(struct device *dev)
11936c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
11946c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = dev_get_drvdata(dev);
11956c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	if (host)
1196e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar		clk_disable_unprepare(host->clk);
11976c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
11986c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
11996c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
12006c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic int fsmc_nand_resume(struct device *dev)
12016c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij{
12026c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	struct fsmc_nand_data *host = dev_get_drvdata(dev);
1203f63acb75c5d8a9eb7cc5548e3e778d2a00bf3baeShiraz Hashim	if (host) {
1204e25da1c07dfb318628a8a86f0967914dc4fd135eViresh Kumar		clk_prepare_enable(host->clk);
1205f63acb75c5d8a9eb7cc5548e3e778d2a00bf3baeShiraz Hashim		fsmc_nand_setup(host->regs_va, host->bank,
1206e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar				host->nand.options & NAND_BUSWIDTH_16,
1207e2f6bce8d94d2c82d4f7ae9d94743963a3b10136Vipin Kumar				host->dev_timings);
1208f63acb75c5d8a9eb7cc5548e3e778d2a00bf3baeShiraz Hashim	}
12096c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	return 0;
12106c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij}
121180ce4dde2f4fa75cec71790d8f582a4ca00dbdb0Jingoo Han#endif
12126c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
1213f63acb75c5d8a9eb7cc5548e3e778d2a00bf3baeShiraz Hashimstatic SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);
12146c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
1215eea628199d5b12429c47db17035a954b0062e554Stefan Roese#ifdef CONFIG_OF
1216eea628199d5b12429c47db17035a954b0062e554Stefan Roesestatic const struct of_device_id fsmc_nand_id_table[] = {
1217eea628199d5b12429c47db17035a954b0062e554Stefan Roese	{ .compatible = "st,spear600-fsmc-nand" },
1218ba785205502f9a03d4ee31bdc3a1228ba5465f00Linus Walleij	{ .compatible = "stericsson,fsmc-nand" },
1219eea628199d5b12429c47db17035a954b0062e554Stefan Roese	{}
1220eea628199d5b12429c47db17035a954b0062e554Stefan Roese};
1221eea628199d5b12429c47db17035a954b0062e554Stefan RoeseMODULE_DEVICE_TABLE(of, fsmc_nand_id_table);
1222eea628199d5b12429c47db17035a954b0062e554Stefan Roese#endif
1223eea628199d5b12429c47db17035a954b0062e554Stefan Roese
12246c009ab89a212b4364cdb74192d438f542fb291cLinus Walleijstatic struct platform_driver fsmc_nand_driver = {
12256c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.remove = fsmc_nand_remove,
12266c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	.driver = {
12276c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		.owner = THIS_MODULE,
12286c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		.name = "fsmc-nand",
1229eea628199d5b12429c47db17035a954b0062e554Stefan Roese		.of_match_table = of_match_ptr(fsmc_nand_id_table),
12306c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij		.pm = &fsmc_nand_pm_ops,
12316c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij	},
12326c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij};
12336c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
1234307d2a5156eb5778fbc1fc29b0e31d34de9efcfcJingoo Hanmodule_platform_driver_probe(fsmc_nand_driver, fsmc_nand_probe);
12356c009ab89a212b4364cdb74192d438f542fb291cLinus Walleij
12366c009ab89a212b4364cdb74192d438f542fb291cLinus WalleijMODULE_LICENSE("GPL");
12376c009ab89a212b4364cdb74192d438f542fb291cLinus WalleijMODULE_AUTHOR("Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi");
12386c009ab89a212b4364cdb74192d438f542fb291cLinus WalleijMODULE_DESCRIPTION("NAND driver for SPEAr Platforms");
1239