1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #ifndef __CCM_ANALOG_IMX6SX_H__
32 #define __CCM_ANALOG_IMX6SX_H__
33 
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <stddef.h>
37 #include <assert.h>
38 #include "device_imx.h"
39 
40 /*!
41  * @addtogroup ccm_analog_driver
42  * @{
43  */
44 
45 /*******************************************************************************
46  * Definitions
47  ******************************************************************************/
48 #define CCM_ANALOG_TUPLE(reg, shift)               ((offsetof(CCM_ANALOG_Type, reg) & 0xFFFF) | ((shift) << 16))
49 #define CCM_ANALOG_TUPLE_REG_OFF(base, tuple, off) (*((volatile uint32_t *)((uint32_t)base + ((tuple) & 0xFFFF) + off)))
50 #define CCM_ANALOG_TUPLE_REG(base, tuple)          CCM_ANALOG_TUPLE_REG_OFF(base, tuple, 0)
51 #define CCM_ANALOG_TUPLE_REG_SET(base, tuple)      CCM_ANALOG_TUPLE_REG_OFF(base, tuple, 4)
52 #define CCM_ANALOG_TUPLE_REG_CLR(base, tuple)      CCM_ANALOG_TUPLE_REG_OFF(base, tuple, 8)
53 #define CCM_ANALOG_TUPLE_SHIFT(tuple)              (((tuple) >> 16) & 0x1F)
54 #define CCM_ANALOG_TUPLE_OFFSET(tuple)             ((tuple) & 0xFFFF)
55 
56 /*!
57  * @brief PLL control names for PLL power/bypass/lock/frequency operations.
58  *
59  * These constants define the PLL control names for PLL power/bypass/lock operations.\n
60  * - 0:15: REG offset to CCM_ANALOG_BASE in bytes.
61  * - 16:20: Powerdown/Power bit shift.
62  */
63 enum _ccm_analog_pll_control
64 {
65     ccmAnalogPllArmControl   = CCM_ANALOG_TUPLE(PLL_ARM, CCM_ANALOG_PLL_ARM_POWERDOWN_SHIFT),     /*!< CCM Analog ARM PLL Control.*/
66     ccmAnalogPllUsb1Control  = CCM_ANALOG_TUPLE(PLL_USB1, CCM_ANALOG_PLL_USB1_POWER_SHIFT),       /*!< CCM Analog USB1 PLL Control.*/
67     ccmAnalogPllUsb2Control  = CCM_ANALOG_TUPLE(PLL_USB2, CCM_ANALOG_PLL_USB2_POWER_SHIFT),       /*!< CCM Analog USB2 PLL Control.*/
68     ccmAnalogPllSysControl   = CCM_ANALOG_TUPLE(PLL_SYS, CCM_ANALOG_PLL_SYS_POWERDOWN_SHIFT),     /*!< CCM Analog SYSTEM PLL Control.*/
69     ccmAnalogPllAudioControl = CCM_ANALOG_TUPLE(PLL_AUDIO, CCM_ANALOG_PLL_AUDIO_POWERDOWN_SHIFT), /*!< CCM Analog AUDIO PLL Control.*/
70     ccmAnalogPllVideoControl = CCM_ANALOG_TUPLE(PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_POWERDOWN_SHIFT), /*!< CCM Analog VIDEO PLL Control.*/
71     ccmAnalogPllEnetControl  = CCM_ANALOG_TUPLE(PLL_ENET, CCM_ANALOG_PLL_ENET_POWERDOWN_SHIFT),   /*!< CCM Analog ETHERNET PLL Control.*/
72 };
73 
74 /*!
75  * @brief PLL clock names for clock enable/disable settings.
76  *
77  * These constants define the PLL clock names for PLL clock enable/disable operations.\n
78  * - 0:15: REG offset to CCM_ANALOG_BASE in bytes.
79  * - 16:20: Clock enable bit shift.
80  */
81 enum _ccm_analog_pll_clock
82 {
83     ccmAnalogPllArmClock         = CCM_ANALOG_TUPLE(PLL_ARM, CCM_ANALOG_PLL_ARM_ENABLE_SHIFT),            /*!< CCM Analog ARM PLL Clock.*/
84     ccmAnalogPllUsb1Clock        = CCM_ANALOG_TUPLE(PLL_USB1, CCM_ANALOG_PLL_USB1_ENABLE_SHIFT),          /*!< CCM Analog USB1 PLL Clock.*/
85     ccmAnalogPllUsb2Clock        = CCM_ANALOG_TUPLE(PLL_USB2, CCM_ANALOG_PLL_USB2_ENABLE_SHIFT),          /*!< CCM Analog USB2 PLL Clock.*/
86     ccmAnalogPllSysClock         = CCM_ANALOG_TUPLE(PLL_SYS, CCM_ANALOG_PLL_SYS_ENABLE_SHIFT),            /*!< CCM Analog SYSTEM PLL Clock.*/
87     ccmAnalogPllAudioClock       = CCM_ANALOG_TUPLE(PLL_AUDIO, CCM_ANALOG_PLL_AUDIO_ENABLE_SHIFT),        /*!< CCM Analog AUDIO PLL Clock.*/
88     ccmAnalogPllVideoClock       = CCM_ANALOG_TUPLE(PLL_VIDEO, CCM_ANALOG_PLL_VIDEO_ENABLE_SHIFT),        /*!< CCM Analog VIDEO PLL Clock.*/
89     ccmAnalogPllEnetClock25Mhz   = CCM_ANALOG_TUPLE(PLL_ENET, CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_SHIFT), /*!< CCM Analog ETHERNET 25MHz PLL Clock.*/
90     ccmAnalogPllEnet2Clock125Mhz = CCM_ANALOG_TUPLE(PLL_ENET, CCM_ANALOG_PLL_ENET_ENET2_125M_EN_SHIFT),   /*!< CCM Analog ETHERNET2 125MHz PLL Clock.*/
91     ccmAnalogPllEnet1Clock125Mhz = CCM_ANALOG_TUPLE(PLL_ENET, CCM_ANALOG_PLL_ENET_ENET1_125M_EN_SHIFT),   /*!< CCM Analog ETHERNET1 125MHz PLL Clock.*/
92 };
93 
94 /*!
95  * @brief PFD gate names for clock gate settings, clock source is PLL2 and PLL3
96  *
97  * These constants define the PFD gate names for PFD clock enable/disable operations.\n
98  * - 0:15: REG offset to CCM_ANALOG_BASE in bytes.
99  * - 16:20: Clock gate bit shift.
100  */
101 enum _ccm_analog_pfd_clkgate
102 {
103     ccmAnalogPll2Pfd0ClkGate = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD0_CLKGATE_SHIFT), /*!< CCM Analog PLL2 PFD0 Clock Gate.*/
104     ccmAnalogPll2Pfd1ClkGate = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD1_CLKGATE_SHIFT), /*!< CCM Analog PLL2 PFD1 Clock Gate.*/
105     ccmAnalogPll2Pfd2ClkGate = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD2_CLKGATE_SHIFT), /*!< CCM Analog PLL2 PFD2 Clock Gate.*/
106     ccmAnalogPll2Pfd3ClkGate = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD3_CLKGATE_SHIFT), /*!< CCM Analog PLL2 PFD3 Clock Gate.*/
107     ccmAnalogPll3Pfd0ClkGate = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD0_CLKGATE_SHIFT), /*!< CCM Analog PLL3 PFD0 Clock Gate.*/
108     ccmAnalogPll3Pfd1ClkGate = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD1_CLKGATE_SHIFT), /*!< CCM Analog PLL3 PFD1 Clock Gate.*/
109     ccmAnalogPll3Pfd2ClkGate = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD2_CLKGATE_SHIFT), /*!< CCM Analog PLL3 PFD2 Clock Gate.*/
110     ccmAnalogPll3Pfd3ClkGate = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD3_CLKGATE_SHIFT), /*!< CCM Analog PLL3 PFD3 Clock Gate.*/
111 };
112 
113 /*!
114  * @brief PFD fraction names for clock fractional divider operations.
115  *
116  * These constants define the PFD fraction names for PFD fractional divider operations.\n
117  * - 0:15: REG offset to CCM_ANALOG_BASE in bytes.
118  * - 16:20: Fraction bits shift
119  */
120 enum _ccm_analog_pfd_frac
121 {
122     ccmAnalogPll2Pfd0Frac = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD0_FRAC_SHIFT), /*!< CCM Analog PLL2 PFD0 fractional divider.*/
123     ccmAnalogPll2Pfd1Frac = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD1_FRAC_SHIFT), /*!< CCM Analog PLL2 PFD1 fractional divider.*/
124     ccmAnalogPll2Pfd2Frac = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD2_FRAC_SHIFT), /*!< CCM Analog PLL2 PFD2 fractional divider.*/
125     ccmAnalogPll2Pfd3Frac = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD3_FRAC_SHIFT), /*!< CCM Analog PLL2 PFD3 fractional divider.*/
126     ccmAnalogPll3Pfd0Frac = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD0_FRAC_SHIFT), /*!< CCM Analog PLL3 PFD0 fractional divider.*/
127     ccmAnalogPll3Pfd1Frac = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD1_FRAC_SHIFT), /*!< CCM Analog PLL3 PFD1 fractional divider.*/
128     ccmAnalogPll3Pfd2Frac = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD2_FRAC_SHIFT), /*!< CCM Analog PLL3 PFD2 fractional divider.*/
129     ccmAnalogPll3Pfd3Frac = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD3_FRAC_SHIFT), /*!< CCM Analog PLL3 PFD3 fractional divider.*/
130 };
131 
132 /*!
133  * @brief PFD stable names for clock stable query
134  *
135  * These constants define the PFD stable names for clock stable query.\n
136  * - 0:15: REG offset to CCM_ANALOG_BASE in bytes.
137  * - 16:20: Stable bit shift.
138  */
139 enum _ccm_analog_pfd_stable
140 {
141     ccmAnalogPll2Pfd0Stable = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD0_STABLE_SHIFT), /*!< CCM Analog PLL2 PFD0 clock stable query.*/
142     ccmAnalogPll2Pfd1Stable = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD1_STABLE_SHIFT), /*!< CCM Analog PLL2 PFD1 clock stable query.*/
143     ccmAnalogPll2Pfd2Stable = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD2_STABLE_SHIFT), /*!< CCM Analog PLL2 PFD2 clock stable query.*/
144     ccmAnalogPll2Pfd3Stable = CCM_ANALOG_TUPLE(PFD_528, CCM_ANALOG_PFD_528_PFD3_STABLE_SHIFT), /*!< CCM Analog PLL2 PFD3 clock stable query.*/
145     ccmAnalogPll3Pfd0Stable = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD0_STABLE_SHIFT), /*!< CCM Analog PLL3 PFD0 clock stable query.*/
146     ccmAnalogPll3Pfd1Stable = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD1_STABLE_SHIFT), /*!< CCM Analog PLL3 PFD1 clock stable query.*/
147     ccmAnalogPll3Pfd2Stable = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD2_STABLE_SHIFT), /*!< CCM Analog PLL3 PFD2 clock stable query.*/
148     ccmAnalogPll3Pfd3Stable = CCM_ANALOG_TUPLE(PFD_480, CCM_ANALOG_PFD_480_PFD3_STABLE_SHIFT), /*!< CCM Analog PLL3 PFD3 clock stable query.*/
149 };
150 
151 /*******************************************************************************
152  * API
153  ******************************************************************************/
154 
155 #if defined(__cplusplus)
156 extern "C" {
157 #endif
158 
159 /*!
160  * @name CCM Analog PLL Operation Functions
161  * @{
162  */
163 
164 /*!
165  * @brief Power up PLL
166  *
167  * @param base CCM_ANALOG base pointer.
168  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
169  */
170 void CCM_ANALOG_PowerUpPll(CCM_ANALOG_Type * base, uint32_t pllControl);
171 
172 /*!
173  * @brief Power down PLL
174  *
175  * @param base CCM_ANALOG base pointer.
176  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
177  */
178 void CCM_ANALOG_PowerDownPll(CCM_ANALOG_Type * base, uint32_t pllControl);
179 
180 /*!
181  * @brief PLL bypass setting
182  *
183  * @param base CCM_ANALOG base pointer.
184  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
185  * @param bypass Bypass the PLL.
186  *               - true: Bypass the PLL.
187  *               - false: Do not bypass the PLL.
188  */
189 void CCM_ANALOG_SetPllBypass(CCM_ANALOG_Type * base, uint32_t pllControl, bool bypass);
190 
191 /*!
192  * @brief Check if PLL is bypassed
193  *
194  * @param base CCM_ANALOG base pointer.
195  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
196  * @return PLL bypass status.
197  *             - true: The PLL is bypassed.
198  *             - false: The PLL is not bypassed.
199  */
CCM_ANALOG_IsPllBypassed(CCM_ANALOG_Type * base,uint32_t pllControl)200 static inline bool CCM_ANALOG_IsPllBypassed(CCM_ANALOG_Type * base, uint32_t pllControl)
201 {
202     return (bool)(CCM_ANALOG_TUPLE_REG(base, pllControl) & CCM_ANALOG_PLL_ARM_BYPASS_MASK);
203 }
204 
205 /*!
206  * @brief Check if PLL clock is locked
207  *
208  * @param base CCM_ANALOG base pointer.
209  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
210  * @return PLL lock status.
211  *         - true: The PLL is locked.
212  *         - false: The PLL is not locked.
213  */
CCM_ANALOG_IsPllLocked(CCM_ANALOG_Type * base,uint32_t pllControl)214 static inline bool CCM_ANALOG_IsPllLocked(CCM_ANALOG_Type * base, uint32_t pllControl)
215 {
216     return (bool)(CCM_ANALOG_TUPLE_REG(base, pllControl) & CCM_ANALOG_PLL_ARM_LOCK_MASK);
217 }
218 
219 /*!
220  * @brief Enable PLL clock
221  *
222  * @param base CCM_ANALOG base pointer.
223  * @param pllClock PLL clock name (see @ref _ccm_analog_pll_clock enumeration)
224  */
CCM_ANALOG_EnablePllClock(CCM_ANALOG_Type * base,uint32_t pllClock)225 static inline void CCM_ANALOG_EnablePllClock(CCM_ANALOG_Type * base, uint32_t pllClock)
226 {
227     CCM_ANALOG_TUPLE_REG_SET(base, pllClock) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllClock);
228 }
229 
230 /*!
231  * @brief Disable PLL clock
232  *
233  * @param base CCM_ANALOG base pointer.
234  * @param pllClock PLL clock name (see @ref _ccm_analog_pll_clock enumeration)
235  */
CCM_ANALOG_DisablePllClock(CCM_ANALOG_Type * base,uint32_t pllClock)236 static inline void CCM_ANALOG_DisablePllClock(CCM_ANALOG_Type * base, uint32_t pllClock)
237 {
238     CCM_ANALOG_TUPLE_REG_CLR(base, pllClock) = 1 << CCM_ANALOG_TUPLE_SHIFT(pllClock);
239 }
240 
241 /*!
242  * @brief Get PLL(involved all PLLs) clock frequency.
243  *
244  * @param base CCM_ANALOG base pointer.
245  * @param pllControl PLL control name (see @ref _ccm_analog_pll_control enumeration)
246  * @return PLL clock frequency in HZ.
247  */
248 uint32_t CCM_ANALOG_GetPllFreq(CCM_ANALOG_Type * base, uint32_t pllControl);
249 
250 /*@}*/
251 
252 /*!
253  * @name CCM Analog PFD Operation Functions
254  * @{
255  */
256 
257 /*!
258  * @brief Enable PFD clock
259  *
260  * @param base CCM_ANALOG base pointer.
261  * @param pfdClkGate PFD clock gate (see @ref _ccm_analog_pfd_clkgate enumeration)
262  */
CCM_ANALOG_EnablePfdClock(CCM_ANALOG_Type * base,uint32_t pfdClkGate)263 static inline void CCM_ANALOG_EnablePfdClock(CCM_ANALOG_Type * base, uint32_t pfdClkGate)
264 {
265     CCM_ANALOG_TUPLE_REG_CLR(base, pfdClkGate) = 1 << CCM_ANALOG_TUPLE_SHIFT(pfdClkGate);
266 }
267 
268 /*!
269  * @brief Disable PFD clock
270  *
271  * @param base CCM_ANALOG base pointer.
272  * @param pfdClkGate PFD clock gate (see @ref _ccm_analog_pfd_clkgate enumeration)
273  */
CCM_ANALOG_DisablePfdClock(CCM_ANALOG_Type * base,uint32_t pfdClkGate)274 static inline void CCM_ANALOG_DisablePfdClock(CCM_ANALOG_Type * base, uint32_t pfdClkGate)
275 {
276     CCM_ANALOG_TUPLE_REG_SET(base, pfdClkGate) = 1 << CCM_ANALOG_TUPLE_SHIFT(pfdClkGate);
277 }
278 
279 /*!
280  * @brief Check if PFD clock is stable
281  *
282  * @param base CCM_ANALOG base pointer.
283  * @param pfdStable PFD stable identifier (see @ref _ccm_analog_pfd_stable enumeration)
284  * @return PFD clock stable status.
285  *         - true: The PFD clock is stable.
286  *         - false: The PFD clock is not stable.
287  */
CCM_ANALOG_IsPfdStable(CCM_ANALOG_Type * base,uint32_t pfdStable)288 static inline bool CCM_ANALOG_IsPfdStable(CCM_ANALOG_Type * base, uint32_t pfdStable)
289 {
290     return (bool)(CCM_ANALOG_TUPLE_REG(base, pfdStable) & (1 << CCM_ANALOG_TUPLE_SHIFT(pfdStable)));
291 }
292 
293 
294 /*!
295  * @brief Set PFD clock fraction
296  *
297  * @param base CCM_ANALOG base pointer.
298  * @param pfdFrac PFD clock fraction (see @ref _ccm_analog_pfd_frac enumeration)
299  * @param value PFD clock fraction value
300  */
CCM_ANALOG_SetPfdFrac(CCM_ANALOG_Type * base,uint32_t pfdFrac,uint32_t value)301 static inline void CCM_ANALOG_SetPfdFrac(CCM_ANALOG_Type * base, uint32_t pfdFrac, uint32_t value)
302 {
303     assert(value >= 12 && value <= 35);
304     CCM_ANALOG_TUPLE_REG_CLR(base, pfdFrac) = CCM_ANALOG_PFD_480_CLR_PFD0_FRAC_MASK << CCM_ANALOG_TUPLE_SHIFT(pfdFrac);
305     CCM_ANALOG_TUPLE_REG_SET(base, pfdFrac) = value << CCM_ANALOG_TUPLE_SHIFT(pfdFrac);
306 }
307 
308 /*!
309  * @brief Get PFD clock fraction
310  *
311  * @param base CCM_ANALOG base pointer.
312  * @param pfdFrac PFD clock fraction (see @ref _ccm_analog_pfd_frac enumeration)
313  * @return PFD clock fraction value
314  */
CCM_ANALOG_GetPfdFrac(CCM_ANALOG_Type * base,uint32_t pfdFrac)315 static inline uint32_t CCM_ANALOG_GetPfdFrac(CCM_ANALOG_Type * base, uint32_t pfdFrac)
316 {
317     return (CCM_ANALOG_TUPLE_REG(base, pfdFrac) >> CCM_ANALOG_TUPLE_SHIFT(pfdFrac)) & CCM_ANALOG_PFD_480_CLR_PFD0_FRAC_MASK;
318 }
319 
320 /*!
321  * @brief Get PFD clock frequency
322  *
323  * @param base CCM_ANALOG base pointer.
324  * @param pfdFrac PFD clock fraction (see @ref _ccm_analog_pfd_frac enumeration)
325  * @return PFD clock frequency in HZ
326  */
327 uint32_t CCM_ANALOG_GetPfdFreq(CCM_ANALOG_Type * base, uint32_t pfdFrac);
328 
329 /*@}*/
330 
331 #if defined(__cplusplus)
332 }
333 #endif
334 
335 /*! @}*/
336 
337 #endif /* __CCM_ANALOG_IMX6SX_H__ */
338 /*******************************************************************************
339  * EOF
340  ******************************************************************************/
341