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