Skip to content

Commit 19301d5

Browse files
Mason Yangmiquelraynal
authored andcommitted
mtd: rawnand: macronix: Add support for deep power down mode
Macronix AD series support deep power down mode for a minimum power consumption state. Overload nand_suspend() & nand_resume() in Macronix specific code to support deep power down mode. Signed-off-by: Mason Yang <[email protected]> Signed-off-by: Miquel Raynal <[email protected]>
1 parent adc6162 commit 19301d5

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

drivers/mtd/nand/raw/nand_macronix.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Author: Boris Brezillon <[email protected]>
77
*/
88

9+
#include "linux/delay.h"
910
#include "internals.h"
1011

1112
#define MACRONIX_READ_RETRY_BIT BIT(0)
@@ -28,6 +29,8 @@
2829
(MACRONIX_RANDOMIZER_RANDEN | \
2930
MACRONIX_RANDOMIZER_RANDOPT)
3031

32+
#define MXIC_CMD_POWER_DOWN 0xB9
33+
3134
struct nand_onfi_vendor_macronix {
3235
u8 reserved;
3336
u8 reliability_func;
@@ -243,6 +246,76 @@ static void macronix_nand_block_protection_support(struct nand_chip *chip)
243246
chip->unlock_area = mxic_nand_unlock;
244247
}
245248

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+
246319
static int macronix_nand_init(struct nand_chip *chip)
247320
{
248321
if (nand_is_slc(chip))
@@ -251,6 +324,7 @@ static int macronix_nand_init(struct nand_chip *chip)
251324
macronix_nand_fix_broken_get_timings(chip);
252325
macronix_nand_onfi_init(chip);
253326
macronix_nand_block_protection_support(chip);
327+
macronix_nand_deep_power_down_support(chip);
254328

255329
return 0;
256330
}

0 commit comments

Comments
 (0)