2010-09-13 00:35:22 +02:00
/*
* drivers / mtd / nand / fsmc_nand . c
*
* ST Microelectronics
* Flexible Static Memory Controller ( FSMC )
* Driver for NAND portions
*
* Copyright © 2010 ST Microelectronics
* Vipin Kumar < vipin . kumar @ st . com >
* Ashish Priyadarshi
*
* Based on drivers / mtd / nand / nomadik_nand . c
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# include <linux/clk.h>
2012-03-14 11:47:18 +05:30
# include <linux/completion.h>
# include <linux/dmaengine.h>
# include <linux/dma-direction.h>
# include <linux/dma-mapping.h>
2010-09-13 00:35:22 +02:00
# include <linux/err.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/resource.h>
# include <linux/sched.h>
# include <linux/types.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/nand.h>
# include <linux/mtd/nand_ecc.h>
# include <linux/platform_device.h>
2012-03-16 10:19:31 +01:00
# include <linux/of.h>
2010-09-13 00:35:22 +02:00
# include <linux/mtd/partitions.h>
# include <linux/io.h>
# include <linux/slab.h>
# include <linux/mtd/fsmc.h>
2010-11-29 13:52:19 +01:00
# include <linux/amba/bus.h>
2010-09-13 00:35:22 +02:00
# include <mtd/mtd-abi.h>
2012-03-07 17:00:50 +05:30
static struct nand_ecclayout fsmc_ecc1_128_layout = {
2010-09-13 00:35:22 +02:00
. eccbytes = 24 ,
. eccpos = { 2 , 3 , 4 , 18 , 19 , 20 , 34 , 35 , 36 , 50 , 51 , 52 ,
66 , 67 , 68 , 82 , 83 , 84 , 98 , 99 , 100 , 114 , 115 , 116 } ,
. oobfree = {
{ . offset = 8 , . length = 8 } ,
{ . offset = 24 , . length = 8 } ,
{ . offset = 40 , . length = 8 } ,
{ . offset = 56 , . length = 8 } ,
{ . offset = 72 , . length = 8 } ,
{ . offset = 88 , . length = 8 } ,
{ . offset = 104 , . length = 8 } ,
{ . offset = 120 , . length = 8 }
}
} ;
2012-03-07 17:00:50 +05:30
static struct nand_ecclayout fsmc_ecc1_64_layout = {
. eccbytes = 12 ,
. eccpos = { 2 , 3 , 4 , 18 , 19 , 20 , 34 , 35 , 36 , 50 , 51 , 52 } ,
. oobfree = {
{ . offset = 8 , . length = 8 } ,
{ . offset = 24 , . length = 8 } ,
{ . offset = 40 , . length = 8 } ,
{ . offset = 56 , . length = 8 } ,
}
} ;
static struct nand_ecclayout fsmc_ecc1_16_layout = {
. eccbytes = 3 ,
. eccpos = { 2 , 3 , 4 } ,
. oobfree = {
{ . offset = 8 , . length = 8 } ,
}
} ;
/*
* ECC4 layout for NAND of pagesize 8192 bytes & OOBsize 256 bytes . 13 * 16 bytes
* of OB size is reserved for ECC , Byte no . 0 & 1 reserved for bad block and 46
* bytes are free for use .
*/
static struct nand_ecclayout fsmc_ecc4_256_layout = {
. eccbytes = 208 ,
. eccpos = { 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14 ,
18 , 19 , 20 , 21 , 22 , 23 , 24 ,
25 , 26 , 27 , 28 , 29 , 30 ,
34 , 35 , 36 , 37 , 38 , 39 , 40 ,
41 , 42 , 43 , 44 , 45 , 46 ,
50 , 51 , 52 , 53 , 54 , 55 , 56 ,
57 , 58 , 59 , 60 , 61 , 62 ,
66 , 67 , 68 , 69 , 70 , 71 , 72 ,
73 , 74 , 75 , 76 , 77 , 78 ,
82 , 83 , 84 , 85 , 86 , 87 , 88 ,
89 , 90 , 91 , 92 , 93 , 94 ,
98 , 99 , 100 , 101 , 102 , 103 , 104 ,
105 , 106 , 107 , 108 , 109 , 110 ,
114 , 115 , 116 , 117 , 118 , 119 , 120 ,
121 , 122 , 123 , 124 , 125 , 126 ,
130 , 131 , 132 , 133 , 134 , 135 , 136 ,
137 , 138 , 139 , 140 , 141 , 142 ,
146 , 147 , 148 , 149 , 150 , 151 , 152 ,
153 , 154 , 155 , 156 , 157 , 158 ,
162 , 163 , 164 , 165 , 166 , 167 , 168 ,
169 , 170 , 171 , 172 , 173 , 174 ,
178 , 179 , 180 , 181 , 182 , 183 , 184 ,
185 , 186 , 187 , 188 , 189 , 190 ,
194 , 195 , 196 , 197 , 198 , 199 , 200 ,
201 , 202 , 203 , 204 , 205 , 206 ,
210 , 211 , 212 , 213 , 214 , 215 , 216 ,
217 , 218 , 219 , 220 , 221 , 222 ,
226 , 227 , 228 , 229 , 230 , 231 , 232 ,
233 , 234 , 235 , 236 , 237 , 238 ,
242 , 243 , 244 , 245 , 246 , 247 , 248 ,
249 , 250 , 251 , 252 , 253 , 254
} ,
. oobfree = {
{ . offset = 15 , . length = 3 } ,
{ . offset = 31 , . length = 3 } ,
{ . offset = 47 , . length = 3 } ,
{ . offset = 63 , . length = 3 } ,
{ . offset = 79 , . length = 3 } ,
{ . offset = 95 , . length = 3 } ,
{ . offset = 111 , . length = 3 } ,
{ . offset = 127 , . length = 3 } ,
{ . offset = 143 , . length = 3 } ,
{ . offset = 159 , . length = 3 } ,
{ . offset = 175 , . length = 3 } ,
{ . offset = 191 , . length = 3 } ,
{ . offset = 207 , . length = 3 } ,
{ . offset = 223 , . length = 3 } ,
{ . offset = 239 , . length = 3 } ,
{ . offset = 255 , . length = 1 }
}
} ;
2012-03-07 17:00:55 +05:30
/*
* ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 224 bytes . 13 * 8 bytes
* of OOB size is reserved for ECC , Byte no . 0 & 1 reserved for bad block & 118
* bytes are free for use .
*/
static struct nand_ecclayout fsmc_ecc4_224_layout = {
. eccbytes = 104 ,
. eccpos = { 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14 ,
18 , 19 , 20 , 21 , 22 , 23 , 24 ,
25 , 26 , 27 , 28 , 29 , 30 ,
34 , 35 , 36 , 37 , 38 , 39 , 40 ,
41 , 42 , 43 , 44 , 45 , 46 ,
50 , 51 , 52 , 53 , 54 , 55 , 56 ,
57 , 58 , 59 , 60 , 61 , 62 ,
66 , 67 , 68 , 69 , 70 , 71 , 72 ,
73 , 74 , 75 , 76 , 77 , 78 ,
82 , 83 , 84 , 85 , 86 , 87 , 88 ,
89 , 90 , 91 , 92 , 93 , 94 ,
98 , 99 , 100 , 101 , 102 , 103 , 104 ,
105 , 106 , 107 , 108 , 109 , 110 ,
114 , 115 , 116 , 117 , 118 , 119 , 120 ,
121 , 122 , 123 , 124 , 125 , 126
} ,
. oobfree = {
{ . offset = 15 , . length = 3 } ,
{ . offset = 31 , . length = 3 } ,
{ . offset = 47 , . length = 3 } ,
{ . offset = 63 , . length = 3 } ,
{ . offset = 79 , . length = 3 } ,
{ . offset = 95 , . length = 3 } ,
{ . offset = 111 , . length = 3 } ,
{ . offset = 127 , . length = 97 }
}
} ;
2012-03-07 17:00:50 +05:30
/*
* ECC4 layout for NAND of pagesize 4096 bytes & OOBsize 128 bytes . 13 * 8 bytes
* of OOB size is reserved for ECC , Byte no . 0 & 1 reserved for bad block & 22
* bytes are free for use .
*/
static struct nand_ecclayout fsmc_ecc4_128_layout = {
2010-09-13 00:35:22 +02:00
. eccbytes = 104 ,
. eccpos = { 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14 ,
18 , 19 , 20 , 21 , 22 , 23 , 24 ,
25 , 26 , 27 , 28 , 29 , 30 ,
34 , 35 , 36 , 37 , 38 , 39 , 40 ,
41 , 42 , 43 , 44 , 45 , 46 ,
50 , 51 , 52 , 53 , 54 , 55 , 56 ,
57 , 58 , 59 , 60 , 61 , 62 ,
66 , 67 , 68 , 69 , 70 , 71 , 72 ,
73 , 74 , 75 , 76 , 77 , 78 ,
82 , 83 , 84 , 85 , 86 , 87 , 88 ,
89 , 90 , 91 , 92 , 93 , 94 ,
98 , 99 , 100 , 101 , 102 , 103 , 104 ,
105 , 106 , 107 , 108 , 109 , 110 ,
114 , 115 , 116 , 117 , 118 , 119 , 120 ,
121 , 122 , 123 , 124 , 125 , 126
} ,
. oobfree = {
{ . offset = 15 , . length = 3 } ,
{ . offset = 31 , . length = 3 } ,
{ . offset = 47 , . length = 3 } ,
{ . offset = 63 , . length = 3 } ,
{ . offset = 79 , . length = 3 } ,
{ . offset = 95 , . length = 3 } ,
{ . offset = 111 , . length = 3 } ,
{ . offset = 127 , . length = 1 }
}
} ;
2012-03-07 17:00:50 +05:30
/*
* ECC4 layout for NAND of pagesize 2048 bytes & OOBsize 64 bytes . 13 * 4 bytes of
* OOB size is reserved for ECC , Byte no . 0 & 1 reserved for bad block and 10
* bytes are free for use .
*/
static struct nand_ecclayout fsmc_ecc4_64_layout = {
. eccbytes = 52 ,
. eccpos = { 2 , 3 , 4 , 5 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14 ,
18 , 19 , 20 , 21 , 22 , 23 , 24 ,
25 , 26 , 27 , 28 , 29 , 30 ,
34 , 35 , 36 , 37 , 38 , 39 , 40 ,
41 , 42 , 43 , 44 , 45 , 46 ,
50 , 51 , 52 , 53 , 54 , 55 , 56 ,
57 , 58 , 59 , 60 , 61 , 62 ,
} ,
. oobfree = {
{ . offset = 15 , . length = 3 } ,
{ . offset = 31 , . length = 3 } ,
{ . offset = 47 , . length = 3 } ,
{ . offset = 63 , . length = 1 } ,
}
} ;
/*
* ECC4 layout for NAND of pagesize 512 bytes & OOBsize 16 bytes . 13 bytes of
* OOB size is reserved for ECC , Byte no . 4 & 5 reserved for bad block and One
* byte is free for use .
*/
static struct nand_ecclayout fsmc_ecc4_16_layout = {
. eccbytes = 13 ,
. eccpos = { 0 , 1 , 2 , 3 , 6 , 7 , 8 ,
9 , 10 , 11 , 12 , 13 , 14
} ,
. oobfree = {
{ . offset = 15 , . length = 1 } ,
}
} ;
2010-09-13 00:35:22 +02:00
/*
* ECC placement definitions in oobfree type format .
* There are 13 bytes of ecc for every 512 byte block and it has to be read
* consecutively and immediately after the 512 byte data block for hardware to
* generate the error bit offsets in 512 byte data .
* Managing the ecc bytes in the following way makes it easier for software to
* read ecc bytes consecutive to data bytes . This way is similar to
* oobfree structure maintained already in generic nand driver
*/
static struct fsmc_eccplace fsmc_ecc4_lp_place = {
. eccplace = {
{ . offset = 2 , . length = 13 } ,
{ . offset = 18 , . length = 13 } ,
{ . offset = 34 , . length = 13 } ,
{ . offset = 50 , . length = 13 } ,
{ . offset = 66 , . length = 13 } ,
{ . offset = 82 , . length = 13 } ,
{ . offset = 98 , . length = 13 } ,
{ . offset = 114 , . length = 13 }
}
} ;
static struct fsmc_eccplace fsmc_ecc4_sp_place = {
. eccplace = {
{ . offset = 0 , . length = 4 } ,
{ . offset = 6 , . length = 9 }
}
} ;
/**
2010-11-29 13:52:19 +01:00
* struct fsmc_nand_data - structure for FSMC NAND device state
2010-09-13 00:35:22 +02:00
*
2010-11-29 13:52:19 +01:00
* @ pid : Part ID on the AMBA PrimeCell format
2010-09-13 00:35:22 +02:00
* @ mtd : MTD info for a NAND flash .
* @ nand : Chip related info for a NAND flash .
2012-03-14 11:47:07 +05:30
* @ partitions : Partition info for a NAND Flash .
* @ nr_partitions : Total number of partition of a NAND flash .
2010-09-13 00:35:22 +02:00
*
* @ ecc_place : ECC placing locations in oobfree type format .
* @ bank : Bank number for probed device .
* @ clk : Clock structure for FSMC .
*
2012-03-14 11:47:18 +05:30
* @ read_dma_chan : DMA channel for read access
* @ write_dma_chan : DMA channel for write access to NAND
* @ dma_access_complete : Completion structure
*
* @ data_pa : NAND Physical port for Data .
2010-09-13 00:35:22 +02:00
* @ data_va : NAND port for Data .
* @ cmd_va : NAND port for Command .
* @ addr_va : NAND port for Address .
* @ regs_va : FSMC regs base address .
*/
struct fsmc_nand_data {
2010-11-29 13:52:19 +01:00
u32 pid ;
2010-09-13 00:35:22 +02:00
struct nand_chip nand ;
2012-03-14 11:47:07 +05:30
struct mtd_partition * partitions ;
unsigned int nr_partitions ;
2010-09-13 00:35:22 +02:00
struct fsmc_eccplace * ecc_place ;
unsigned int bank ;
2012-03-14 11:47:16 +05:30
struct device * dev ;
2012-03-14 11:47:18 +05:30
enum access_mode mode ;
2010-09-13 00:35:22 +02:00
struct clk * clk ;
2012-03-14 11:47:18 +05:30
/* DMA related objects */
struct dma_chan * read_dma_chan ;
struct dma_chan * write_dma_chan ;
struct completion dma_access_complete ;
2012-03-14 11:47:14 +05:30
struct fsmc_nand_timings * dev_timings ;
2012-03-14 11:47:18 +05:30
dma_addr_t data_pa ;
2010-09-13 00:35:22 +02:00
void __iomem * data_va ;
void __iomem * cmd_va ;
void __iomem * addr_va ;
void __iomem * regs_va ;
void ( * select_chip ) ( uint32_t bank , uint32_t busw ) ;
} ;
2015-12-10 08:59:46 +01:00
static inline struct fsmc_nand_data * mtd_to_fsmc ( struct mtd_info * mtd )
{
2015-12-10 09:00:05 +01:00
return container_of ( mtd_to_nand ( mtd ) , struct fsmc_nand_data , nand ) ;
2015-12-10 08:59:46 +01:00
}
2010-09-13 00:35:22 +02:00
/* Assert CS signal based on chipnr */
static void fsmc_select_chip ( struct mtd_info * mtd , int chipnr )
{
2015-12-01 12:03:04 +01:00
struct nand_chip * chip = mtd_to_nand ( mtd ) ;
2010-09-13 00:35:22 +02:00
struct fsmc_nand_data * host ;
2015-12-10 08:59:46 +01:00
host = mtd_to_fsmc ( mtd ) ;
2010-09-13 00:35:22 +02:00
switch ( chipnr ) {
case - 1 :
chip - > cmd_ctrl ( mtd , NAND_CMD_NONE , 0 | NAND_CTRL_CHANGE ) ;
break ;
case 0 :
case 1 :
case 2 :
case 3 :
if ( host - > select_chip )
host - > select_chip ( chipnr ,
chip - > options & NAND_BUSWIDTH_16 ) ;
break ;
default :
2015-10-02 12:40:21 +02:00
dev_err ( host - > dev , " unsupported chip-select %d \n " , chipnr ) ;
2010-09-13 00:35:22 +02:00
}
}
/*
* fsmc_cmd_ctrl - For facilitaing Hardware access
* This routine allows hardware specific access to control - lines ( ALE , CLE )
*/
static void fsmc_cmd_ctrl ( struct mtd_info * mtd , int cmd , unsigned int ctrl )
{
2015-12-01 12:03:04 +01:00
struct nand_chip * this = mtd_to_nand ( mtd ) ;
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-10-09 16:14:43 +05:30
void __iomem * regs = host - > regs_va ;
2010-09-13 00:35:22 +02:00
unsigned int bank = host - > bank ;
if ( ctrl & NAND_CTRL_CHANGE ) {
2012-03-14 11:47:19 +05:30
u32 pc ;
2010-09-13 00:35:22 +02:00
if ( ctrl & NAND_CLE ) {
2012-03-14 11:47:19 +05:30
this - > IO_ADDR_R = host - > cmd_va ;
this - > IO_ADDR_W = host - > cmd_va ;
2010-09-13 00:35:22 +02:00
} else if ( ctrl & NAND_ALE ) {
2012-03-14 11:47:19 +05:30
this - > IO_ADDR_R = host - > addr_va ;
this - > IO_ADDR_W = host - > addr_va ;
2010-09-13 00:35:22 +02:00
} else {
2012-03-14 11:47:19 +05:30
this - > IO_ADDR_R = host - > data_va ;
this - > IO_ADDR_W = host - > data_va ;
2010-09-13 00:35:22 +02:00
}
2012-03-14 11:47:19 +05:30
pc = readl ( FSMC_NAND_REG ( regs , bank , PC ) ) ;
if ( ctrl & NAND_NCE )
pc | = FSMC_ENABLE ;
else
pc & = ~ FSMC_ENABLE ;
2012-10-09 16:14:50 +05:30
writel_relaxed ( pc , FSMC_NAND_REG ( regs , bank , PC ) ) ;
2010-09-13 00:35:22 +02:00
}
mb ( ) ;
if ( cmd ! = NAND_CMD_NONE )
2012-10-09 16:14:50 +05:30
writeb_relaxed ( cmd , this - > IO_ADDR_W ) ;
2010-09-13 00:35:22 +02:00
}
/*
* fsmc_nand_setup - FSMC ( Flexible Static Memory Controller ) init routine
*
* This routine initializes timing parameters related to NAND memory access in
* FSMC registers
*/
2012-03-14 11:47:19 +05:30
static void fsmc_nand_setup ( void __iomem * regs , uint32_t bank ,
2012-03-14 11:47:14 +05:30
uint32_t busw , struct fsmc_nand_timings * timings )
2010-09-13 00:35:22 +02:00
{
uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON ;
2012-03-14 11:47:14 +05:30
uint32_t tclr , tar , thiz , thold , twait , tset ;
struct fsmc_nand_timings * tims ;
struct fsmc_nand_timings default_timings = {
. tclr = FSMC_TCLR_1 ,
. tar = FSMC_TAR_1 ,
. thiz = FSMC_THIZ_1 ,
. thold = FSMC_THOLD_4 ,
. twait = FSMC_TWAIT_6 ,
. tset = FSMC_TSET_0 ,
} ;
if ( timings )
tims = timings ;
else
tims = & default_timings ;
tclr = ( tims - > tclr & FSMC_TCLR_MASK ) < < FSMC_TCLR_SHIFT ;
tar = ( tims - > tar & FSMC_TAR_MASK ) < < FSMC_TAR_SHIFT ;
thiz = ( tims - > thiz & FSMC_THIZ_MASK ) < < FSMC_THIZ_SHIFT ;
thold = ( tims - > thold & FSMC_THOLD_MASK ) < < FSMC_THOLD_SHIFT ;
twait = ( tims - > twait & FSMC_TWAIT_MASK ) < < FSMC_TWAIT_SHIFT ;
tset = ( tims - > tset & FSMC_TSET_MASK ) < < FSMC_TSET_SHIFT ;
2010-09-13 00:35:22 +02:00
if ( busw )
2012-10-09 16:14:50 +05:30
writel_relaxed ( value | FSMC_DEVWID_16 ,
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2010-09-13 00:35:22 +02:00
else
2012-10-09 16:14:50 +05:30
writel_relaxed ( value | FSMC_DEVWID_8 ,
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2010-09-13 00:35:22 +02:00
2012-10-09 16:14:50 +05:30
writel_relaxed ( readl ( FSMC_NAND_REG ( regs , bank , PC ) ) | tclr | tar ,
2012-03-14 11:47:19 +05:30
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2012-10-09 16:14:50 +05:30
writel_relaxed ( thiz | thold | twait | tset ,
FSMC_NAND_REG ( regs , bank , COMM ) ) ;
writel_relaxed ( thiz | thold | twait | tset ,
FSMC_NAND_REG ( regs , bank , ATTRIB ) ) ;
2010-09-13 00:35:22 +02:00
}
/*
* fsmc_enable_hwecc - Enables Hardware ECC through FSMC registers
*/
static void fsmc_enable_hwecc ( struct mtd_info * mtd , int mode )
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:19 +05:30
void __iomem * regs = host - > regs_va ;
2010-09-13 00:35:22 +02:00
uint32_t bank = host - > bank ;
2012-10-09 16:14:50 +05:30
writel_relaxed ( readl ( FSMC_NAND_REG ( regs , bank , PC ) ) & ~ FSMC_ECCPLEN_256 ,
2012-03-14 11:47:19 +05:30
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2012-10-09 16:14:50 +05:30
writel_relaxed ( readl ( FSMC_NAND_REG ( regs , bank , PC ) ) & ~ FSMC_ECCEN ,
2012-03-14 11:47:19 +05:30
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2012-10-09 16:14:50 +05:30
writel_relaxed ( readl ( FSMC_NAND_REG ( regs , bank , PC ) ) | FSMC_ECCEN ,
2012-03-14 11:47:19 +05:30
FSMC_NAND_REG ( regs , bank , PC ) ) ;
2010-09-13 00:35:22 +02:00
}
/*
* fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by
2011-03-30 22:57:33 -03:00
* FSMC . ECC is 13 bytes for 512 bytes of data ( supports error correction up to
2010-09-13 00:35:22 +02:00
* max of 8 - bits )
*/
static int fsmc_read_hwecc_ecc4 ( struct mtd_info * mtd , const uint8_t * data ,
uint8_t * ecc )
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:19 +05:30
void __iomem * regs = host - > regs_va ;
2010-09-13 00:35:22 +02:00
uint32_t bank = host - > bank ;
uint32_t ecc_tmp ;
unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT ;
do {
2012-10-09 16:14:50 +05:30
if ( readl_relaxed ( FSMC_NAND_REG ( regs , bank , STS ) ) & FSMC_CODE_RDY )
2010-09-13 00:35:22 +02:00
break ;
else
cond_resched ( ) ;
} while ( ! time_after_eq ( jiffies , deadline ) ) ;
2012-03-14 11:47:16 +05:30
if ( time_after_eq ( jiffies , deadline ) ) {
dev_err ( host - > dev , " calculate ecc timed out \n " ) ;
return - ETIMEDOUT ;
}
2012-10-09 16:14:50 +05:30
ecc_tmp = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC1 ) ) ;
2010-09-13 00:35:22 +02:00
ecc [ 0 ] = ( uint8_t ) ( ecc_tmp > > 0 ) ;
ecc [ 1 ] = ( uint8_t ) ( ecc_tmp > > 8 ) ;
ecc [ 2 ] = ( uint8_t ) ( ecc_tmp > > 16 ) ;
ecc [ 3 ] = ( uint8_t ) ( ecc_tmp > > 24 ) ;
2012-10-09 16:14:50 +05:30
ecc_tmp = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC2 ) ) ;
2010-09-13 00:35:22 +02:00
ecc [ 4 ] = ( uint8_t ) ( ecc_tmp > > 0 ) ;
ecc [ 5 ] = ( uint8_t ) ( ecc_tmp > > 8 ) ;
ecc [ 6 ] = ( uint8_t ) ( ecc_tmp > > 16 ) ;
ecc [ 7 ] = ( uint8_t ) ( ecc_tmp > > 24 ) ;
2012-10-09 16:14:50 +05:30
ecc_tmp = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC3 ) ) ;
2010-09-13 00:35:22 +02:00
ecc [ 8 ] = ( uint8_t ) ( ecc_tmp > > 0 ) ;
ecc [ 9 ] = ( uint8_t ) ( ecc_tmp > > 8 ) ;
ecc [ 10 ] = ( uint8_t ) ( ecc_tmp > > 16 ) ;
ecc [ 11 ] = ( uint8_t ) ( ecc_tmp > > 24 ) ;
2012-10-09 16:14:50 +05:30
ecc_tmp = readl_relaxed ( FSMC_NAND_REG ( regs , bank , STS ) ) ;
2010-09-13 00:35:22 +02:00
ecc [ 12 ] = ( uint8_t ) ( ecc_tmp > > 16 ) ;
return 0 ;
}
/*
* fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by
2011-03-30 22:57:33 -03:00
* FSMC . ECC is 3 bytes for 512 bytes of data ( supports error correction up to
2010-09-13 00:35:22 +02:00
* max of 1 - bit )
*/
static int fsmc_read_hwecc_ecc1 ( struct mtd_info * mtd , const uint8_t * data ,
uint8_t * ecc )
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:19 +05:30
void __iomem * regs = host - > regs_va ;
2010-09-13 00:35:22 +02:00
uint32_t bank = host - > bank ;
uint32_t ecc_tmp ;
2012-10-09 16:14:50 +05:30
ecc_tmp = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC1 ) ) ;
2010-09-13 00:35:22 +02:00
ecc [ 0 ] = ( uint8_t ) ( ecc_tmp > > 0 ) ;
ecc [ 1 ] = ( uint8_t ) ( ecc_tmp > > 8 ) ;
ecc [ 2 ] = ( uint8_t ) ( ecc_tmp > > 16 ) ;
return 0 ;
}
2012-03-07 17:00:49 +05:30
/* Count the number of 0's in buff upto a max of max_bits */
static int count_written_bits ( uint8_t * buff , int size , int max_bits )
{
int k , written_bits = 0 ;
for ( k = 0 ; k < size ; k + + ) {
written_bits + = hweight8 ( ~ buff [ k ] ) ;
if ( written_bits > max_bits )
break ;
}
return written_bits ;
}
2012-03-14 11:47:18 +05:30
static void dma_complete ( void * param )
{
struct fsmc_nand_data * host = param ;
complete ( & host - > dma_access_complete ) ;
}
static int dma_xfer ( struct fsmc_nand_data * host , void * buffer , int len ,
enum dma_data_direction direction )
{
struct dma_chan * chan ;
struct dma_device * dma_dev ;
struct dma_async_tx_descriptor * tx ;
dma_addr_t dma_dst , dma_src , dma_addr ;
dma_cookie_t cookie ;
unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT ;
int ret ;
2015-03-13 07:54:46 -04:00
unsigned long time_left ;
2012-03-14 11:47:18 +05:30
if ( direction = = DMA_TO_DEVICE )
chan = host - > write_dma_chan ;
else if ( direction = = DMA_FROM_DEVICE )
chan = host - > read_dma_chan ;
else
return - EINVAL ;
dma_dev = chan - > device ;
dma_addr = dma_map_single ( dma_dev - > dev , buffer , len , direction ) ;
if ( direction = = DMA_TO_DEVICE ) {
dma_src = dma_addr ;
dma_dst = host - > data_pa ;
} else {
dma_src = host - > data_pa ;
dma_dst = dma_addr ;
}
tx = dma_dev - > device_prep_dma_memcpy ( chan , dma_dst , dma_src ,
len , flags ) ;
if ( ! tx ) {
dev_err ( host - > dev , " device_prep_dma_memcpy error \n " ) ;
2012-11-05 10:00:14 +00:00
ret = - EIO ;
goto unmap_dma ;
2012-03-14 11:47:18 +05:30
}
tx - > callback = dma_complete ;
tx - > callback_param = host ;
cookie = tx - > tx_submit ( tx ) ;
ret = dma_submit_error ( cookie ) ;
if ( ret ) {
dev_err ( host - > dev , " dma_submit_error %d \n " , cookie ) ;
2012-11-05 10:00:14 +00:00
goto unmap_dma ;
2012-03-14 11:47:18 +05:30
}
dma_async_issue_pending ( chan ) ;
2015-03-13 07:54:46 -04:00
time_left =
2012-10-09 16:14:48 +05:30
wait_for_completion_timeout ( & host - > dma_access_complete ,
2012-03-14 11:47:18 +05:30
msecs_to_jiffies ( 3000 ) ) ;
2015-03-13 07:54:46 -04:00
if ( time_left = = 0 ) {
2014-10-11 21:10:32 +05:30
dmaengine_terminate_all ( chan ) ;
2012-03-14 11:47:18 +05:30
dev_err ( host - > dev , " wait_for_completion_timeout \n " ) ;
2015-03-13 07:54:45 -04:00
ret = - ETIMEDOUT ;
2012-11-05 10:00:14 +00:00
goto unmap_dma ;
2012-03-14 11:47:18 +05:30
}
2012-11-05 10:00:14 +00:00
ret = 0 ;
unmap_dma :
dma_unmap_single ( dma_dev - > dev , dma_addr , len , direction ) ;
return ret ;
2012-03-14 11:47:18 +05:30
}
2012-03-14 11:47:17 +05:30
/*
* fsmc_write_buf - write buffer to chip
* @ mtd : MTD device structure
* @ buf : data buffer
* @ len : number of bytes to write
*/
static void fsmc_write_buf ( struct mtd_info * mtd , const uint8_t * buf , int len )
{
int i ;
2015-12-01 12:03:04 +01:00
struct nand_chip * chip = mtd_to_nand ( mtd ) ;
2012-03-14 11:47:17 +05:30
if ( IS_ALIGNED ( ( uint32_t ) buf , sizeof ( uint32_t ) ) & &
IS_ALIGNED ( len , sizeof ( uint32_t ) ) ) {
uint32_t * p = ( uint32_t * ) buf ;
len = len > > 2 ;
for ( i = 0 ; i < len ; i + + )
2012-10-09 16:14:50 +05:30
writel_relaxed ( p [ i ] , chip - > IO_ADDR_W ) ;
2012-03-14 11:47:17 +05:30
} else {
for ( i = 0 ; i < len ; i + + )
2012-10-09 16:14:50 +05:30
writeb_relaxed ( buf [ i ] , chip - > IO_ADDR_W ) ;
2012-03-14 11:47:17 +05:30
}
}
/*
* fsmc_read_buf - read chip data into buffer
* @ mtd : MTD device structure
* @ buf : buffer to store date
* @ len : number of bytes to read
*/
static void fsmc_read_buf ( struct mtd_info * mtd , uint8_t * buf , int len )
{
int i ;
2015-12-01 12:03:04 +01:00
struct nand_chip * chip = mtd_to_nand ( mtd ) ;
2012-03-14 11:47:17 +05:30
if ( IS_ALIGNED ( ( uint32_t ) buf , sizeof ( uint32_t ) ) & &
IS_ALIGNED ( len , sizeof ( uint32_t ) ) ) {
uint32_t * p = ( uint32_t * ) buf ;
len = len > > 2 ;
for ( i = 0 ; i < len ; i + + )
2012-10-09 16:14:50 +05:30
p [ i ] = readl_relaxed ( chip - > IO_ADDR_R ) ;
2012-03-14 11:47:17 +05:30
} else {
for ( i = 0 ; i < len ; i + + )
2012-10-09 16:14:50 +05:30
buf [ i ] = readb_relaxed ( chip - > IO_ADDR_R ) ;
2012-03-14 11:47:17 +05:30
}
}
2012-03-14 11:47:18 +05:30
/*
* fsmc_read_buf_dma - read chip data into buffer
* @ mtd : MTD device structure
* @ buf : buffer to store date
* @ len : number of bytes to read
*/
static void fsmc_read_buf_dma ( struct mtd_info * mtd , uint8_t * buf , int len )
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:18 +05:30
dma_xfer ( host , buf , len , DMA_FROM_DEVICE ) ;
}
/*
* fsmc_write_buf_dma - write buffer to chip
* @ mtd : MTD device structure
* @ buf : data buffer
* @ len : number of bytes to write
*/
static void fsmc_write_buf_dma ( struct mtd_info * mtd , const uint8_t * buf ,
int len )
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:18 +05:30
dma_xfer ( host , ( void * ) buf , len , DMA_TO_DEVICE ) ;
}
2010-09-13 00:35:22 +02:00
/*
* fsmc_read_page_hwecc
* @ mtd : mtd info structure
* @ chip : nand chip info structure
* @ buf : buffer to store read data
2012-05-02 10:14:55 -07:00
* @ oob_required : caller expects OOB data read to chip - > oob_poi
2010-09-13 00:35:22 +02:00
* @ page : page number to read
*
2011-03-30 22:57:33 -03:00
* This routine is needed for fsmc version 8 as reading from NAND chip has to be
2010-09-13 00:35:22 +02:00
* performed in a strict sequence as follows :
* data ( 512 byte ) - > ecc ( 13 byte )
2011-03-30 22:57:33 -03:00
* After this read , fsmc hardware generates and reports error data bits ( up to a
2010-09-13 00:35:22 +02:00
* max of 8 bits )
*/
static int fsmc_read_page_hwecc ( struct mtd_info * mtd , struct nand_chip * chip ,
2012-05-02 10:14:55 -07:00
uint8_t * buf , int oob_required , int page )
2010-09-13 00:35:22 +02:00
{
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2010-09-13 00:35:22 +02:00
struct fsmc_eccplace * ecc_place = host - > ecc_place ;
int i , j , s , stat , eccsize = chip - > ecc . size ;
int eccbytes = chip - > ecc . bytes ;
int eccsteps = chip - > ecc . steps ;
uint8_t * p = buf ;
uint8_t * ecc_calc = chip - > buffers - > ecccalc ;
uint8_t * ecc_code = chip - > buffers - > ecccode ;
int off , len , group = 0 ;
/*
* ecc_oob is intentionally taken as uint16_t . In 16 bit devices , we
* end up reading 14 bytes ( 7 words ) from oob . The local array is
* to maintain word alignment
*/
uint16_t ecc_oob [ 7 ] ;
uint8_t * oob = ( uint8_t * ) & ecc_oob [ 0 ] ;
2012-04-25 12:06:09 -07:00
unsigned int max_bitflips = 0 ;
2010-09-13 00:35:22 +02:00
for ( i = 0 , s = 0 ; s < eccsteps ; s + + , i + = eccbytes , p + = eccsize ) {
chip - > cmdfunc ( mtd , NAND_CMD_READ0 , s * eccsize , page ) ;
chip - > ecc . hwctl ( mtd , NAND_ECC_READ ) ;
chip - > read_buf ( mtd , p , eccsize ) ;
for ( j = 0 ; j < eccbytes ; ) {
off = ecc_place - > eccplace [ group ] . offset ;
len = ecc_place - > eccplace [ group ] . length ;
group + + ;
/*
2012-03-14 11:47:09 +05:30
* length is intentionally kept a higher multiple of 2
* to read at least 13 bytes even in case of 16 bit NAND
* devices
*/
2012-03-14 11:47:10 +05:30
if ( chip - > options & NAND_BUSWIDTH_16 )
len = roundup ( len , 2 ) ;
2010-09-13 00:35:22 +02:00
chip - > cmdfunc ( mtd , NAND_CMD_READOOB , off , page ) ;
chip - > read_buf ( mtd , oob + j , len ) ;
j + = len ;
}
2012-03-07 17:00:49 +05:30
memcpy ( & ecc_code [ i ] , oob , chip - > ecc . bytes ) ;
2010-09-13 00:35:22 +02:00
chip - > ecc . calculate ( mtd , p , & ecc_calc [ i ] ) ;
stat = chip - > ecc . correct ( mtd , p , & ecc_code [ i ] , & ecc_calc [ i ] ) ;
2012-04-25 12:06:09 -07:00
if ( stat < 0 ) {
2010-09-13 00:35:22 +02:00
mtd - > ecc_stats . failed + + ;
2012-04-25 12:06:09 -07:00
} else {
2010-09-13 00:35:22 +02:00
mtd - > ecc_stats . corrected + = stat ;
2012-04-25 12:06:09 -07:00
max_bitflips = max_t ( unsigned int , max_bitflips , stat ) ;
}
2010-09-13 00:35:22 +02:00
}
2012-04-25 12:06:09 -07:00
return max_bitflips ;
2010-09-13 00:35:22 +02:00
}
/*
2012-03-07 17:00:54 +05:30
* fsmc_bch8_correct_data
2010-09-13 00:35:22 +02:00
* @ mtd : mtd info structure
* @ dat : buffer of read data
* @ read_ecc : ecc read from device spare area
* @ calc_ecc : ecc calculated from read data
*
* calc_ecc is a 104 bit information containing maximum of 8 error
* offset informations of 13 bits each in 512 bytes of read data .
*/
2012-03-07 17:00:54 +05:30
static int fsmc_bch8_correct_data ( struct mtd_info * mtd , uint8_t * dat ,
2010-09-13 00:35:22 +02:00
uint8_t * read_ecc , uint8_t * calc_ecc )
{
2015-12-01 12:03:04 +01:00
struct nand_chip * chip = mtd_to_nand ( mtd ) ;
2015-12-10 08:59:46 +01:00
struct fsmc_nand_data * host = mtd_to_fsmc ( mtd ) ;
2012-03-14 11:47:19 +05:30
void __iomem * regs = host - > regs_va ;
2010-09-13 00:35:22 +02:00
unsigned int bank = host - > bank ;
2012-03-07 17:00:53 +05:30
uint32_t err_idx [ 8 ] ;
2010-09-13 00:35:22 +02:00
uint32_t num_err , i ;
2012-03-07 17:00:54 +05:30
uint32_t ecc1 , ecc2 , ecc3 , ecc4 ;
2010-09-13 00:35:22 +02:00
2012-10-09 16:14:50 +05:30
num_err = ( readl_relaxed ( FSMC_NAND_REG ( regs , bank , STS ) ) > > 10 ) & 0xF ;
2012-03-07 17:00:49 +05:30
/* no bit flipping */
if ( likely ( num_err = = 0 ) )
return 0 ;
/* too many errors */
if ( unlikely ( num_err > 8 ) ) {
/*
* This is a temporary erase check . A newly erased page read
* would result in an ecc error because the oob data is also
* erased to FF and the calculated ecc for an FF data is not
* FF . . FF .
* This is a workaround to skip performing correction in case
* data is FF . . FF
*
* Logic :
* For every page , each bit written as 0 is counted until these
* number of bits are greater than 8 ( the maximum correction
* capability of FSMC for each 512 + 13 bytes )
*/
int bits_ecc = count_written_bits ( read_ecc , chip - > ecc . bytes , 8 ) ;
int bits_data = count_written_bits ( dat , chip - > ecc . size , 8 ) ;
if ( ( bits_ecc + bits_data ) < = 8 ) {
if ( bits_data )
memset ( dat , 0xff , chip - > ecc . size ) ;
return bits_data ;
}
return - EBADMSG ;
}
2010-09-13 00:35:22 +02:00
/*
* - - - - - - - - - - - - - - - - - - - calc_ecc [ ] bit wise - - - - - - - - - - - | - - 13 bits - - |
* | - - - idx [ 7 ] - - | - - . . . . . - - - - - | - - - idx [ 2 ] - - | | - - - idx [ 1 ] - - | | - - - idx [ 0 ] - - |
*
* calc_ecc is a 104 bit information containing maximum of 8 error
* offset informations of 13 bits each . calc_ecc is copied into a
* uint64_t array and error offset indexes are populated in err_idx
* array
*/
2012-10-09 16:14:50 +05:30
ecc1 = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC1 ) ) ;
ecc2 = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC2 ) ) ;
ecc3 = readl_relaxed ( FSMC_NAND_REG ( regs , bank , ECC3 ) ) ;
ecc4 = readl_relaxed ( FSMC_NAND_REG ( regs , bank , STS ) ) ;
2012-03-07 17:00:54 +05:30
err_idx [ 0 ] = ( ecc1 > > 0 ) & 0x1FFF ;
err_idx [ 1 ] = ( ecc1 > > 13 ) & 0x1FFF ;
err_idx [ 2 ] = ( ( ( ecc2 > > 0 ) & 0x7F ) < < 6 ) | ( ( ecc1 > > 26 ) & 0x3F ) ;
err_idx [ 3 ] = ( ecc2 > > 7 ) & 0x1FFF ;
err_idx [ 4 ] = ( ( ( ecc3 > > 0 ) & 0x1 ) < < 12 ) | ( ( ecc2 > > 20 ) & 0xFFF ) ;
err_idx [ 5 ] = ( ecc3 > > 1 ) & 0x1FFF ;
err_idx [ 6 ] = ( ecc3 > > 14 ) & 0x1FFF ;
err_idx [ 7 ] = ( ( ( ecc4 > > 16 ) & 0xFF ) < < 5 ) | ( ( ecc3 > > 27 ) & 0x1F ) ;
2010-09-13 00:35:22 +02:00
i = 0 ;
while ( num_err - - ) {
change_bit ( 0 , ( unsigned long * ) & err_idx [ i ] ) ;
change_bit ( 1 , ( unsigned long * ) & err_idx [ i ] ) ;
2012-03-14 11:47:11 +05:30
if ( err_idx [ i ] < chip - > ecc . size * 8 ) {
2010-09-13 00:35:22 +02:00
change_bit ( err_idx [ i ] , ( unsigned long * ) dat ) ;
i + + ;
}
}
return i ;
}
2012-03-14 11:47:18 +05:30
static bool filter ( struct dma_chan * chan , void * slave )
{
chan - > private = slave ;
return true ;
}
2012-03-16 10:19:31 +01:00
# ifdef CONFIG_OF
2012-11-19 13:23:07 -05:00
static int fsmc_nand_probe_config_dt ( struct platform_device * pdev ,
2012-12-21 13:19:05 -08:00
struct device_node * np )
2012-03-16 10:19:31 +01:00
{
struct fsmc_nand_platform_data * pdata = dev_get_platdata ( & pdev - > dev ) ;
u32 val ;
2015-03-19 14:34:29 +01:00
int ret ;
2012-03-16 10:19:31 +01:00
/* Set default NAND width to 8 bits */
pdata - > width = 8 ;
if ( ! of_property_read_u32 ( np , " bank-width " , & val ) ) {
if ( val = = 2 ) {
pdata - > width = 16 ;
} else if ( val ! = 1 ) {
dev_err ( & pdev - > dev , " invalid bank-width %u \n " , val ) ;
return - EINVAL ;
}
}
if ( of_get_property ( np , " nand-skip-bbtscan " , NULL ) )
pdata - > options = NAND_SKIP_BBTSCAN ;
2013-04-29 14:07:48 +02:00
pdata - > nand_timings = devm_kzalloc ( & pdev - > dev ,
sizeof ( * pdata - > nand_timings ) , GFP_KERNEL ) ;
2013-12-26 12:16:38 +09:00
if ( ! pdata - > nand_timings )
2013-04-29 14:07:48 +02:00
return - ENOMEM ;
2015-03-19 14:34:29 +01:00
ret = of_property_read_u8_array ( np , " timings " , ( u8 * ) pdata - > nand_timings ,
2013-04-29 14:07:48 +02:00
sizeof ( * pdata - > nand_timings ) ) ;
2015-03-19 14:34:29 +01:00
if ( ret ) {
dev_info ( & pdev - > dev , " No timings in dts specified, using default timings! \n " ) ;
pdata - > nand_timings = NULL ;
}
2013-04-29 14:07:48 +02:00
/* Set default NAND bank to 0 */
pdata - > bank = 0 ;
if ( ! of_property_read_u32 ( np , " bank " , & val ) ) {
if ( val > 3 ) {
dev_err ( & pdev - > dev , " invalid bank %u \n " , val ) ;
return - EINVAL ;
}
pdata - > bank = val ;
}
2012-03-16 10:19:31 +01:00
return 0 ;
}
# else
2012-11-19 13:23:07 -05:00
static int fsmc_nand_probe_config_dt ( struct platform_device * pdev ,
2012-12-21 13:19:05 -08:00
struct device_node * np )
2012-03-16 10:19:31 +01:00
{
return - ENOSYS ;
}
# endif
2010-09-13 00:35:22 +02:00
/*
* fsmc_nand_probe - Probe function
* @ pdev : platform device structure
*/
static int __init fsmc_nand_probe ( struct platform_device * pdev )
{
struct fsmc_nand_platform_data * pdata = dev_get_platdata ( & pdev - > dev ) ;
2012-03-16 10:19:31 +01:00
struct device_node __maybe_unused * np = pdev - > dev . of_node ;
2010-09-13 00:35:22 +02:00
struct fsmc_nand_data * host ;
struct mtd_info * mtd ;
struct nand_chip * nand ;
struct resource * res ;
2012-03-14 11:47:18 +05:30
dma_cap_mask_t mask ;
2010-11-29 13:52:06 +01:00
int ret = 0 ;
2010-11-29 13:52:19 +01:00
u32 pid ;
int i ;
2010-09-13 00:35:22 +02:00
2012-03-16 10:19:31 +01:00
if ( np ) {
pdata = devm_kzalloc ( & pdev - > dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
pdev - > dev . platform_data = pdata ;
ret = fsmc_nand_probe_config_dt ( pdev , np ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " no platform data \n " ) ;
return - ENODEV ;
}
}
2010-09-13 00:35:22 +02:00
if ( ! pdata ) {
dev_err ( & pdev - > dev , " platform data is NULL \n " ) ;
return - EINVAL ;
}
/* Allocate memory for the device structure (and zero it) */
2012-03-14 11:47:15 +05:30
host = devm_kzalloc ( & pdev - > dev , sizeof ( * host ) , GFP_KERNEL ) ;
2013-12-26 12:16:38 +09:00
if ( ! host )
2010-09-13 00:35:22 +02:00
return - ENOMEM ;
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM , " nand_data " ) ;
2013-01-21 11:09:12 +01:00
host - > data_va = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( host - > data_va ) )
return PTR_ERR ( host - > data_va ) ;
2015-10-02 12:40:20 +02:00
2012-10-04 15:14:16 +02:00
host - > data_pa = ( dma_addr_t ) res - > start ;
2010-09-13 00:35:22 +02:00
2012-10-04 15:14:16 +02:00
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM , " nand_addr " ) ;
2013-01-21 11:09:12 +01:00
host - > addr_va = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( host - > addr_va ) )
return PTR_ERR ( host - > addr_va ) ;
2010-09-13 00:35:22 +02:00
2012-10-04 15:14:16 +02:00
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM , " nand_cmd " ) ;
2013-01-21 11:09:12 +01:00
host - > cmd_va = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( host - > cmd_va ) )
return PTR_ERR ( host - > cmd_va ) ;
2010-09-13 00:35:22 +02:00
res = platform_get_resource_byname ( pdev , IORESOURCE_MEM , " fsmc_regs " ) ;
2013-01-21 11:09:12 +01:00
host - > regs_va = devm_ioremap_resource ( & pdev - > dev , res ) ;
if ( IS_ERR ( host - > regs_va ) )
return PTR_ERR ( host - > regs_va ) ;
2010-09-13 00:35:22 +02:00
host - > clk = clk_get ( & pdev - > dev , NULL ) ;
if ( IS_ERR ( host - > clk ) ) {
dev_err ( & pdev - > dev , " failed to fetch block clock \n " ) ;
2012-03-14 11:47:15 +05:30
return PTR_ERR ( host - > clk ) ;
2010-09-13 00:35:22 +02:00
}
2012-04-17 17:07:57 +05:30
ret = clk_prepare_enable ( host - > clk ) ;
2010-09-13 00:35:22 +02:00
if ( ret )
2012-04-17 17:07:57 +05:30
goto err_clk_prepare_enable ;
2010-09-13 00:35:22 +02:00
2010-11-29 13:52:19 +01:00
/*
* This device ID is actually a common AMBA ID as used on the
* AMBA PrimeCell bus . However it is not a PrimeCell .
*/
for ( pid = 0 , i = 0 ; i < 4 ; i + + )
pid | = ( readl ( host - > regs_va + resource_size ( res ) - 0x20 + 4 * i ) & 255 ) < < ( i * 8 ) ;
host - > pid = pid ;
dev_info ( & pdev - > dev , " FSMC device partno %03x, manufacturer %02x, "
" revision %02x, config %02x \n " ,
AMBA_PART_BITS ( pid ) , AMBA_MANF_BITS ( pid ) ,
AMBA_REV_BITS ( pid ) , AMBA_CONFIG_BITS ( pid ) ) ;
2010-09-13 00:35:22 +02:00
host - > bank = pdata - > bank ;
host - > select_chip = pdata - > select_bank ;
2012-03-14 11:47:07 +05:30
host - > partitions = pdata - > partitions ;
host - > nr_partitions = pdata - > nr_partitions ;
2012-03-14 11:47:16 +05:30
host - > dev = & pdev - > dev ;
2012-03-14 11:47:14 +05:30
host - > dev_timings = pdata - > nand_timings ;
2012-03-14 11:47:18 +05:30
host - > mode = pdata - > mode ;
if ( host - > mode = = USE_DMA_ACCESS )
init_completion ( & host - > dma_access_complete ) ;
2010-09-13 00:35:22 +02:00
/* Link all private pointers */
2015-12-10 09:00:05 +01:00
mtd = nand_to_mtd ( & host - > nand ) ;
2010-09-13 00:35:22 +02:00
nand = & host - > nand ;
nand - > priv = host ;
2015-10-30 20:33:25 -07:00
nand_set_flash_node ( nand , np ) ;
2010-09-13 00:35:22 +02:00
2015-12-10 09:00:05 +01:00
mtd - > dev . parent = & pdev - > dev ;
2010-09-13 00:35:22 +02:00
nand - > IO_ADDR_R = host - > data_va ;
nand - > IO_ADDR_W = host - > data_va ;
nand - > cmd_ctrl = fsmc_cmd_ctrl ;
nand - > chip_delay = 30 ;
2015-10-19 08:40:13 +02:00
/*
* Setup default ECC mode . nand_dt_init ( ) called from nand_scan_ident ( )
* can overwrite this value if the DT provides a different value .
*/
2010-09-13 00:35:22 +02:00
nand - > ecc . mode = NAND_ECC_HW ;
nand - > ecc . hwctl = fsmc_enable_hwecc ;
nand - > ecc . size = 512 ;
nand - > options = pdata - > options ;
nand - > select_chip = fsmc_select_chip ;
2012-03-14 11:47:12 +05:30
nand - > badblockbits = 7 ;
2015-10-30 20:33:23 -07:00
nand_set_flash_node ( nand , np ) ;
2010-09-13 00:35:22 +02:00
if ( pdata - > width = = FSMC_NAND_BW16 )
nand - > options | = NAND_BUSWIDTH_16 ;
2012-03-14 11:47:18 +05:30
switch ( host - > mode ) {
case USE_DMA_ACCESS :
dma_cap_zero ( mask ) ;
dma_cap_set ( DMA_MEMCPY , mask ) ;
host - > read_dma_chan = dma_request_channel ( mask , filter ,
pdata - > read_dma_priv ) ;
if ( ! host - > read_dma_chan ) {
dev_err ( & pdev - > dev , " Unable to get read dma channel \n " ) ;
goto err_req_read_chnl ;
}
host - > write_dma_chan = dma_request_channel ( mask , filter ,
pdata - > write_dma_priv ) ;
if ( ! host - > write_dma_chan ) {
dev_err ( & pdev - > dev , " Unable to get write dma channel \n " ) ;
goto err_req_write_chnl ;
}
nand - > read_buf = fsmc_read_buf_dma ;
nand - > write_buf = fsmc_write_buf_dma ;
break ;
default :
case USE_WORD_ACCESS :
2012-03-14 11:47:17 +05:30
nand - > read_buf = fsmc_read_buf ;
nand - > write_buf = fsmc_write_buf ;
2012-03-14 11:47:18 +05:30
break ;
2012-03-14 11:47:17 +05:30
}
2012-03-14 11:47:19 +05:30
fsmc_nand_setup ( host - > regs_va , host - > bank ,
nand - > options & NAND_BUSWIDTH_16 ,
2012-03-14 11:47:14 +05:30
host - > dev_timings ) ;
2010-09-13 00:35:22 +02:00
2010-11-29 13:52:19 +01:00
if ( AMBA_REV_BITS ( host - > pid ) > = 8 ) {
2010-09-13 00:35:22 +02:00
nand - > ecc . read_page = fsmc_read_page_hwecc ;
nand - > ecc . calculate = fsmc_read_hwecc_ecc4 ;
2012-03-07 17:00:54 +05:30
nand - > ecc . correct = fsmc_bch8_correct_data ;
2010-09-13 00:35:22 +02:00
nand - > ecc . bytes = 13 ;
2012-03-11 14:21:11 -07:00
nand - > ecc . strength = 8 ;
2010-09-13 00:35:22 +02:00
}
/*
2011-03-30 22:57:33 -03:00
* Scan to find existence of the device
2010-09-13 00:35:22 +02:00
*/
2015-12-10 09:00:05 +01:00
if ( nand_scan_ident ( mtd , 1 , NULL ) ) {
2010-09-13 00:35:22 +02:00
ret = - ENXIO ;
dev_err ( & pdev - > dev , " No NAND Device found! \n " ) ;
2012-03-14 11:47:15 +05:30
goto err_scan_ident ;
2010-09-13 00:35:22 +02:00
}
2010-11-29 13:52:19 +01:00
if ( AMBA_REV_BITS ( host - > pid ) > = 8 ) {
2015-12-10 09:00:05 +01:00
switch ( mtd - > oobsize ) {
2012-03-07 17:00:50 +05:30
case 16 :
nand - > ecc . layout = & fsmc_ecc4_16_layout ;
2010-09-13 00:35:22 +02:00
host - > ecc_place = & fsmc_ecc4_sp_place ;
2012-03-07 17:00:50 +05:30
break ;
case 64 :
nand - > ecc . layout = & fsmc_ecc4_64_layout ;
host - > ecc_place = & fsmc_ecc4_lp_place ;
break ;
case 128 :
nand - > ecc . layout = & fsmc_ecc4_128_layout ;
host - > ecc_place = & fsmc_ecc4_lp_place ;
break ;
2012-03-07 17:00:55 +05:30
case 224 :
nand - > ecc . layout = & fsmc_ecc4_224_layout ;
host - > ecc_place = & fsmc_ecc4_lp_place ;
break ;
2012-03-07 17:00:50 +05:30
case 256 :
nand - > ecc . layout = & fsmc_ecc4_256_layout ;
2010-09-13 00:35:22 +02:00
host - > ecc_place = & fsmc_ecc4_lp_place ;
2012-03-07 17:00:50 +05:30
break ;
default :
2013-12-26 12:31:25 +09:00
dev_warn ( & pdev - > dev , " No oob scheme defined for oobsize %d \n " ,
mtd - > oobsize ) ;
2015-10-02 12:40:21 +02:00
ret = - EINVAL ;
goto err_probe ;
2010-09-13 00:35:22 +02:00
}
} else {
2015-10-19 08:40:13 +02:00
switch ( nand - > ecc . mode ) {
case NAND_ECC_HW :
dev_info ( & pdev - > dev , " Using 1-bit HW ECC scheme \n " ) ;
nand - > ecc . calculate = fsmc_read_hwecc_ecc1 ;
nand - > ecc . correct = nand_correct_data ;
nand - > ecc . bytes = 3 ;
nand - > ecc . strength = 1 ;
2012-03-07 17:00:50 +05:30
break ;
2015-10-19 08:40:13 +02:00
case NAND_ECC_SOFT_BCH :
dev_info ( & pdev - > dev , " Using 4-bit SW BCH ECC scheme \n " ) ;
2012-03-07 17:00:50 +05:30
break ;
2015-10-19 08:40:13 +02:00
2012-03-07 17:00:50 +05:30
default :
2015-10-19 08:40:13 +02:00
dev_err ( & pdev - > dev , " Unsupported ECC mode! \n " ) ;
2015-10-02 12:40:21 +02:00
goto err_probe ;
2012-03-07 17:00:50 +05:30
}
2015-10-19 08:40:13 +02:00
/*
* Don ' t set layout for BCH4 SW ECC . This will be
* generated later in nand_bch_init ( ) later .
*/
if ( nand - > ecc . mode ! = NAND_ECC_SOFT_BCH ) {
2015-12-10 09:00:05 +01:00
switch ( mtd - > oobsize ) {
2015-10-19 08:40:13 +02:00
case 16 :
nand - > ecc . layout = & fsmc_ecc1_16_layout ;
break ;
case 64 :
nand - > ecc . layout = & fsmc_ecc1_64_layout ;
break ;
case 128 :
nand - > ecc . layout = & fsmc_ecc1_128_layout ;
break ;
default :
dev_warn ( & pdev - > dev ,
" No oob scheme defined for oobsize %d \n " ,
mtd - > oobsize ) ;
ret = - EINVAL ;
goto err_probe ;
}
}
2010-09-13 00:35:22 +02:00
}
/* Second stage of scan to fill MTD data-structures */
2015-12-10 09:00:05 +01:00
if ( nand_scan_tail ( mtd ) ) {
2010-09-13 00:35:22 +02:00
ret = - ENXIO ;
goto err_probe ;
}
/*
* The partition information can is accessed by ( in the same precedence )
*
* command line through Bootloader ,
* platform data ,
* default partition information present in driver .
*/
/*
2011-05-29 20:16:57 +04:00
* Check for partition info passed
2010-09-13 00:35:22 +02:00
*/
2015-12-10 09:00:05 +01:00
mtd - > name = " nand " ;
ret = mtd_device_register ( mtd , host - > partitions , host - > nr_partitions ) ;
2011-05-23 10:23:23 +01:00
if ( ret )
2010-09-13 00:35:22 +02:00
goto err_probe ;
platform_set_drvdata ( pdev , host ) ;
dev_info ( & pdev - > dev , " FSMC NAND driver registration successful \n " ) ;
return 0 ;
err_probe :
2012-03-14 11:47:15 +05:30
err_scan_ident :
2012-03-14 11:47:18 +05:30
if ( host - > mode = = USE_DMA_ACCESS )
dma_release_channel ( host - > write_dma_chan ) ;
err_req_write_chnl :
if ( host - > mode = = USE_DMA_ACCESS )
dma_release_channel ( host - > read_dma_chan ) ;
err_req_read_chnl :
2012-04-17 17:07:57 +05:30
clk_disable_unprepare ( host - > clk ) ;
err_clk_prepare_enable :
2012-03-14 11:47:15 +05:30
clk_put ( host - > clk ) ;
2010-09-13 00:35:22 +02:00
return ret ;
}
/*
* Clean up routine
*/
static int fsmc_nand_remove ( struct platform_device * pdev )
{
struct fsmc_nand_data * host = platform_get_drvdata ( pdev ) ;
if ( host ) {
2015-12-10 09:00:05 +01:00
nand_release ( nand_to_mtd ( & host - > nand ) ) ;
2012-03-14 11:47:18 +05:30
if ( host - > mode = = USE_DMA_ACCESS ) {
dma_release_channel ( host - > write_dma_chan ) ;
dma_release_channel ( host - > read_dma_chan ) ;
}
2012-04-17 17:07:57 +05:30
clk_disable_unprepare ( host - > clk ) ;
2010-09-13 00:35:22 +02:00
clk_put ( host - > clk ) ;
}
2012-03-14 11:47:15 +05:30
2010-09-13 00:35:22 +02:00
return 0 ;
}
2013-03-26 15:53:48 +09:00
# ifdef CONFIG_PM_SLEEP
2010-09-13 00:35:22 +02:00
static int fsmc_nand_suspend ( struct device * dev )
{
struct fsmc_nand_data * host = dev_get_drvdata ( dev ) ;
if ( host )
2012-04-17 17:07:57 +05:30
clk_disable_unprepare ( host - > clk ) ;
2010-09-13 00:35:22 +02:00
return 0 ;
}
static int fsmc_nand_resume ( struct device * dev )
{
struct fsmc_nand_data * host = dev_get_drvdata ( dev ) ;
2012-03-14 11:47:13 +05:30
if ( host ) {
2012-04-17 17:07:57 +05:30
clk_prepare_enable ( host - > clk ) ;
2012-03-14 11:47:13 +05:30
fsmc_nand_setup ( host - > regs_va , host - > bank ,
2012-03-14 11:47:14 +05:30
host - > nand . options & NAND_BUSWIDTH_16 ,
host - > dev_timings ) ;
2012-03-14 11:47:13 +05:30
}
2010-09-13 00:35:22 +02:00
return 0 ;
}
2013-03-26 15:53:48 +09:00
# endif
2010-09-13 00:35:22 +02:00
2012-03-14 11:47:13 +05:30
static SIMPLE_DEV_PM_OPS ( fsmc_nand_pm_ops , fsmc_nand_suspend , fsmc_nand_resume ) ;
2010-09-13 00:35:22 +02:00
2012-03-16 10:19:31 +01:00
# ifdef CONFIG_OF
static const struct of_device_id fsmc_nand_id_table [ ] = {
{ . compatible = " st,spear600-fsmc-nand " } ,
2013-01-05 22:28:32 +01:00
{ . compatible = " stericsson,fsmc-nand " } ,
2012-03-16 10:19:31 +01:00
{ }
} ;
MODULE_DEVICE_TABLE ( of , fsmc_nand_id_table ) ;
# endif
2010-09-13 00:35:22 +02:00
static struct platform_driver fsmc_nand_driver = {
. remove = fsmc_nand_remove ,
. driver = {
. name = " fsmc-nand " ,
2012-03-16 10:19:31 +01:00
. of_match_table = of_match_ptr ( fsmc_nand_id_table ) ,
2010-09-13 00:35:22 +02:00
. pm = & fsmc_nand_pm_ops ,
} ,
} ;
2013-03-05 13:30:36 +09:00
module_platform_driver_probe ( fsmc_nand_driver , fsmc_nand_probe ) ;
2010-09-13 00:35:22 +02:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Vipin Kumar <vipin.kumar@st.com>, Ashish Priyadarshi " ) ;
MODULE_DESCRIPTION ( " NAND driver for SPEAr Platforms " ) ;