Based on Linux downstream commit:

| commit a621a1075550f0e857adbadb4142fc1b3142136d
| Author: Sai Sree Kartheek Adivi <s-ad...@ti.com>
| Date:   Thu Feb 20 21:56:48 2025 +0530
|
|     PENDING: drivers: soc: ti: k3-ringacc: handle absence of tisci
|
|     Handle absence of tisci with direct register writes. This will support
|     platforms that do not have tisci firmware like AM62L.
|
|     Signed-off-by: Sai Sree Kartheek Adivi <s-ad...@ti.com>

Signed-off-by: Sascha Hauer <s.ha...@pengutronix.de>
---
 drivers/soc/ti/k3-navss-ringacc.c | 127 ++++++++++++++++++++++++++++++++++----
 include/soc/ti/k3-navss-ringacc.h |   3 +
 2 files changed, 117 insertions(+), 13 deletions(-)

diff --git a/drivers/soc/ti/k3-navss-ringacc.c 
b/drivers/soc/ti/k3-navss-ringacc.c
index 
4835aef2f3d2425bf45610cc9e5b9273bde30eb3..dfc397a1f5aca08a90ed773540bdeae9f50b8173
 100644
--- a/drivers/soc/ti/k3-navss-ringacc.c
+++ b/drivers/soc/ti/k3-navss-ringacc.c
@@ -40,6 +40,38 @@ struct k3_ring_rt_regs {
        u32     hwindx;
 };
 
+#define K3_RINGACC_RT_CFG_REGS_OFS     0x40
+#define K3_DMARING_CFG_ADDR_HI_MASK    GENMASK(3, 0)
+#define K3_DMARING_CFG_ASEL_SHIFT      16
+#define K3_DMARING_CFG_SIZE_MASK       GENMASK(15, 0)
+
+/**
+ * struct k3_ring_cfg_regs - The RA Configuration Registers region
+ *
+ * @ba_lo: Ring Base Address Low Register
+ * @ba_hi: Ring Base Address High Register
+ * @size: Ring Size Register
+ */
+struct k3_ring_cfg_regs {
+       u32     ba_lo;
+       u32     ba_hi;
+       u32     size;
+};
+
+#define K3_RINGACC_RT_INT_REGS_OFS             0x140
+#define K3_RINGACC_RT_INT_ENABLE_SET_COMPLETE  BIT(0)
+#define K3_RINGACC_RT_INT_ENABLE_SET_TR                        BIT(2)
+
+struct k3_ring_intr_regs {
+       u32     enable_set;
+       u32     resv_4;
+       u32     clr;
+       u32     resv_16;
+       u32     status_set;
+       u32     resv_8;
+       u32     status;
+};
+
 #define K3_RINGACC_RT_REGS_STEP                        0x1000
 #define K3_DMARING_RT_REGS_STEP                        0x2000
 #define K3_DMARING_RT_REGS_REVERSE_OFS         0x1000
