Skip to content

Commit 21ab602

Browse files
zonquegregkh
authored andcommitted
mtd: rawnand: marvell: add suspend and resume hooks
commit bd9c3f9 upstream. This patch restores the suspend and resume hooks that the old driver used to have. Apart from stopping and starting the clocks, the resume callback also nullifies the selected_chip pointer, so the next command that is issued will re-select the chip and thereby restore the timing registers. Factor out some code from marvell_nfc_init() into a new function marvell_nfc_reset() and also call it at resume time to reset some registers that don't retain their contents during low-power mode. Without this patch, a PXA3xx based system would cough up an error similar to the one below after resume. [ 44.660162] marvell-nfc 43100000.nand-controller: Timeout waiting for RB signal [ 44.671492] ubi0 error: ubi_io_write: error -110 while writing 2048 bytes to PEB 102:38912, written 0 bytes [ 44.682887] CPU: 0 PID: 1417 Comm: remote-control Not tainted 4.18.0-rc2+ #344 [ 44.691197] Hardware name: Marvell PXA3xx (Device Tree Support) [ 44.697111] Backtrace: [ 44.699593] [<c0106458>] (dump_backtrace) from [<c0106718>] (show_stack+0x18/0x1c) [ 44.708931] r7:00000800 r6:00009800 r5:00000066 r4:c6139000 [ 44.715833] [<c0106700>] (show_stack) from [<c0678a60>] (dump_stack+0x20/0x28) [ 44.724206] [<c0678a40>] (dump_stack) from [<c0456cbc>] (ubi_io_write+0x3d4/0x630) [ 44.732925] [<c04568e8>] (ubi_io_write) from [<c0454428>] (ubi_eba_write_leb+0x690/0x6fc) ... Fixes: 02f26ec ("mtd: nand: add reworked Marvell NAND controller driver") Cc: [email protected] Signed-off-by: Daniel Mack <[email protected]> Signed-off-by: Miquel Raynal <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f05cb63 commit 21ab602

File tree

1 file changed

+62
-11
lines changed

1 file changed

+62
-11
lines changed

drivers/mtd/nand/raw/marvell_nand.c

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,6 +2677,21 @@ static int marvell_nfc_init_dma(struct marvell_nfc *nfc)
26772677
return 0;
26782678
}
26792679

2680+
static void marvell_nfc_reset(struct marvell_nfc *nfc)
2681+
{
2682+
/*
2683+
* ECC operations and interruptions are only enabled when specifically
2684+
* needed. ECC shall not be activated in the early stages (fails probe).
2685+
* Arbiter flag, even if marked as "reserved", must be set (empirical).
2686+
* SPARE_EN bit must always be set or ECC bytes will not be at the same
2687+
* offset in the read page and this will fail the protection.
2688+
*/
2689+
writel_relaxed(NDCR_ALL_INT | NDCR_ND_ARB_EN | NDCR_SPARE_EN |
2690+
NDCR_RD_ID_CNT(NFCV1_READID_LEN), nfc->regs + NDCR);
2691+
writel_relaxed(0xFFFFFFFF, nfc->regs + NDSR);
2692+
writel_relaxed(0, nfc->regs + NDECCCTRL);
2693+
}
2694+
26802695
static int marvell_nfc_init(struct marvell_nfc *nfc)
26812696
{
26822697
struct device_node *np = nfc->dev->of_node;
@@ -2715,17 +2730,7 @@ static int marvell_nfc_init(struct marvell_nfc *nfc)
27152730
if (!nfc->caps->is_nfcv2)
27162731
marvell_nfc_init_dma(nfc);
27172732

2718-
/*
2719-
* ECC operations and interruptions are only enabled when specifically
2720-
* needed. ECC shall not be activated in the early stages (fails probe).
2721-
* Arbiter flag, even if marked as "reserved", must be set (empirical).
2722-
* SPARE_EN bit must always be set or ECC bytes will not be at the same
2723-
* offset in the read page and this will fail the protection.
2724-
*/
2725-
writel_relaxed(NDCR_ALL_INT | NDCR_ND_ARB_EN | NDCR_SPARE_EN |
2726-
NDCR_RD_ID_CNT(NFCV1_READID_LEN), nfc->regs + NDCR);
2727-
writel_relaxed(0xFFFFFFFF, nfc->regs + NDSR);
2728-
writel_relaxed(0, nfc->regs + NDECCCTRL);
2733+
marvell_nfc_reset(nfc);
27292734

27302735
return 0;
27312736
}
@@ -2840,6 +2845,51 @@ static int marvell_nfc_remove(struct platform_device *pdev)
28402845
return 0;
28412846
}
28422847

2848+
static int __maybe_unused marvell_nfc_suspend(struct device *dev)
2849+
{
2850+
struct marvell_nfc *nfc = dev_get_drvdata(dev);
2851+
struct marvell_nand_chip *chip;
2852+
2853+
list_for_each_entry(chip, &nfc->chips, node)
2854+
marvell_nfc_wait_ndrun(&chip->chip);
2855+
2856+
clk_disable_unprepare(nfc->reg_clk);
2857+
clk_disable_unprepare(nfc->core_clk);
2858+
2859+
return 0;
2860+
}
2861+
2862+
static int __maybe_unused marvell_nfc_resume(struct device *dev)
2863+
{
2864+
struct marvell_nfc *nfc = dev_get_drvdata(dev);
2865+
int ret;
2866+
2867+
ret = clk_prepare_enable(nfc->core_clk);
2868+
if (ret < 0)
2869+
return ret;
2870+
2871+
if (!IS_ERR(nfc->reg_clk)) {
2872+
ret = clk_prepare_enable(nfc->reg_clk);
2873+
if (ret < 0)
2874+
return ret;
2875+
}
2876+
2877+
/*
2878+
* Reset nfc->selected_chip so the next command will cause the timing
2879+
* registers to be restored in marvell_nfc_select_chip().
2880+
*/
2881+
nfc->selected_chip = NULL;
2882+
2883+
/* Reset registers that have lost their contents */
2884+
marvell_nfc_reset(nfc);
2885+
2886+
return 0;
2887+
}
2888+
2889+
static const struct dev_pm_ops marvell_nfc_pm_ops = {
2890+
SET_SYSTEM_SLEEP_PM_OPS(marvell_nfc_suspend, marvell_nfc_resume)
2891+
};
2892+
28432893
static const struct marvell_nfc_caps marvell_armada_8k_nfc_caps = {
28442894
.max_cs_nb = 4,
28452895
.max_rb_nb = 2,
@@ -2924,6 +2974,7 @@ static struct platform_driver marvell_nfc_driver = {
29242974
.driver = {
29252975
.name = "marvell-nfc",
29262976
.of_match_table = marvell_nfc_of_ids,
2977+
.pm = &marvell_nfc_pm_ops,
29272978
},
29282979
.id_table = marvell_nfc_platform_ids,
29292980
.probe = marvell_nfc_probe,

0 commit comments

Comments
 (0)