aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej S. Szmigiero <mail@maciej.szmigiero.name>2016-01-18 14:07:44 -0500
committerMark Brown <broonie@kernel.org>2016-02-21 22:02:47 -0500
commit6139b1b184d5f6257f692dc814dbcd47e4cf90f1 (patch)
tree395e6ecae72279ff8e7d3455b225ae4a56575455
parent99777b07efe3b533b4b6c67e59ad9138607c0467 (diff)
ASoC: fsl_ssi: remove explicit register defaults
There is no guarantee that on fsl_ssi module load SSI registers will have their power-on-reset values. In fact, if the driver is reloaded the values in registers will be whatever they were set to previously. However, the cache needs to be fully populated at probe time to avoid non-atomic allocations during register access. Special case here is imx21-class SSI, since according to datasheet it don't have SACC{ST,EN,DIS} regs. This fixes hard lockup on fsl_ssi module reload, at least in AC'97 mode. Fixes: 05cf237972fe ("ASoC: fsl_ssi: Add driver suspend and resume to support MEGA Fast") Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Tested-by: Fabio Estevam <fabio.estevam@nxp.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/fsl/fsl_ssi.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 40dfd8a36484..ed8de1035cda 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -112,20 +112,6 @@ struct fsl_ssi_rxtx_reg_val {
112 struct fsl_ssi_reg_val tx; 112 struct fsl_ssi_reg_val tx;
113}; 113};
114 114
115static const struct reg_default fsl_ssi_reg_defaults[] = {
116 {CCSR_SSI_SCR, 0x00000000},
117 {CCSR_SSI_SIER, 0x00003003},
118 {CCSR_SSI_STCR, 0x00000200},
119 {CCSR_SSI_SRCR, 0x00000200},
120 {CCSR_SSI_STCCR, 0x00040000},
121 {CCSR_SSI_SRCCR, 0x00040000},
122 {CCSR_SSI_SACNT, 0x00000000},
123 {CCSR_SSI_STMSK, 0x00000000},
124 {CCSR_SSI_SRMSK, 0x00000000},
125 {CCSR_SSI_SACCEN, 0x00000000},
126 {CCSR_SSI_SACCDIS, 0x00000000},
127};
128
129static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg) 115static bool fsl_ssi_readable_reg(struct device *dev, unsigned int reg)
130{ 116{
131 switch (reg) { 117 switch (reg) {
@@ -190,8 +176,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
190 .val_bits = 32, 176 .val_bits = 32,
191 .reg_stride = 4, 177 .reg_stride = 4,
192 .val_format_endian = REGMAP_ENDIAN_NATIVE, 178 .val_format_endian = REGMAP_ENDIAN_NATIVE,
193 .reg_defaults = fsl_ssi_reg_defaults, 179 .num_reg_defaults_raw = CCSR_SSI_SACCDIS / sizeof(uint32_t) + 1,
194 .num_reg_defaults = ARRAY_SIZE(fsl_ssi_reg_defaults),
195 .readable_reg = fsl_ssi_readable_reg, 180 .readable_reg = fsl_ssi_readable_reg,
196 .volatile_reg = fsl_ssi_volatile_reg, 181 .volatile_reg = fsl_ssi_volatile_reg,
197 .precious_reg = fsl_ssi_precious_reg, 182 .precious_reg = fsl_ssi_precious_reg,
@@ -201,6 +186,7 @@ static const struct regmap_config fsl_ssi_regconfig = {
201 186
202struct fsl_ssi_soc_data { 187struct fsl_ssi_soc_data {
203 bool imx; 188 bool imx;
189 bool imx21regs; /* imx21-class SSI - no SACC{ST,EN,DIS} regs */
204 bool offline_config; 190 bool offline_config;
205 u32 sisr_write_mask; 191 u32 sisr_write_mask;
206}; 192};
@@ -303,6 +289,7 @@ static struct fsl_ssi_soc_data fsl_ssi_mpc8610 = {
303 289
304static struct fsl_ssi_soc_data fsl_ssi_imx21 = { 290static struct fsl_ssi_soc_data fsl_ssi_imx21 = {
305 .imx = true, 291 .imx = true,
292 .imx21regs = true,
306 .offline_config = true, 293 .offline_config = true,
307 .sisr_write_mask = 0, 294 .sisr_write_mask = 0,
308}; 295};
@@ -586,8 +573,12 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
586 */ 573 */
587 regmap_write(regs, CCSR_SSI_SACNT, 574 regmap_write(regs, CCSR_SSI_SACNT,
588 CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV); 575 CCSR_SSI_SACNT_AC97EN | CCSR_SSI_SACNT_FV);
589 regmap_write(regs, CCSR_SSI_SACCDIS, 0xff); 576
590 regmap_write(regs, CCSR_SSI_SACCEN, 0x300); 577 /* no SACC{ST,EN,DIS} regs on imx21-class SSI */
578 if (!ssi_private->soc->imx21regs) {
579 regmap_write(regs, CCSR_SSI_SACCDIS, 0xff);
580 regmap_write(regs, CCSR_SSI_SACCEN, 0x300);
581 }
591 582
592 /* 583 /*
593 * Enable SSI, Transmit and Receive. AC97 has to communicate with the 584 * Enable SSI, Transmit and Receive. AC97 has to communicate with the
@@ -1397,6 +1388,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1397 struct resource *res; 1388 struct resource *res;
1398 void __iomem *iomem; 1389 void __iomem *iomem;
1399 char name[64]; 1390 char name[64];
1391 struct regmap_config regconfig = fsl_ssi_regconfig;
1400 1392
1401 of_id = of_match_device(fsl_ssi_ids, &pdev->dev); 1393 of_id = of_match_device(fsl_ssi_ids, &pdev->dev);
1402 if (!of_id || !of_id->data) 1394 if (!of_id || !of_id->data)
@@ -1444,15 +1436,25 @@ static int fsl_ssi_probe(struct platform_device *pdev)
1444 return PTR_ERR(iomem); 1436 return PTR_ERR(iomem);
1445 ssi_private->ssi_phys = res->start; 1437 ssi_private->ssi_phys = res->start;
1446 1438
1439 if (ssi_private->soc->imx21regs) {
1440 /*
1441 * According to datasheet imx21-class SSI
1442 * don't have SACC{ST,EN,DIS} regs.
1443 */
1444 regconfig.max_register = CCSR_SSI_SRMSK;
1445 regconfig.num_reg_defaults_raw =
1446 CCSR_SSI_SRMSK / sizeof(uint32_t) + 1;
1447 }
1448
1447 ret = of_property_match_string(np, "clock-names", "ipg"); 1449 ret = of_property_match_string(np, "clock-names", "ipg");
1448 if (ret < 0) { 1450 if (ret < 0) {
1449 ssi_private->has_ipg_clk_name = false; 1451 ssi_private->has_ipg_clk_name = false;
1450 ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem, 1452 ssi_private->regs = devm_regmap_init_mmio(&pdev->dev, iomem,
1451 &fsl_ssi_regconfig); 1453 &regconfig);
1452 } else { 1454 } else {
1453 ssi_private->has_ipg_clk_name = true; 1455 ssi_private->has_ipg_clk_name = true;
1454 ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev, 1456 ssi_private->regs = devm_regmap_init_mmio_clk(&pdev->dev,
1455 "ipg", iomem, &fsl_ssi_regconfig); 1457 "ipg", iomem, &regconfig);
1456 } 1458 }
1457 if (IS_ERR(ssi_private->regs)) { 1459 if (IS_ERR(ssi_private->regs)) {
1458 dev_err(&pdev->dev, "Failed to init register map\n"); 1460 dev_err(&pdev->dev, "Failed to init register map\n");