@@ -152,6 +184,8 @@ struct k3_ring_state {
  */
 struct k3_ring {
        struct k3_ring_rt_regs __iomem *rt;
+       struct k3_ring_cfg_regs __iomem *cfg;
+       struct k3_ring_intr_regs __iomem *intr;
        struct k3_ring_fifo_regs __iomem *fifos;
        struct k3_ringacc_proxy_target_regs  __iomem *proxy;
        dma_addr_t      ring_mem_dma;
@@ -439,6 +473,10 @@ static void k3_ringacc_ring_reset_sci(struct k3_ring *ring)
        struct k3_ringacc *ringacc = ring->parent;
        int ret;
 
+       /* TODO: Implement ring reset without tisci */
+       if (!ringacc->tisci)
+               return;
+
        ring_cfg.nav_id = ringacc->tisci_dev_id;
        ring_cfg.index = ring->ring_id;
        ring_cfg.valid_params = TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID;
@@ -467,16 +505,30 @@ static void k3_ringacc_ring_reconfig_qmode_sci(struct 
k3_ring *ring,
        struct ti_sci_msg_rm_ring_cfg ring_cfg = { 0 };
        struct k3_ringacc *ringacc = ring->parent;
        int ret;
+       u32 reg;
 
        ring_cfg.nav_id = ringacc->tisci_dev_id;
        ring_cfg.index = ring->ring_id;
        ring_cfg.valid_params = TI_SCI_MSG_VALUE_RM_RING_MODE_VALID;
        ring_cfg.mode = mode;
 
-       ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, &ring_cfg);
-       if (ret)
-               dev_err(ringacc->dev, "TISCI reconf qmode fail (%d) ring_idx 
%d\n",
-                       ret, ring->ring_id);
+       if (!ringacc->tisci) {
+               writel(ring_cfg.addr_lo, &ring->cfg->ba_lo);
+               writel((ring_cfg.addr_hi & K3_DMARING_CFG_ADDR_HI_MASK) +
+                               (ring_cfg.asel << K3_DMARING_CFG_ASEL_SHIFT),
+                               &ring->cfg->ba_hi);
+
+               reg = readl(&ring->cfg->size);
+               reg &= ~K3_DMARING_CFG_SIZE_MASK;
+               reg |= ring_cfg.count & K3_DMARING_CFG_SIZE_MASK;
+
+               writel(reg, &ring->cfg->size);
+       } else {
+               ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, 
&ring_cfg);
+               if (ret)
+                       dev_err(ringacc->dev, "TISCI reconf qmode fail (%d) 
ring_idx %d\n",
+                                       ret, ring->ring_id);
+       }
 }
 
 void k3_ringacc_ring_reset_dma(struct k3_ring *ring, u32 occ)
@@ -543,15 +595,29 @@ static void k3_ringacc_ring_free_sci(struct k3_ring *ring)
        struct ti_sci_msg_rm_ring_cfg ring_cfg = { 0 };
        struct k3_ringacc *ringacc = ring->parent;
        int ret;
+       u32 reg;
 
        ring_cfg.nav_id = ringacc->tisci_dev_id;
        ring_cfg.index = ring->ring_id;
        ring_cfg.valid_params = TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER;
 
-       ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, &ring_cfg);
-       if (ret)
-               dev_err(ringacc->dev, "TISCI ring free fail (%d) ring_idx %d\n",
-                       ret, ring->ring_id);
+       if (!ringacc->tisci) {
+               writel(ring_cfg.addr_lo, &ring->cfg->ba_lo);
+               writel((ring_cfg.addr_hi & K3_DMARING_CFG_ADDR_HI_MASK) +
+                               (ring_cfg.asel << K3_DMARING_CFG_ASEL_SHIFT),
+                               &ring->cfg->ba_hi);
+
+               reg = readl(&ring->cfg->size);
+               reg &= ~K3_DMARING_CFG_SIZE_MASK;
+               reg |= ring_cfg.count & K3_DMARING_CFG_SIZE_MASK;
+
+               writel(reg, &ring->cfg->size);
+       } else {
+               ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, 
&ring_cfg);
+               if (ret)
+                       dev_err(ringacc->dev, "TISCI ring free fail (%d) 
ring_idx %d\n",
+                                       ret, ring->ring_id);
+       }
 }
 
 int k3_ringacc_ring_free(struct k3_ring *ring)
@@ -626,15 +692,31 @@ u32 k3_ringacc_get_tisci_dev_id(struct k3_ring *ring)
 }
 EXPORT_SYMBOL_GPL(k3_ringacc_get_tisci_dev_id);
 
