To enable the writing of panic and oops logs, a Cavium specific MMC
polling method is defined and thereby ensure the functioning of mmcpstore.

Signed-off-by: Bhaskara Budiredla <bbudire...@marvell.com>
---
 drivers/mmc/host/cavium-thunderx.c | 10 +++++
 drivers/mmc/host/cavium.c          | 67 ++++++++++++++++++++++++++++++
 drivers/mmc/host/cavium.h          |  3 ++
 3 files changed, 80 insertions(+)

diff --git a/drivers/mmc/host/cavium-thunderx.c 
b/drivers/mmc/host/cavium-thunderx.c
index 76013bbbcff3..efd3422939af 100644
--- a/drivers/mmc/host/cavium-thunderx.c
+++ b/drivers/mmc/host/cavium-thunderx.c
@@ -19,12 +19,22 @@
 
 static void thunder_mmc_acquire_bus(struct cvm_mmc_host *host)
 {
+#ifdef CONFIG_MMC_PSTORE
+       if (!host->pstore)
+               down(&host->mmc_serializer);
+#else
        down(&host->mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_release_bus(struct cvm_mmc_host *host)
 {
+#ifdef CONFIG_MMC_PSTORE
+       if (!host->pstore)
+               up(&host->mmc_serializer);
+#else
        up(&host->mmc_serializer);
+#endif
 }
 
 static void thunder_mmc_int_enable(struct cvm_mmc_host *host, u64 val)
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c
index c5da3aaee334..8f62f6612ac0 100644
--- a/drivers/mmc/host/cavium.c
+++ b/drivers/mmc/host/cavium.c
@@ -510,6 +510,66 @@ irqreturn_t cvm_mmc_interrupt(int irq, void *dev_id)
        return IRQ_RETVAL(emm_int != 0);
 }
 
+#ifdef CONFIG_MMC_PSTORE
+static int cvm_req_completion_poll(struct mmc_host *host, unsigned long msecs)
+{
+       struct cvm_mmc_slot *slot = mmc_priv(host);
+       struct cvm_mmc_host *cvm_host = slot->host;
+       u64 emm_int;
+
+       while (msecs) {
+               emm_int = readq(cvm_host->base + MIO_EMM_INT(cvm_host));
+
+               if (emm_int & MIO_EMM_INT_DMA_DONE)
+                       return 0;
+               else if (emm_int & MIO_EMM_INT_DMA_ERR)
+                       return -EIO;
+               mdelay(1);
+               msecs--;
+       }
+
+       return -ETIMEDOUT;
+}
+
+static void cvm_req_cleanup_pending(struct mmc_host *host)
+{
+       struct cvm_mmc_slot *slot = mmc_priv(host);
+       struct cvm_mmc_host *cvm_host = slot->host;
+       u64 fifo_cfg;
+       u64 dma_cfg;
+       u64 emm_int;
+
+       cvm_host->pstore = 1;
+
+       /* Clear pending DMA FIFO queue */
+       fifo_cfg = readq(cvm_host->dma_base + MIO_EMM_DMA_FIFO_CFG(cvm_host));
+       if (FIELD_GET(MIO_EMM_DMA_FIFO_CFG_COUNT, fifo_cfg))
+               writeq(MIO_EMM_DMA_FIFO_CFG_CLR,
+                       cvm_host->dma_base + MIO_EMM_DMA_FIFO_CFG(cvm_host));
+
+       /* Clear ongoing DMA, if there is any */
+       dma_cfg = readq(cvm_host->dma_base + MIO_EMM_DMA_CFG(cvm_host));
+       if (dma_cfg & MIO_EMM_DMA_CFG_EN) {
+               dma_cfg |= MIO_EMM_DMA_CFG_CLR;
+               writeq(dma_cfg, cvm_host->dma_base +
+                               MIO_EMM_DMA_CFG(cvm_host));
+               do {
+                       dma_cfg = readq(cvm_host->dma_base +
+                                       MIO_EMM_DMA_CFG(cvm_host));
+               } while (dma_cfg & MIO_EMM_DMA_CFG_EN);
+       }
+
+       /* Clear pending DMA interrupts */
+       emm_int = readq(cvm_host->base + MIO_EMM_INT(cvm_host));
+       if (emm_int)
+               writeq(emm_int, cvm_host->base + MIO_EMM_INT(cvm_host));
+
+       /* Clear prepared and yet to be fired DMA requests */
+       cvm_host->current_req = NULL;
+       cvm_host->dma_active = false;
+}
+#endif
+
 /*
  * Program DMA_CFG and if needed DMA_ADR.
  * Returns 0 on error, DMA address otherwise.
@@ -901,6 +961,10 @@ static const struct mmc_host_ops cvm_mmc_ops = {
        .set_ios        = cvm_mmc_set_ios,
        .get_ro         = mmc_gpio_get_ro,
        .get_cd         = mmc_gpio_get_cd,
+#ifdef CONFIG_MMC_PSTORE
+       .req_cleanup_pending = cvm_req_cleanup_pending,
+       .req_completion_poll = cvm_req_completion_poll,
+#endif
 };
 
 static void cvm_mmc_set_clock(struct cvm_mmc_slot *slot, unsigned int clock)
@@ -1058,6 +1122,9 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct 
cvm_mmc_host *host)
        slot->bus_id = id;
        slot->cached_rca = 1;
 
+#ifdef CONFIG_MMC_PSTORE
+       host->pstore = 0;
+#endif
        host->acquire_bus(host);
        host->slot[id] = slot;
        cvm_mmc_switch_to(slot);
diff --git a/drivers/mmc/host/cavium.h b/drivers/mmc/host/cavium.h
index f3eea5eaa678..b72dea9a81eb 100644
--- a/drivers/mmc/host/cavium.h
+++ b/drivers/mmc/host/cavium.h
@@ -75,6 +75,9 @@ struct cvm_mmc_host {
        spinlock_t irq_handler_lock;
        struct semaphore mmc_serializer;
 
+#ifdef CONFIG_MMC_PSTORE
+       bool pstore;
+#endif
        struct gpio_desc *global_pwr_gpiod;
        atomic_t shared_power_users;
 
-- 
2.17.1

Reply via email to