update mcsdk_tools based on platform library 00.03
[keystone-rtos/mcsdk-tools.git] / post / src / qm.c
1 /******************************************************************************************
2  * FILE PURPOSE: Boot queue manager driver
3  ******************************************************************************************
4  * FILE NAME: qm.c
5  *
6  * DESCRIPTION: The boot loader queue manager driver. This driver uses a very simple
7  *                              setup on the queue manager, with a single link ram and a single
8  *                              memory region. The descriptors are configured as host descriptors
9  *                              and have the minimum 32 byte size.
10  *
11  *              For the boot driver queue register C is not written. It is important
12  *              to the boot loader if packets are pushed/popped from the head or
13  *              tail of a queue.
14  *
15  ******************************************************************************************/
16 #include "types.h"
17 #include "platform.h"
18 #include "qm_loc.h"
19 #include "qm_api.h"
20 #include "target.h"
21 #include <string.h>
23 /*******************************************************************************************
24  * FUNCTION PURPOSE: Pop a descriptor off of a queue
25  *******************************************************************************************
26  * DESCRIPTION: The descriptor is read from queue register D.
27  *******************************************************************************************/
28 qmHostDesc_t *hwQmQueuePop (uint32_t qnum)
29 {
30     qmHostDesc_t *hd;
31     uint32_t        uhd;
33     /* Strip the descriptor size info */
34     uhd = DEVICE_REG32_R (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(qnum));
35     uhd = uhd & ~0xf;
36     hd  = (qmHostDesc_t *)uhd;
38     return (hd);
39 } /* hwQmQueuePop */
41 /*******************************************************************************************
42  * FUNCTION PURPOSE: Return the number of descriptors on a queue
43  *******************************************************************************************
44  * DESCRIPTION: The queue count is returned
45  *******************************************************************************************/
46 uint32_t  hwQmQueueCount (uint32_t qnum)
47 {
48     uint32_t rega;
50     rega = DEVICE_REG32_R (DEVICE_QM_QUEUE_STATUS_BASE + QM_REG_QUEUE_REGA(qnum));
51     rega = BOOT_READ_BITFIELD (rega, QM_QA_ENTRY_COUNT_MSB, QM_QA_ENTRY_COUNT_LSB);
52     return (rega);
54 } /* hwQmQueueCount */
56 /*******************************************************************************************
57  * FUNCTION PURPOSE: Set a queue threshold
58  *******************************************************************************************
59  * DESCRIPTION: The queue threshold is enabled. Only high threshold is set, with a threshold
60  *                              value of 1.
61  *******************************************************************************************/
62 int16_t hwQmInitThreshold (uint32_t qnum)
63 {
64         DEVICE_REG32_W (DEVICE_QM_QUEUE_STATUS_BASE + QM_REG_STAT_CFG_REGD(qnum), 0x81);
66         return (0);
68 } /* hwQmInitThreshold */
71 /*******************************************************************************************
72  * FUNCTION PURPOSE: Push a descriptor onto a queue
73  *******************************************************************************************
74  * DESCRIPTION: The descriptor is written to queue register D. No check is made to see
75  *              if the queue number is valid.
76  *******************************************************************************************/
77 void hwQmQueuePush (qmHostDesc_t *hd, uint32_t qnum, uint32_t descrSize)
78 {
79         uint32_t regd;
81         regd = ((uint32_t) hd | ((descrSize >> 4) - 1));
83     /* Push the descriptor onto the queue */
84     DEVICE_REG32_W (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(qnum), regd);
86 } /* hwQmQueuePush */
88 /*******************************************************************************************
89  * FILE PURPOSE: Setup the queue manager
90  *******************************************************************************************
91  * DESCRIPTION: The queue manager is setup using a single linking ram and memory region,
92  *              with fixed descriptor initialization.
93  *
94  *              Since the linking ram and descriptor regions are configured, it is assumed
95  *              that all queues are currently empty.
96  *
97  ********************************************************************************************/
98 int16_t hwQmSetup (qmConfig_t *cfg)
99 {
100     uint32_t v;
101     uint32_t w;
102     uint32_t x;
103     uint32_t i;
104     qmHostDesc_t *hd;
106     /* Verify that alignment requirements */
107     if ( (cfg->linkRamBase & (QM_LINKRAM_ALIGN-1))  !=  0 )
108         return (QM_INVALID_LINKRAM_ALIGNMENT);
110     if ( (cfg->memRegionBase & (QM_MEMR_ALIGN-1))   !=  0 )
111         return (QM_INVALID_MEMREGION_ALIGNMENT);
113     /* Verify linkram sizing is in range */
114     if ( (cfg->linkRamSize & ~QM_REG_LINKRAM_SIZE_MAX_MASK)  != 0 )
115         return (QM_INVALID_LINKRAM_SIZE);
117     /* Verify there is enough linkram to cover the single memory region */
118     if (cfg->linkRamSize < cfg->memRegNumDescriptors)
119         return (QM_INVALID_LINKRAM_RAM_SIZE);
122     /* Linking RAM info */
123     DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(0), cfg->linkRamBase);
124     DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_SIZE(0), cfg->linkRamSize);
125     DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(1), 0);
127     /* Memory region 0 info */
128     DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_BASE_ADDR(0), cfg->memRegionBase);
129     DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_START_IDX(0), 0);
131     /* Calculate the 2 fields in the descriptor setup register. Bits 0-3 specifiy
132      * the total memory size rounded up to the next higher power of two, and
133      * is expresses as 2^(n - 5). So for example if you have 20 descriptors
134      * The next higher power of 2 that exceeds this is 32, which is 2^5, so the value 0 (5-5)
135      * is placed in this field */
136     v = (31 - chipLmbd (1, cfg->memRegNumDescriptors));
137     if (v >= 4)
138       v = v - 4;
139     else
140       v = 0;
142     /* Add the descriptor size field */
143     QM_REG_VAL_DESC_SETUP_SET_DESC_SIZE(v, QM_DESC_SIZE_BYTES);
145     DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_DESC_SETUP(0), v);
148     /* Now format the descriptors and put them in a queue */
149     for (i = 0, v = cfg->memRegionBase; i < cfg->memRegNumDescriptors; i++, v += QM_DESC_SIZE_BYTES)  {
151         hd = (qmHostDesc_t *)v;
152         memset (hd, 0, sizeof(qmHostDesc_t));
154         hd->descInfo   = QM_DESC_DEFAULT_DESCINFO;
155         hd->packetInfo = QM_DESC_DEFAULT_PINFO;
157         if (QM_DESC_INFO_GET_PSINFO_LOC(hd->descInfo) == QM_DESC_PSINFO_IN_DESCR)  {
158                 if (QM_PKT_INFO_GET_EPIB(hd->packetInfo) == QM_DESC_PINFO_EPIB)
159                         w = QM_DESC_SIZE_BYTES - 32 - 16;  /* 32 bytes min descriptor size, 16 bytes extended info */
160                 else
161                         w = QM_DESC_SIZE_BYTES - 32;
162         }  else
163                 w = 0;
165         QM_PKT_INFO_SET_PSINFO_SIZE(hd->packetInfo, (w >> 2));
168         /* Push the descriptor onto the queue */
169         x = deviceLocalAddrToGlobal (v);
171         DEVICE_REG32_W (DEVICE_QM_MANAGER_QUEUES_BASE + QM_REG_QUEUE_REGD(cfg->destQ), x);
173     }
175     return (QM_OK);
177 } /* hwQmSetup */
180 /****************************************************************************************
181  * FUNCTION PURPOSE: Disable the QM
182  ****************************************************************************************
183  * DESCRIPTION: The QM is reset by clearing the linking ram and region 0 information
184  ****************************************************************************************/
185 void hwQmTeardown (void)
187     uint32_t i;
189     /* Linking RAM info */
190     for (i = 0; i < DEVICE_QM_NUM_LINKRAMS; i++)  {
191         DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_BASE(i), 0);
192         DEVICE_REG32_W (DEVICE_QM_MANAGER_BASE + QM_REG_LINKRAM_SIZE(i), 0);
193     }
195     /* Memory region info */
196     for (i = 0; i < DEVICE_QM_NUM_MEMREGIONS; i++)  {
197         DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_BASE_ADDR(i),  0);
198         DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_START_IDX(i),  0);
199         DEVICE_REG32_W (DEVICE_QM_DESC_SETUP_BASE + QM_REG_MEMR_DESC_SETUP(i), 0);
200     }
202 } /* hwQmTeardown */