1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * MPFS HAL Embedded Software
7  *
8  */
9 /*******************************************************************************
10  * @file mss_axiswitch.c
11  * @author Microchip-FPGA Embedded Systems Solutions
12  * @brief PolarFire SoC MSS AXI switch configuration
13  *
14  */
15 
16 #include <stddef.h>
17 #include <stdint.h>
18 #include "mpfs_hal/mss_hal.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /*Returns the value of AXI_HW_CFG_REG register*/
MSS_AXISW_get_hwcfg(void)25 uint32_t MSS_AXISW_get_hwcfg(void)
26 {
27     return (AXISW->HWCFG);
28 }
29 
30 /*Returns the value of AXI_VERSION_ID_REG register*/
MSS_AXISW_get_vid(void)31 uint32_t MSS_AXISW_get_vid(void)
32 {
33     return (AXISW->VID);
34 }
35 
36 /*Performs write operation on the AXI SWITCH APB interface,
37  * Parameters:
38  * master_port_num = AXI Master Port number. See Enum mss_axisw_mport_t above.
39 
40 
41  Note: QoS values are programmable through registers only for AXI3 configurations.
42  We have AXI4 so the QoS value programming should not be attempted.
43  IF you try to write/read QoS value you will get return value =1 (AXI_ERR_BIT)
44 
45  Burstiness peak rate and transaction rate can be configured using other APIs.
46 
47   data: QoS value to be programmed
48  return value: As received form AXI_ERR_BIT in CMD register.
49 
50  * */
MSS_AXISW_write_qos_val(mss_axisw_mport_t master_port_num,uint32_t data)51 uint32_t MSS_AXISW_write_qos_val(mss_axisw_mport_t master_port_num,
52                                                uint32_t data)
53 {
54     while(AXISW->CMD & AXISW_CMD_EN_MASK);  /*make sure previous command completed*/
55 
56     AXISW->DATA = data & AXISW_DATA_QOSVAL_MASK;  /*only valid values of bits[3:0]*/
57 
58     AXISW->CMD = (AXISW_CMD_RW_MASK |
59                  (master_port_num << AXISW_CMD_RWCHAN) |
60                  MSS_AXISW_QOS_VAL |
61                  AXISW_CMD_EN_MASK);
62 
63     while(AXISW->CMD & AXISW_CMD_EN_MASK);    /*Wait for command to complete*/
64 
65     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
66 }
67 
68 /*Performs read operation on the AXI SWITCH APB interface,
69  * Parameters:
70  * master_port_num = AXI Master Port number. See Enum mss_axisw_mport_t above.
71  *
72  * Note: QoS values are programmable through registers only for AXI3 configurations.
73  We have AXI4 so the QoS value programming should not be attempted.
74  IF you try to write/read QoS value you will get return value =1 (AXI_ERR_BIT)
75  *
76  * returns the data returned by AXI SWITCH read operation for QoS command
77  *
78  * return value: As received form AXI_ERR_BIT in CMD register.
79  */
MSS_AXISW_read_qos_val(mss_axisw_mport_t master_port_num,uint32_t * rd_data)80 uint32_t MSS_AXISW_read_qos_val(mss_axisw_mport_t master_port_num,
81                                               uint32_t* rd_data)
82 {
83 
84     while(AXISW->CMD & AXISW_CMD_EN_MASK);
85 
86     AXISW->CMD &= ~(AXISW_CMD_RW_MASK);  /*Clear read/write bit*/
87 
88     AXISW->CMD = ((master_port_num << AXISW_CMD_RWCHAN) | (MSS_AXISW_QOS_VAL) | AXISW_CMD_EN_MASK);
89 
90     while(AXISW->CMD & AXISW_CMD_EN_MASK);
91 
92     *rd_data = AXISW->DATA & AXISW_DATA_QOSVAL_MASK;
93 
94     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
95 }
96 
97 /* Programs the peak rate and transaction rate value for the given master port
98  read/write address channel
99 
100  NOTE: Peak rate and transaction rate are programmed simultaneously in one command.
101  So we must make sure that both desired valid values must be provided.
102 
103 * return value: As received form AXI_ERR_BIT in CMD register.
104 
105 */
MSS_AXISW_write_rate(mss_axisw_mport_t master_port_num,mss_axisw_rate_t peak_rate,mss_axisw_rate_t xct_rate)106 uint32_t MSS_AXISW_write_rate(mss_axisw_mport_t master_port_num,
107                                             mss_axisw_rate_t peak_rate,
108                                             mss_axisw_rate_t xct_rate)
109 {
110     while(AXISW->CMD & AXISW_CMD_EN_MASK);  /*make sure previous command completed*/
111     AXISW->DATA = ((peak_rate) << AXISW_DATA_PEAKRT) | ((xct_rate) << AXISW_DATA_XCTRT) ;
112 
113     AXISW->CMD = (AXISW_CMD_RW_MASK |
114                  (master_port_num << AXISW_CMD_RWCHAN) |
115                  (MSS_AXISW_PEAKRT_XCTRT) |
116                  AXISW_CMD_EN_MASK);
117 
118     while(AXISW->CMD & AXISW_CMD_EN_MASK);    /*Wait for command to complete*/
119 
120     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
121 }
122 
123 /* Reads the peak rate and transaction rate value for the given master port
124 read/write address channel
125 peak_rate: returns the value of peak rate
126 xct_rate: returns the value of transaction rate
127 return value: As received form AXI_ERR_BIT in CMD register.
128 
129 */
MSS_AXISW_read_rate(mss_axisw_mport_t master_port_num,mss_axisw_rate_t * peak_rate,mss_axisw_rate_t * xct_rate)130 uint32_t MSS_AXISW_read_rate(mss_axisw_mport_t master_port_num,
131                                           mss_axisw_rate_t* peak_rate,
132                                           mss_axisw_rate_t* xct_rate)
133 {
134     uint32_t temp = 0u;
135     while(AXISW->CMD & AXISW_CMD_EN_MASK);
136 
137     AXISW->CMD &= ~(AXISW_CMD_RW_MASK);  /*Clear read/write and command EN bit*/
138 
139     AXISW->CMD = ((master_port_num << AXISW_CMD_RWCHAN) |
140                  (MSS_AXISW_PEAKRT_XCTRT) |
141                  AXISW_CMD_EN_MASK);
142 
143     while(AXISW->CMD & AXISW_CMD_EN_MASK);
144 
145     temp = AXISW->DATA;
146 
147     *peak_rate = (temp & AXISW_DATA_PEAKRT_MASK) >> AXISW_DATA_PEAKRT;
148     *xct_rate = (temp & AXISW_DATA_XCTRT_MASK) >> AXISW_DATA_XCTRT;
149 
150     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
151 }
152 
153 /* Programs the burstiness value for the given master port read/write address channel
154 
155 burstiness_val: burstiness value to be programmed
156 NOTE: Burstiness value formula as mentioned in AXISW document is Burstiness = DataReg[23:16] + 1
157 
158 regulator_en: QoS regulator Enable 1= enable, 0 = disable
159 
160 * return value: As received form AXI_ERR_BIT in CMD register.
161 */
MSS_AXISW_write_burstiness(mss_axisw_mport_t master_port_num,uint32_t burstiness_val,uint32_t regulator_en)162 int32_t MSS_AXISW_write_burstiness(mss_axisw_mport_t master_port_num,
163                                                   uint32_t burstiness_val,
164                                                   uint32_t regulator_en)
165 {
166 
167     while(AXISW->CMD & AXISW_CMD_EN_MASK);  /*make sure previous command completed*/
168 
169     /*Write burstiness value and enable burstiness regulator.
170      * Burstiness_val=0 is not valid.
171     Burstiness value formula as mentioned in AXISW document is Burstiness = DataReg[23:16] + 1*/
172 
173     if(burstiness_val == 0)
174     {
175     	return -1;
176     }
177     else
178     {
179         AXISW->DATA = ((burstiness_val - 1u) << AXISW_DATA_BURSTI) | (regulator_en & 0x01);
180     }
181 
182     AXISW->CMD = (AXISW_CMD_RW_MASK |
183                  (master_port_num << AXISW_CMD_RWCHAN) |
184                  (MSS_AXISW_BURSTINESS_EN) |
185                  AXISW_CMD_EN_MASK);
186 
187     while(AXISW->CMD & AXISW_CMD_EN_MASK);      /*Wait for command to complete*/
188 
189     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
190 }
191 
192 /* Reads the burstiness value for the given master port read/write address channel
193 
194 burstiness_val: Return parameter bit 23:16 shows the burstiness value.
195 NOTE: Burstiness value formula as mentioned in AXISW document is Burstiness = DataReg[23:16] + 1
196 
197 * return value: As received form AXI_ERR_BIT in CMD register.
198 */
MSS_AXISW_read_burstiness(mss_axisw_mport_t master_port_num,uint32_t * burstiness_val)199 uint32_t MSS_AXISW_read_burstiness(mss_axisw_mport_t master_port_num,
200                                                 uint32_t* burstiness_val)
201 {
202     while(AXISW->CMD & AXISW_CMD_EN_MASK);
203 
204     AXISW->CMD &= ~(AXISW_CMD_RW_MASK);  /*Clear read/write and command EN bit*/
205 
206     AXISW->CMD = ((master_port_num << AXISW_CMD_RWCHAN) |
207                  (MSS_AXISW_BURSTINESS_EN) |
208                  AXISW_CMD_EN_MASK);
209 
210     while(AXISW->CMD & AXISW_CMD_EN_MASK);
211 
212     *burstiness_val = ((AXISW->DATA & AXISW_DATA_BURSTI_MASK) >> AXISW_DATA_BURSTI) + 1u;
213 
214     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
215 }
216 
MSS_AXISW_write_slave_ready(mss_axisw_mport_t master_port_num,uint8_t slave_ready_en)217 uint32_t MSS_AXISW_write_slave_ready(mss_axisw_mport_t master_port_num,
218                                                    uint8_t slave_ready_en)
219 {
220     while(AXISW->CMD & AXISW_CMD_EN_MASK);  /*make sure previous command completed*/
221 
222     AXISW->DATA = slave_ready_en & 0x01;  /*only valid value of bit0*/
223 
224     AXISW->CMD = (AXISW_CMD_RW_MASK |
225                  (master_port_num << AXISW_CMD_RWCHAN) |
226                  MSS_AXISW_SLV_RDY |
227                  AXISW_CMD_EN_MASK);
228 
229     while(AXISW->CMD & AXISW_CMD_EN_MASK);    /*Wait for command to complete*/
230 
231     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
232 }
233 
234 /*Performs read operation on the AXI SWITCH APB interface,
235  * Parameters:
236  * master_port_num = AXI Master Port number. See Enum mss_axisw_mport_t above.
237  *
238  *
239  * slave_ready_en: returns the data returned by AXI SWITCH read operation for slave ready command
240  * return value: As received form AXI_ERR_BIT in CMD register.
241  *
242  */
MSS_AXISW_read_slave_ready(mss_axisw_mport_t master_port_num,uint8_t * slave_ready_en)243 uint32_t MSS_AXISW_read_slave_ready(mss_axisw_mport_t master_port_num,
244                                                   uint8_t* slave_ready_en)
245 {
246 
247     while(AXISW->CMD & AXISW_CMD_EN_MASK);
248 
249     AXISW->CMD &= ~(AXISW_CMD_RW_MASK);  /*Clear read/write bit*/
250 
251     AXISW->CMD = ((master_port_num << AXISW_CMD_RWCHAN) |
252                  (MSS_AXISW_SLV_RDY) |
253                  AXISW_CMD_EN_MASK);
254 
255     while(AXISW->CMD & AXISW_CMD_EN_MASK);
256 
257     *slave_ready_en = AXISW->DATA & 0x01;
258 
259     return ((AXISW->CMD & AXISW_CMD_ERR_MASK) >> AXISW_CMD_ERR);   /*return error bit value*/
260 }
261 
262 #ifdef __cplusplus
263 }
264 #endif
265 
266 
267