+u32 k3_ringacc_ring_get_irq_status(struct k3_ring *ring)
+{
+       struct k3_ringacc *ringacc = ring->parent;
+       struct k3_ring *ring2 = &ringacc->rings[ring->ring_id];
+
+       return readl(&ring2->intr->status);
+}
+EXPORT_SYMBOL_GPL(k3_ringacc_ring_get_irq_status);
+
+void k3_ringacc_ring_clear_irq(struct k3_ring *ring)
+{
+       struct k3_ringacc *ringacc = ring->parent;
+       struct k3_ring *ring2 = &ringacc->rings[ring->ring_id];
+
+       writel(0xFF, &ring2->intr->status);
+}
+EXPORT_SYMBOL_GPL(k3_ringacc_ring_clear_irq);
+
 static int k3_ringacc_ring_cfg_sci(struct k3_ring *ring)
 {
        struct ti_sci_msg_rm_ring_cfg ring_cfg = { 0 };
        struct k3_ringacc *ringacc = ring->parent;
+       u32 reg;
        int ret;
 
-       if (!ringacc->tisci)
-               return -EINVAL;
-
        ring_cfg.nav_id = ringacc->tisci_dev_id;
        ring_cfg.index = ring->ring_id;
        ring_cfg.valid_params = TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER;
@@ -645,11 +727,26 @@ static int k3_ringacc_ring_cfg_sci(struct k3_ring *ring)
        ring_cfg.size = ring->elm_size;
        ring_cfg.asel = ring->asel;
 
+       if (!ringacc->tisci) {
+               writel(ring_cfg.addr_lo, &ring->cfg->ba_lo);
+               writel((ring_cfg.addr_hi & K3_DMARING_CFG_ADDR_HI_MASK) +
+                               (ring_cfg.asel << K3_DMARING_CFG_ASEL_SHIFT),
+                               &ring->cfg->ba_hi);
+
+               reg = readl(&ring->cfg->size);
+               reg &= ~K3_DMARING_CFG_SIZE_MASK;
+               reg |= ring_cfg.count & K3_DMARING_CFG_SIZE_MASK;
+
+               writel(reg, &ring->cfg->size);
+               writel(K3_RINGACC_RT_INT_ENABLE_SET_COMPLETE | 
K3_RINGACC_RT_INT_ENABLE_SET_TR,
+                               &ring->intr->enable_set);
+               return 0;
+       }
+
        ret = ringacc->tisci_ring_ops->set_cfg(ringacc->tisci, &ring_cfg);
        if (ret)
                dev_err(ringacc->dev, "TISCI config ring fail (%d) ring_idx 
%d\n",
-                       ret, ring->ring_id);
-
+                               ret, ring->ring_id);
        return ret;
 }
 
@@ -1426,6 +1523,10 @@ struct k3_ringacc *k3_ringacc_dmarings_init(struct 
device *dev,
                struct k3_ring *ring = &ringacc->rings[i];
 
                ring->rt = base_rt + K3_DMARING_RT_REGS_STEP * i;
+               ring->cfg = base_rt + K3_RINGACC_RT_CFG_REGS_OFS +
+                           K3_DMARING_RT_REGS_STEP * i;
+               ring->intr = base_rt + K3_RINGACC_RT_INT_REGS_OFS +
+                            K3_DMARING_RT_REGS_STEP * i;
                ring->parent = ringacc;
                ring->ring_id = i;
                ring->proxy_id = K3_RINGACC_PROXY_NOT_USED;
diff --git a/include/soc/ti/k3-navss-ringacc.h 
b/include/soc/ti/k3-navss-ringacc.h
index 
80b14b98622480d5c6927afc6e5b5407eae5c7f5..96a89113c100b409aef77bc0ee55c07597196223
 100644
--- a/include/soc/ti/k3-navss-ringacc.h
+++ b/include/soc/ti/k3-navss-ringacc.h
@@ -158,6 +158,9 @@ u32 k3_ringacc_get_ring_id(struct k3_ring *ring);
  */
 int k3_ringacc_get_ring_irq_num(struct k3_ring *ring);
 
+u32 k3_ringacc_ring_get_irq_status(struct k3_ring *ring);
+void k3_ringacc_ring_clear_irq(struct k3_ring *ring);
+
 /**
  * k3_ringacc_ring_cfg - ring configure
  * @ring: pointer on ring

-- 
2.39.5


Reply via email to