--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * U-Boot specific helpers for TI K3 AM65x NAVSS Ring accelerator
+ * Manager (RA) subsystem driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+struct k3_nav_ring_cfg_regs {
+ u32 resv_64[16];
+ u32 ba_lo; /* Ring Base Address Lo Register */
+ u32 ba_hi; /* Ring Base Address Hi Register */
+ u32 size; /* Ring Size Register */
+ u32 event; /* Ring Event Register */
+ u32 orderid; /* Ring OrderID Register */
+};
+
+#define KNAV_RINGACC_CFG_REGS_STEP 0x100
+
+#define KNAV_RINGACC_CFG_RING_BA_HI_ADDR_HI_MASK GENMASK(15, 0)
+
+#define KNAV_RINGACC_CFG_RING_SIZE_QMODE_MASK GENMASK(31, 30)
+#define KNAV_RINGACC_CFG_RING_SIZE_QMODE_SHIFT (30)
+
+#define KNAV_RINGACC_CFG_RING_SIZE_ELSIZE_MASK GENMASK(26, 24)
+#define KNAV_RINGACC_CFG_RING_SIZE_ELSIZE_SHIFT (24)
+
+static void k3_ringacc_ring_reset_raw(struct k3_nav_ring *ring)
+{
+ writel(0, &ring->cfg->size);
+}
+
+static void k3_ringacc_ring_reconfig_qmode_raw(struct k3_nav_ring *ring, enum k3_nav_ring_mode mode)
+{
+ u32 val;
+
+ val = readl(&ring->cfg->size);
+ val &= KNAV_RINGACC_CFG_RING_SIZE_QMODE_MASK;
+ val |= mode << KNAV_RINGACC_CFG_RING_SIZE_QMODE_SHIFT;
+ writel(val, &ring->cfg->size);
+}
+
+static void k3_ringacc_ring_free_raw(struct k3_nav_ring *ring)
+{
+ writel(0, &ring->cfg->ba_hi);
+ writel(0, &ring->cfg->ba_lo);
+ writel(0, &ring->cfg->size);
+}
+
+static void k3_nav_ringacc_ring_cfg_raw(struct k3_nav_ring *ring)
+{
+ u32 val;
+
+ writel(lower_32_bits(ring->ring_mem_dma), &ring->cfg->ba_lo);
+ writel(upper_32_bits(ring->ring_mem_dma), &ring->cfg->ba_hi);
+
+ val = ring->mode << KNAV_RINGACC_CFG_RING_SIZE_QMODE_SHIFT |
+ ring->elm_size << KNAV_RINGACC_CFG_RING_SIZE_ELSIZE_SHIFT |
+ ring->size;
+ writel(val, &ring->cfg->size);
+}
/**
* struct k3_nav_ring - RA Ring descriptor
*
+ * @cfg - Ring configuration registers
* @rt - Ring control/status registers
* @fifos - Ring queues registers
* @ring_mem_dma - Ring buffer dma address
* @use_count - Use count for shared rings
*/
struct k3_nav_ring {
+ struct k3_nav_ring_cfg_regs __iomem *cfg;
struct k3_nav_ring_rt_regs __iomem *rt;
struct k3_nav_ring_fifo_regs __iomem *fifos;
dma_addr_t ring_mem_dma;
bool dual_ring;
};
+#include "k3-navss-ringacc-u-boot.c"
+
static int k3_nav_ringacc_ring_read_occ(struct k3_nav_ring *ring)
{
return readl(&ring->rt->occ) & KNAV_RINGACC_RT_OCC_MASK;
struct k3_nav_ringacc *ringacc = ring->parent;
int ret;
+ if (IS_ENABLED(CONFIG_K3_DM_FW))
+ return k3_ringacc_ring_reset_raw(ring);
+
ret = ringacc->tisci_ring_ops->config(
ringacc->tisci,
TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID,
struct k3_nav_ringacc *ringacc = ring->parent;
int ret;
+ if (IS_ENABLED(CONFIG_K3_DM_FW))
+ return k3_ringacc_ring_reconfig_qmode_raw(ring, mode);
+
ret = ringacc->tisci_ring_ops->config(
ringacc->tisci,
TI_SCI_MSG_VALUE_RM_RING_MODE_VALID,
struct k3_nav_ringacc *ringacc = ring->parent;
int ret;
+ if (IS_ENABLED(CONFIG_K3_DM_FW))
+ return k3_ringacc_ring_free_raw(ring);
+
ret = ringacc->tisci_ring_ops->config(
ringacc->tisci,
TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER,
ring->mode,
ring->elm_size,
0);
- if (ret)
+ if (ret) {
dev_err(ringacc->dev, "TISCI config ring fail (%d) ring_idx %d\n",
ret, ring_idx);
+ return ret;
+ }
- return ret;
+ /*
+ * Above TI SCI call handles firewall configuration, cfg
+ * register configuration still has to be done locally in
+ * absence of RM services.
+ */
+ if (IS_ENABLED(CONFIG_K3_DM_FW))
+ k3_nav_ringacc_ring_cfg_raw(ring);
+
+ return 0;
}
static int k3_dmaring_ring_cfg(struct k3_nav_ring *ring, struct k3_nav_ring_cfg *cfg)
static int k3_nav_ringacc_init(struct udevice *dev, struct k3_nav_ringacc *ringacc)
{
- void __iomem *base_rt;
+ void __iomem *base_cfg, *base_rt;
int ret, i;
ret = k3_nav_ringacc_probe_dt(ringacc);
if (ret)
return ret;
+ base_cfg = dev_remap_addr_name(dev, "cfg");
+ pr_debug("cfg %p\n", base_cfg);
+ if (!base_cfg)
+ return -EINVAL;
+
base_rt = (uint32_t *)devfdt_get_addr_name(dev, "rt");
pr_debug("rt %p\n", base_rt);
if (IS_ERR(base_rt))
return -ENOMEM;
for (i = 0; i < ringacc->num_rings; i++) {
+ ringacc->rings[i].cfg = base_cfg +
+ KNAV_RINGACC_CFG_REGS_STEP * i;
ringacc->rings[i].rt = base_rt +
KNAV_RINGACC_RT_REGS_STEP * i;
ringacc->rings[i].parent = ringacc;