aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Petazzoni <thomas.petazzoni@free-electrons.com>2015-12-22 05:43:29 -0500
committerVinod Koul <vinod.koul@intel.com>2016-01-06 05:12:27 -0500
commit8b648436eb45c1f561164b24aafd35fb2bee9cfc (patch)
tree5006799243ec01f2b89991b6586938d94a3ff892
parent81aafb3e0e16bcca060efa6b5e477e812e4154bc (diff)
dmaengine: mv_xor: add suspend/resume support
This commit adds suspend/resume support to the mv_xor driver. The config and interrupt mask registers must be saved and restored, and upon resume, the MBus windows configuration must also be done again. Tested on Armada 388 GP, with a RAID 5 array, accessed before and after a suspend to RAM cycle. Based on work from Ofer Heifetz and Lior Amsalem. Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/dma/mv_xor.c53
-rw-r--r--drivers/dma/mv_xor.h1
2 files changed, 54 insertions, 0 deletions
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index a95878cd36d9..14091f878f80 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1085,6 +1085,57 @@ mv_xor_conf_mbus_windows(struct mv_xor_device *xordev,
1085 writel(0, base + WINDOW_OVERRIDE_CTRL(1)); 1085 writel(0, base + WINDOW_OVERRIDE_CTRL(1));
1086} 1086}
1087 1087
1088/*
1089 * Since this XOR driver is basically used only for RAID5, we don't
1090 * need to care about synchronizing ->suspend with DMA activity,
1091 * because the DMA engine will naturally be quiet due to the block
1092 * devices being suspended.
1093 */
1094static int mv_xor_suspend(struct platform_device *pdev, pm_message_t state)
1095{
1096 struct mv_xor_device *xordev = platform_get_drvdata(pdev);
1097 int i;
1098
1099 for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
1100 struct mv_xor_chan *mv_chan = xordev->channels[i];
1101
1102 if (!mv_chan)
1103 continue;
1104
1105 mv_chan->saved_config_reg =
1106 readl_relaxed(XOR_CONFIG(mv_chan));
1107 mv_chan->saved_int_mask_reg =
1108 readl_relaxed(XOR_INTR_MASK(mv_chan));
1109 }
1110
1111 return 0;
1112}
1113
1114static int mv_xor_resume(struct platform_device *dev)
1115{
1116 struct mv_xor_device *xordev = platform_get_drvdata(dev);
1117 const struct mbus_dram_target_info *dram;
1118 int i;
1119
1120 for (i = 0; i < MV_XOR_MAX_CHANNELS; i++) {
1121 struct mv_xor_chan *mv_chan = xordev->channels[i];
1122
1123 if (!mv_chan)
1124 continue;
1125
1126 writel_relaxed(mv_chan->saved_config_reg,
1127 XOR_CONFIG(mv_chan));
1128 writel_relaxed(mv_chan->saved_int_mask_reg,
1129 XOR_INTR_MASK(mv_chan));
1130 }
1131
1132 dram = mv_mbus_dram_info();
1133 if (dram)
1134 mv_xor_conf_mbus_windows(xordev, dram);
1135
1136 return 0;
1137}
1138
1088static const struct of_device_id mv_xor_dt_ids[] = { 1139static const struct of_device_id mv_xor_dt_ids[] = {
1089 { .compatible = "marvell,orion-xor", .data = (void *)XOR_MODE_IN_REG }, 1140 { .compatible = "marvell,orion-xor", .data = (void *)XOR_MODE_IN_REG },
1090 { .compatible = "marvell,armada-380-xor", .data = (void *)XOR_MODE_IN_DESC }, 1141 { .compatible = "marvell,armada-380-xor", .data = (void *)XOR_MODE_IN_DESC },
@@ -1246,6 +1297,8 @@ err_channel_add:
1246 1297
1247static struct platform_driver mv_xor_driver = { 1298static struct platform_driver mv_xor_driver = {
1248 .probe = mv_xor_probe, 1299 .probe = mv_xor_probe,
1300 .suspend = mv_xor_suspend,
1301 .resume = mv_xor_resume,
1249 .driver = { 1302 .driver = {
1250 .name = MV_XOR_NAME, 1303 .name = MV_XOR_NAME,
1251 .of_match_table = of_match_ptr(mv_xor_dt_ids), 1304 .of_match_table = of_match_ptr(mv_xor_dt_ids),
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
index 34389146bf13..c19fe30e5ae9 100644
--- a/drivers/dma/mv_xor.h
+++ b/drivers/dma/mv_xor.h
@@ -125,6 +125,7 @@ struct mv_xor_chan {
125 char dummy_src[MV_XOR_MIN_BYTE_COUNT]; 125 char dummy_src[MV_XOR_MIN_BYTE_COUNT];
126 char dummy_dst[MV_XOR_MIN_BYTE_COUNT]; 126 char dummy_dst[MV_XOR_MIN_BYTE_COUNT];
127 dma_addr_t dummy_src_addr, dummy_dst_addr; 127 dma_addr_t dummy_src_addr, dummy_dst_addr;
128 u32 saved_config_reg, saved_int_mask_reg;
128}; 129};
129 130
130/** 131/**