]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blobdiff - src/hw/qm/qm.c
Initial c661x version
[keystone-rtos/ibl.git] / src / hw / qm / qm.c
diff --git a/src/hw/qm/qm.c b/src/hw/qm/qm.c
new file mode 100644 (file)
index 0000000..b7a0e69
--- /dev/null
@@ -0,0 +1,213 @@
+/******************************************************************************************
+ * FILE PURPOSE: Boot queue manager driver
+ ******************************************************************************************
+ * FILE NAME: qm.c
+ *
+ * DESCRIPTION: The boot loader queue manager driver. This driver uses a very simple
+ *                             setup on the queue manager, with a single link ram and a single
+ *                             memory region. The descriptors are configured as host descriptors
+ *                             and have the minimum 32 byte size.
+ *
+ *              For the boot driver queue register C is not written. It is important
+ *              to the boot loader if packets are pushed/popped from the head or
+ *              tail of a queue.
+ *
+ ******************************************************************************************/
+#include "types.h"
+#include "qm_loc.h"
+#include "qm_api.h"
+#include "device.h"
+#include <string.h>
+
+/*******************************************************************************************
+ * FUNCTION PURPOSE: Pop a descriptor off of a queue
+ *******************************************************************************************
+ * DESCRIPTION: The descriptor is read from queue register D.
+ *******************************************************************************************/
+qmHostDesc_t *hwQmQueuePop (UINT32 qnum)
+{
+    qmHostDesc_t *hd;
+    UINT32        uhd;
+
+    /* Strip the descriptor size info */
+    uhd = DEVICE_REG32_R (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(qnum));
+    uhd = uhd & ~0xf;
+    hd  = (qmHostDesc_t *)uhd;
+
+    return (hd);
+} /* hwQmQueuePop */
+
+/*******************************************************************************************
+ * FUNCTION PURPOSE: Return the number of descriptors on a queue
+ *******************************************************************************************
+ * DESCRIPTION: The queue count is returned
+ *******************************************************************************************/
+UINT32  hwQmQueueCount (UINT32 qnum)
+{
+    UINT32 rega;
+
+    rega = DEVICE_REG32_R (DEVICE_QM_QUEUE_STATUS_BASE + QM_REG_QUEUE_REGA(qnum));
+    rega = BOOT_READ_BITFIELD (rega, QM_QA_ENTRY_COUNT_MSB, QM_QA_ENTRY_COUNT_LSB);
+    return (rega);
+
+} /* hwQmQueueCount */
+
+/*******************************************************************************************
+ * FUNCTION PURPOSE: Set a queue threshold
+ *******************************************************************************************
+ * DESCRIPTION: The queue threshold is enabled. Only high threshold is set, with a threshold
+ *                             value of 1.
+ *******************************************************************************************/
+SINT16 hwQmInitThreshold (UINT32 qnum)
+{
+       DEVICE_REG32_W (DEVICE_QM_QUEUE_STATUS_BASE + QM_REG_STAT_CFG_REGD(qnum), 0x81);
+       
+       return (0);
+       
+} /* hwQmInitThreshold */      
+
+
+/*******************************************************************************************
+ * FUNCTION PURPOSE: Push a descriptor onto a queue
+ *******************************************************************************************
+ * DESCRIPTION: The descriptor is written to queue register D. No check is made to see
+ *              if the queue number is valid.
+ *******************************************************************************************/
+void hwQmQueuePush (qmHostDesc_t *hd, UINT32 qnum, UINT32 descrSize)
+{
+       UINT32 regd;
+       
+       regd = ((UINT32) hd | ((descrSize >> 4) - 1));
+       
+    /* Push the descriptor onto the queue */
+    DEVICE_REG32_W (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(qnum), regd);
+
+} /* hwQmQueuePush */
+
+/*******************************************************************************************
+ * FILE PURPOSE: Setup the queue manager
+ *******************************************************************************************
+ * DESCRIPTION: The queue manager is setup using a single linking ram and memory region,
+ *              with fixed descriptor initialization.
+ *
+ *              Since the linking ram and descriptor regions are configured, it is assumed
+ *              that all queues are currently empty.
+ *
+ ********************************************************************************************/
+SINT16 hwQmSetup (qmConfig_t *cfg)
+{
+    UINT32 v;
+    UINT32 w;
+    UINT32 x;
+    UINT32 i;
+    qmHostDesc_t *hd;
+
+    /* Verify that alignment requirements */
+    if ( (cfg->linkRamBase & (QM_LINKRAM_ALIGN-1))  !=  0 )
+        return (QM_INVALID_LINKRAM_ALIGNMENT);
+
+    if ( (cfg->memRegionBase & (QM_MEMR_ALIGN-1))   !=  0 )
+        return (QM_INVALID_MEMREGION_ALIGNMENT);
+
+    /* Verify linkram sizing is in range */
+    if ( (cfg->linkRamSize & ~QM_REG_LINKRAM_SIZE_MAX_MASK)  != 0 )
+        return (QM_INVALID_LINKRAM_SIZE);
+
+    /* Verify there is enough linkram to cover the single memory region */ 
+    if (cfg->linkRamSize < cfg->memRegNumDescriptors)
+        return (QM_INVALID_LINKRAM_RAM_SIZE);
+
+
+    /* Linking RAM info */
+    DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(0), cfg->linkRamBase);
+    DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_SIZE(0), cfg->linkRamSize);
+    DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(1), 0);
+
+    /* Memory region 0 info */
+    DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_BASE_ADDR(0), cfg->memRegionBase);
+    DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_START_IDX(0), 0);
+
+    /* Calculate the 2 fields in the descriptor setup register. Bits 0-3 specifiy
+     * the total memory size rounded up to the next higher power of two, and
+     * is expresses as 2^(n - 5). So for example if you have 20 descriptors
+     * The next higher power of 2 that exceeds this is 32, which is 2^5, so the value 0 (5-5)
+     * is placed in this field */
+    v = (31 - chipLmbd (1, cfg->memRegNumDescriptors));
+    if (v >= 4)
+      v = v - 4;
+    else
+      v = 0;
+
+    /* Add the descriptor size field */
+    QM_REG_VAL_DESC_SETUP_SET_DESC_SIZE(v, QM_DESC_SIZE_BYTES);
+
+    DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_DESC_SETUP(0), v);
+
+
+    /* Now format the descriptors and put them in a queue */
+    for (i = 0, v = cfg->memRegionBase; i < cfg->memRegNumDescriptors; i++, v += QM_DESC_SIZE_BYTES)  {
+
+        hd = (qmHostDesc_t *)v;
+        memset (hd, 0, sizeof(qmHostDesc_t));
+
+        hd->descInfo   = QM_DESC_DEFAULT_DESCINFO;
+        hd->packetInfo = QM_DESC_DEFAULT_PINFO;
+        
+        if (QM_DESC_INFO_GET_PSINFO_LOC(hd->descInfo) == QM_DESC_PSINFO_IN_DESCR)  {
+               if (QM_PKT_INFO_GET_EPIB(hd->packetInfo) == QM_DESC_PINFO_EPIB)
+                       w = QM_DESC_SIZE_BYTES - 32 - 16;  /* 32 bytes min descriptor size, 16 bytes extended info */
+               else
+                       w = QM_DESC_SIZE_BYTES - 32;
+        }  else
+               w = 0;
+               
+               QM_PKT_INFO_SET_PSINFO_SIZE(hd->packetInfo, (w >> 2));
+
+        /* Push the descriptor onto the queue */
+        x = deviceLocalAddrToGlobal (v);
+
+        DEVICE_REG32_W (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(cfg->destQ), x);
+
+    }
+
+    return (QM_OK);
+
+} /* hwQmSetup */
+
+
+/****************************************************************************************
+ * FUNCTION PURPOSE: Disable the QM
+ ****************************************************************************************
+ * DESCRIPTION: The QM is reset by clearing the linking ram and region 0 information
+ ****************************************************************************************/
+void hwQmTeardown (void)
+{
+    UINT32 i;
+
+    /* Linking RAM info */
+    for (i = 0; i < DEVICE_QM_NUM_LINKRAMS; i++)  {
+        DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(i), 0);
+        DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_SIZE(i), 0);
+    }
+
+    /* Memory region info */
+    for (i = 0; i < DEVICE_QM_NUM_MEMREGIONS; i++)  {
+        DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_BASE_ADDR(i),  0);
+        DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_START_IDX(i),  0);
+        DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_DESC_SETUP(i), 0);
+    }
+
+} /* hwQmTeardown */
+
+
+
+
+
+
+
+
+
+
+
+