These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / sound / soc / intel / common / sst-dsp.c
index 64e9421..c9452e0 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 
 #include "sst-dsp.h"
 #include "sst-dsp-priv.h"
@@ -196,6 +197,22 @@ int sst_dsp_shim_update_bits64_unlocked(struct sst_dsp *sst, u32 offset,
 }
 EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64_unlocked);
 
+/* This is for registers bits with attribute RWC */
+void sst_dsp_shim_update_bits_forced_unlocked(struct sst_dsp *sst, u32 offset,
+                               u32 mask, u32 value)
+{
+       unsigned int old, new;
+       u32 ret;
+
+       ret = sst_dsp_shim_read_unlocked(sst, offset);
+
+       old = ret;
+       new = (old & (~mask)) | (value & mask);
+
+       sst_dsp_shim_write_unlocked(sst, offset, new);
+}
+EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced_unlocked);
+
 int sst_dsp_shim_update_bits(struct sst_dsp *sst, u32 offset,
                                u32 mask, u32 value)
 {
@@ -222,6 +239,60 @@ int sst_dsp_shim_update_bits64(struct sst_dsp *sst, u32 offset,
 }
 EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits64);
 
+/* This is for registers bits with attribute RWC */
+void sst_dsp_shim_update_bits_forced(struct sst_dsp *sst, u32 offset,
+                               u32 mask, u32 value)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&sst->spinlock, flags);
+       sst_dsp_shim_update_bits_forced_unlocked(sst, offset, mask, value);
+       spin_unlock_irqrestore(&sst->spinlock, flags);
+}
+EXPORT_SYMBOL_GPL(sst_dsp_shim_update_bits_forced);
+
+int sst_dsp_register_poll(struct sst_dsp *ctx, u32 offset, u32 mask,
+                        u32 target, u32 timeout, char *operation)
+{
+       int time, ret;
+       u32 reg;
+       bool done = false;
+
+       /*
+        * we will poll for couple of ms using mdelay, if not successful
+        * then go to longer sleep using usleep_range
+        */
+
+       /* check if set state successful */
+       for (time = 0; time < 5; time++) {
+               if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target) {
+                       done = true;
+                       break;
+               }
+               mdelay(1);
+       }
+
+       if (done ==  false) {
+               /* sleeping in 10ms steps so adjust timeout value */
+               timeout /= 10;
+
+               for (time = 0; time < timeout; time++) {
+                       if ((sst_dsp_shim_read_unlocked(ctx, offset) & mask) == target)
+                               break;
+
+                       usleep_range(5000, 10000);
+               }
+       }
+
+       reg = sst_dsp_shim_read_unlocked(ctx, offset);
+       dev_info(ctx->dev, "FW Poll Status: reg=%#x %s %s\n", reg, operation,
+                       (time < timeout) ? "successful" : "timedout");
+       ret = time < timeout ? 0 : -ETIME;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(sst_dsp_register_poll);
+
 void sst_dsp_dump(struct sst_dsp *sst)
 {
        if (sst->ops->dump)
@@ -349,6 +420,7 @@ void sst_dsp_inbox_read(struct sst_dsp *sst, void *message, size_t bytes)
 }
 EXPORT_SYMBOL_GPL(sst_dsp_inbox_read);
 
+#if IS_ENABLED(CONFIG_DW_DMAC_CORE)
 struct sst_dsp *sst_dsp_new(struct device *dev,
        struct sst_dsp_device *sst_dev, struct sst_pdata *pdata)
 {
@@ -413,6 +485,7 @@ void sst_dsp_free(struct sst_dsp *sst)
        sst_dma_free(sst->dma);
 }
 EXPORT_SYMBOL_GPL(sst_dsp_free);
+#endif
 
 /* Module information */
 MODULE_AUTHOR("Liam Girdwood");