1 /*******************************************************************************
2  * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
3  *
4  */
5 /*=========================================================================*//**
6   @mainpage PolarFire MSS Frequency Meter Bare Metal Driver.
7    The MSS Clock Frequency Meter (CFM) block is used to support test of the
8    DLL's within the MSS. All functional clocks are connected to the CFM block.
9 
10    The frequency meter can be configured to measure time or frequency, time
11    allowing items such as PLL lock times to be tested and frequency to test
12    oscillator frequencies.
13 
14    Upto 8 circuit counters are implemented.
15 
16   @section intro_sec Introduction
17 
18  *//*=========================================================================*/
19 #ifndef __COREPLEX_PLATFORM_CFM_H_
20 #define __COREPLEX_PLATFORM_CFM_H_
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 
27 
28 /* CFM Register base address. */
29 #define CFM_REG_BASE 0x20006000
30 
31 /***************************************************************************//**
32   The __cfm_count_id_t enumeration is used to identify the channel used.
33  */
34 typedef enum __cfm_count_id
35 {
36     CFM_COUNT_0 = 0,
37     CFM_COUNT_1,
38     CFM_COUNT_2,
39     CFM_COUNT_3,
40     CFM_COUNT_4,
41     CFM_COUNT_5,
42     CFM_COUNT_6,
43     CFM_COUNT_7,
44     cfm_lastCH,
45 } cfm_count_id_t;
46 
47 
48 
49 /***************************************************************************//**
50   The cfm_channel_mode enumeration is used to specify the channel mode.
51  */
52 typedef enum __cfm_channel_mode
53 {
54     CFM_CH_DISABLED = 0,
55     CFM_CH_FREQUENCY_MODE,
56     CFM_CH_RESERVER,
57     CFM_CH_TIMER_MODE,
58     CFM_CH_lastmd
59 } cfm_channel_mode;
60 
61 
62 
63 typedef enum __cfm_error_id_t
64 {
65     CFM_OK = 0,
66     ERROR_INVALID_CLK_SELECTION_GROUP,
67     ERROR_INVALID_REF_SEL0,
68     ERROR_INVALID_REF_SEL1,
69     ERROR_INVALID_CHANNEL_DRIVE_CLK_MONITOR,
70     ERROR_INVALID_CFM_BUSY,
71 
72     ERROR_NULL_VALUE,
73 
74     ERROR_CFMLAST_ID
75 } cfm_error_id_t;
76 
77 
78 typedef struct _cfmRegs
79 {
80     __IO uint32_t controlReg;           /* CFM Control Register */
81     __IO uint32_t clkselReg;            /* Clock Selection Register */
82     __IO uint32_t runtimeReg;           /* Reference Count Value */
83     __IO uint32_t modelReg;             /* Sets the measurement mode */
84 
85     __I  uint32_t count0;               /* Count x value */
86     __I  uint32_t count1;
87     __I  uint32_t count2;
88     __I  uint32_t count3;
89     __I  uint32_t count4;
90     __I  uint32_t count5;
91     __I  uint32_t count6;
92     __I  uint32_t count7;
93 
94     __I  uint32_t reserved[4];          /*Reserved registers, padding structure */
95 
96 
97 }CFM;
98 
99 
100 #define CFM_REG                       ((CFM *)CFM_REG_BASE)
101 
102 typedef struct _cfmChannelMode
103 {
104     uint8_t channel0;        /* Channel x mode */
105     uint8_t channel1;        /* Channel x mode */
106     uint8_t channel2;        /* Channel x mode */
107     uint8_t channel3;        /* Channel x mode */
108     uint8_t channel4;        /* Channel x mode */
109     uint8_t channel5;        /* Channel x mode */
110     uint8_t channel6;        /* Channel x mode */
111     uint8_t channel7;        /* Channel x mode */
112 
113 }cfmChannelMode;
114 
115 #define CFM_CONTROL_REG_BUSY_MASK        0x01U
116 #define CFM_CONTROL_REG_START_MASK       0x01U
117 #define CFM_CONTROL_REG_STOP_BITS_SHIFT  0x01U
118 
119 #define CFM_CLK_SEL_MASK                 0x07U
120 
121 
122 #define CFM_CLK_REFSEL0_MASK             0x01U
123 #define CFM_CLK_REFSEL0SHIFT             0x04U
124 
125 
126 #define CFM_CLK_REFSEL1_MASK             0x01U
127 #define CFM_CLK_REFSEL1SHIFT             0x05U
128 
129 
130 #define CFM_CLK_MONSEL_MASK              0x07U
131 #define CFM_CLK_MONSEL_SHIFT             0x08U
132 
133 
134 
135 #define CFM_CLK_MONEN_MASK               0x01
136 #define CFM_CLK_MONEN_SHIFT              11U
137 
138 #define CFM_RUNTIME_REG_MASK             0xFFFFFFU
139 
140 #define CFM_CHANNEL_MODE_MASK            0x3U
141 
142 #define CFM_CH0_SHIFT_MASK           0x00U
143 #define CFM_CH1_SHIFT_MASK           0x02U
144 #define CFM_CH2_SHIFT_MASK           0x04U
145 #define CFM_CH3_SHIFT_MASK           0x06U
146 #define CFM_CH4_SHIFT_MASK           0x08U
147 #define CFM_CH5_SHIFT_MASK           0x0AU
148 #define CFM_CH6_SHIFT_MASK           0x0CU
149 #define CFM_CH7_SHIFT_MASK           0x0EU
150 
151 
152 
153 /*****************************************************************************
154  * CFM Function Prototypes
155  *******************************************************************************
156  */
157 /*-------------------------------------------------------------------------*//**
158   The MSS_CFM_control_start() function causes the measurement circuitry
159   to start. This state of 'busy' will clear which measurement is complete.
160 
161 
162   @param None
163 
164    @return
165     Busy state
166 
167   Example:
168   The following call will start the CFM
169   @code
170   MSS_CFM_control_start(  );
171   @endcode
172  */
173 uint8_t MSS_CFM_control_start(void);
174 
175 
176 
177 /*-------------------------------------------------------------------------*//**
178   The MSS_CFM_control_stop() function causes the measurement circuitry
179   to stop.
180 
181 
182   @param None
183 
184 
185   @return uint8_t
186    Returns the busy flag.
187 
188 
189   Example:
190   The following call will stop the CFM
191   @code
192   MSS_CFM_control_stop(  );
193   @endcode
194  */
195 uint8_t MSS_CFM_control_stop(void);
196 
197 
198 
199 
200 
201 /*-------------------------------------------------------------------------*//**
202   The MSS_CLF_clk_configuration() function is used to configure the clock
203   selection register.
204 
205   @param clkSel
206     Selects which group of clock inputs are selected by the channels, control
207     the input multiplexer.
208 
209   @param refsel0
210     Selects the reference input, 0=clkref1 / 1=clkref2
211 
212   @param refsel1
213     When in timer mode allows ATPG (corners) / clkref3 clock input to clock
214     the channel counters. This clock input is expected to be sourced from an
215     on-chip PLL to support at-speed testing. This allows the timer to clocked
216     off a much higher clock frequency that the reference counter that is limited
217     to 100Mhz.
218 
219   @param monSEL
220     Selects which channel drives the clock monitor output 0-7.
221 
222 
223   @param monEN
224    Enables the clock monitor output.
225 
226 
227    @return
228     cfm_error_id_t
229 
230   Example:
231   The following call will configure clk 0, using clkref1, channel zero drives
232   the clock monitor and enable the clock monitor output.
233   @code
234   MSS_GPIO_config( 0, 0, 0, 0, 1 );
235   @endcode
236  */
237 cfm_error_id_t MSS_CLF_clk_configuration(
238         uint8_t clkSel,
239         uint8_t refsel0,
240         uint8_t refsel1,
241         uint8_t monSEL,
242         uint8_t monEN
243     );
244 
245 
246 
247 
248 /*-------------------------------------------------------------------------*//**
249   The MSS_CFM_runtime_register() function is used to set how many reference
250   clock cycles the frequency and time measurement should be made.
251   The register does NOT change during oepration
252 
253   @param refcount
254     The reference count value.
255 
256  */
257 void MSS_CFM_runtime_register(
258         uint32_t  referenceCount
259     );
260 
261 
262 
263 /*-------------------------------------------------------------------------*//**
264   The MSS_CFM_channel_mode() function is used to set the measurement mode for
265   the specified channel.
266    2'b00: Disabled
267    2'b01: Frequency Mode
268    2'b11: Timer Mode
269    2'b10: Reserved
270 
271   @param cfmChannelMode
272    Configuration structure for each channel
273 
274    @return
275     None
276 
277  */
278 void MSS_CFM_channel_mode(cfmChannelMode  chMode);
279 
280 
281 /*-------------------------------------------------------------------------*//**
282   The MSS_CFM_get_count() function is used to get the count value.
283   Block must not be busy.
284 
285   @param ch
286      The channel ID to return the count for.
287 
288   @param count
289       The count for the channel register.
290 
291    @return
292     cfm_error_id_t
293 
294   Example:
295   The following call will return the value in count register. channel 0
296 
297   @code
298   MSS_CFM_get_count();
299   @endcode
300  */
301 cfm_error_id_t MSS_CFM_get_count(cfm_count_id_t ch, uint32_t *count);
302 
303 
304 #ifdef __cplusplus
305 }
306 #endif
307 
308 
309 #endif  /* __COREPLEX_PLATFORM_CFM_H_ */
310