aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/fsl/fsl_ssi.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index a66dd375047b..331c1465a818 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -53,9 +53,9 @@ static inline void write_ssi_mask(u32 __iomem *addr, u32 clear, u32 set)
53} 53}
54#endif 54#endif
55 55
56#ifdef DEBUG
57#define NUM_OF_SSI_REG (sizeof(struct ccsr_ssi) / sizeof(__be32)) 56#define NUM_OF_SSI_REG (sizeof(struct ccsr_ssi) / sizeof(__be32))
58 57
58#ifdef DEBUG
59void dump_reg(struct ccsr_ssi __iomem *ssi) 59void dump_reg(struct ccsr_ssi __iomem *ssi)
60{ 60{
61 u32 val, i; 61 u32 val, i;
@@ -169,9 +169,25 @@ struct fsl_ssi_private {
169 unsigned int tfe0; 169 unsigned int tfe0;
170 } stats; 170 } stats;
171 171
172 u32 regcache[NUM_OF_SSI_REG];
172 char name[1]; 173 char name[1];
173}; 174};
174 175
176static bool fsl_ssi_volatile_reg(unsigned int reg)
177{
178 switch (reg) {
179 case 0x0: /* stx0 */
180 case 0x4: /* stx1 */
181 case 0x8: /* srx0 */
182 case 0xc: /* srx1 */
183 case 0x14: /* sisr */
184 case 0x50: /* saccst */
185 return true;
186 default:
187 return false;
188 }
189}
190
175/** 191/**
176 * fsl_ssi_isr: SSI interrupt handler 192 * fsl_ssi_isr: SSI interrupt handler
177 * 193 *
@@ -1163,10 +1179,51 @@ static int fsl_ssi_runtime_suspend(struct device *dev)
1163} 1179}
1164#endif 1180#endif
1165 1181
1182#ifdef CONFIG_PM_SLEEP
1183static int fsl_ssi_suspend(struct device *dev)
1184{
1185 struct fsl_ssi_private *ssi_private = dev_get_drvdata(dev);
1186 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
1187 int i;
1188
1189 clk_prepare_enable(ssi_private->coreclk);
1190
1191 for (i = 0; i < NUM_OF_SSI_REG; i++) {
1192 if (&ssi->stx0 + i == NULL || fsl_ssi_volatile_reg(i * 0x4))
1193 continue;
1194 ssi_private->regcache[i] = read_ssi(&ssi->stx0 + i);
1195 }
1196
1197 clk_disable_unprepare(ssi_private->coreclk);
1198
1199 return 0;
1200}
1201
1202static int fsl_ssi_resume(struct device *dev)
1203{
1204 struct fsl_ssi_private *ssi_private = dev_get_drvdata(dev);
1205 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
1206 int i;
1207
1208 clk_prepare_enable(ssi_private->coreclk);
1209
1210 for (i = 0; i < NUM_OF_SSI_REG; i++) {
1211 if (&ssi->stx0 + i == NULL || fsl_ssi_volatile_reg(i * 0x4))
1212 continue;
1213 write_ssi(ssi_private->regcache[i], &ssi->stx0 + i);
1214 }
1215
1216 clk_disable_unprepare(ssi_private->coreclk);
1217
1218 return 0;
1219}
1220#endif /* CONFIG_PM_SLEEP */
1221
1166static const struct dev_pm_ops fsl_ssi_pm = { 1222static const struct dev_pm_ops fsl_ssi_pm = {
1167 SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend, 1223 SET_RUNTIME_PM_OPS(fsl_ssi_runtime_suspend,
1168 fsl_ssi_runtime_resume, 1224 fsl_ssi_runtime_resume,
1169 NULL) 1225 NULL)
1226 SET_SYSTEM_SLEEP_PM_OPS(fsl_ssi_suspend, fsl_ssi_resume)
1170}; 1227};
1171 1228
1172static const struct of_device_id fsl_ssi_ids[] = { 1229static const struct of_device_id fsl_ssi_ids[] = {