6
6
* Author: Boris Brezillon <[email protected] >
7
7
*/
8
8
9
+ #include "linux/delay.h"
9
10
#include "internals.h"
10
11
11
12
#define MACRONIX_READ_RETRY_BIT BIT(0)
28
29
(MACRONIX_RANDOMIZER_RANDEN | \
29
30
MACRONIX_RANDOMIZER_RANDOPT)
30
31
32
+ #define MXIC_CMD_POWER_DOWN 0xB9
33
+
31
34
struct nand_onfi_vendor_macronix {
32
35
u8 reserved ;
33
36
u8 reliability_func ;
@@ -243,6 +246,76 @@ static void macronix_nand_block_protection_support(struct nand_chip *chip)
243
246
chip -> unlock_area = mxic_nand_unlock ;
244
247
}
245
248
249
+ static int nand_power_down_op (struct nand_chip * chip )
250
+ {
251
+ int ret ;
252
+
253
+ if (nand_has_exec_op (chip )) {
254
+ struct nand_op_instr instrs [] = {
255
+ NAND_OP_CMD (MXIC_CMD_POWER_DOWN , 0 ),
256
+ };
257
+
258
+ struct nand_operation op = NAND_OPERATION (chip -> cur_cs , instrs );
259
+
260
+ ret = nand_exec_op (chip , & op );
261
+ if (ret )
262
+ return ret ;
263
+
264
+ } else {
265
+ chip -> legacy .cmdfunc (chip , MXIC_CMD_POWER_DOWN , -1 , -1 );
266
+ }
267
+
268
+ return 0 ;
269
+ }
270
+
271
+ static int mxic_nand_suspend (struct nand_chip * chip )
272
+ {
273
+ int ret ;
274
+
275
+ nand_select_target (chip , 0 );
276
+ ret = nand_power_down_op (chip );
277
+ if (ret < 0 )
278
+ pr_err ("Suspending MXIC NAND chip failed (%d)\n" , ret );
279
+ nand_deselect_target (chip );
280
+
281
+ return ret ;
282
+ }
283
+
284
+ static void mxic_nand_resume (struct nand_chip * chip )
285
+ {
286
+ /*
287
+ * Toggle #CS pin to resume NAND device and don't care
288
+ * of the others CLE, #WE, #RE pins status.
289
+ * A NAND controller ensure it is able to assert/de-assert #CS
290
+ * by sending any byte over the NAND bus.
291
+ * i.e.,
292
+ * NAND power down command or reset command w/o R/B# status checking.
293
+ */
294
+ nand_select_target (chip , 0 );
295
+ nand_power_down_op (chip );
296
+ /* The minimum of a recovery time tRDP is 35 us */
297
+ usleep_range (35 , 100 );
298
+ nand_deselect_target (chip );
299
+ }
300
+
301
+ static void macronix_nand_deep_power_down_support (struct nand_chip * chip )
302
+ {
303
+ int i ;
304
+ static const char * const deep_power_down_dev [] = {
305
+ "MX30UF1G28AD" ,
306
+ "MX30UF2G28AD" ,
307
+ "MX30UF4G28AD" ,
308
+ };
309
+
310
+ i = match_string (deep_power_down_dev , ARRAY_SIZE (deep_power_down_dev ),
311
+ chip -> parameters .model );
312
+ if (i < 0 )
313
+ return ;
314
+
315
+ chip -> suspend = mxic_nand_suspend ;
316
+ chip -> resume = mxic_nand_resume ;
317
+ }
318
+
246
319
static int macronix_nand_init (struct nand_chip * chip )
247
320
{
248
321
if (nand_is_slc (chip ))
@@ -251,6 +324,7 @@ static int macronix_nand_init(struct nand_chip *chip)
251
324
macronix_nand_fix_broken_get_timings (chip );
252
325
macronix_nand_onfi_init (chip );
253
326
macronix_nand_block_protection_support (chip );
327
+ macronix_nand_deep_power_down_support (chip );
254
328
255
329
return 0 ;
256
330
}
0 commit comments