1df5a00840c3d0bce3933a222e83a88f98e2d0e6
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / family / vayu / gptimers.c
1 /*
2  * Copyright (c) 2014, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /* Standard headers */
34 #include <ti/syslink/Std.h>
36 /*QNX specific header include */
37 #include <errno.h>
38 #include <unistd.h>
39 #include <stdbool.h>
41 #include <hw/inout.h>
42 #include <sys/mman.h>
44 #include <gptimers.h>
47 /* Start a software forced wake-up */
48 #define SW_WKUP                           0x2
50 /* Start a software forced wake-up */
51 #define HW_AUTO                           0x3
53 /* Explicitly enable a module */
54 #define MOD_ENABLE                        0x2
56 /* Disable a module */
57 #define MOD_DISABLE                       0xFFFFFFFC
59 /*
60  * Empirically determined delay that is necessary between when the clock domain
61  * is enabled and when the status bit is updated
62  */
63 #define DELAY                             100
65 /* Module idle status mask */
66 #define IDLEST_MASK                       0x30000
68 /* Module mode mask */
69 #define MODULEMODE_MASK                   0x3
71 /* Registers for clock management of timers in IPU power domain */
72 #define CM_CORE_AON__IPU_SIZE             0x100
73 #define CM_CORE_AON__IPU_BASE             0x4A005500
74 #define CM_IPU_CLKSTCTRL_OFFSET           0x40
75 #define CM_IPU_TIMER5_CLKCTRL_OFFSET      0x58
76 #define CM_IPU_TIMER6_CLKCTRL_OFFSET      0x60
77 #define CM_IPU_TIMER7_CLKCTRL_OFFSET      0x68
78 #define CM_IPU_TIMER8_CLKCTRL_OFFSET      0x70
80 /*
81  * Defines the state object, which contains all the module
82  * specific information.
83  */
84 struct gpt_module_object {
85     uintptr_t cmCoreAonBaseVa;
86     /* base address to CM_CORE_AON__IPU */
87     bool isSetup;
88     /* Indicates whether the ipu_pm module is setup. */
89 };
91 static struct gpt_module_object gptState = {
92     .cmCoreAonBaseVa = NULL,
93     .isSetup = false
94 };
96 /* Enable a particular timer by setting its module mode */
97 static int enable(uintptr_t reg)
98 {
99     int max_tries = DELAY;
101     out32(reg, MOD_ENABLE);
102     do {
103         if (!(in32(reg) & IDLEST_MASK)) {
104             break;
105         }
106     } while (--max_tries);
108     if (max_tries == 0) {
109         return -EIO;
110     }
111     else {
112         return EOK;
113     }
116 /* Disable a particular timer by setting its module mode */
117 static int disable(uintptr_t reg)
119     uint32_t value = 0;
121     /*Check if Clock is Enabled*/
122     value = in32(reg);
123     if ((value & MODULEMODE_MASK) == MOD_ENABLE) {
124         /*Disable the Timer*/
125         value &= MOD_DISABLE;
126         out32(reg, value);
127     }
129     return EOK;
132 /* Enable GP timers (only the ones in PD_IPU for now) */
133 static int gpt_enable()
135     /* make sure abe clock domain is enabled as it is source for gpt5-8 */
136     out32((uintptr_t)(gptState.cmCoreAonBaseVa + CM_IPU_CLKSTCTRL_OFFSET),
137         SW_WKUP);
139     /* Set module mode for each timer */
140     if (enable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER5_CLKCTRL_OFFSET)
141         != EOK) {
142         return -EIO;
143     }
145     if (enable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER6_CLKCTRL_OFFSET)
146         != EOK) {
147         return -EIO;
148     }
150     if (enable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER7_CLKCTRL_OFFSET)
151         != EOK) {
152         return -EIO;
153     }
155     if (enable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER8_CLKCTRL_OFFSET)
156         != EOK) {
157         return -EIO;
158     }
160     return EOK;
163 /* Disable GP timers (only the ones in PD_IPU for now) */
164 static int gpt_disable()
166     disable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER5_CLKCTRL_OFFSET);
167     disable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER6_CLKCTRL_OFFSET);
168     disable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER7_CLKCTRL_OFFSET);
169     disable(gptState.cmCoreAonBaseVa + CM_IPU_TIMER8_CLKCTRL_OFFSET);
171     /* put abe clock domain back to HW_AUTO mode */
172     out32((uintptr_t)(gptState.cmCoreAonBaseVa + CM_IPU_CLKSTCTRL_OFFSET),
173         HW_AUTO);
175     return EOK;
178 /* Setup module */
179 int gpt_setup()
181     int retval = EOK;
183     if (gptState.isSetup == false) {
184         gptState.cmCoreAonBaseVa = (uintptr_t)mmap_device_io(
185             CM_CORE_AON__IPU_SIZE, CM_CORE_AON__IPU_BASE);
186         if((uintptr_t)gptState.cmCoreAonBaseVa == MAP_DEVICE_FAILED) {
187             gptState.cmCoreAonBaseVa = NULL;
188             retval = -errno;
189             goto exit;
190         }
192         gpt_enable();
194         gptState.isSetup = true;
195     }
197 exit:
198     if (retval != EOK) {
199         gpt_disable();
201         if (gptState.cmCoreAonBaseVa) {
202             munmap((void *)gptState.cmCoreAonBaseVa, CM_CORE_AON__IPU_SIZE);
203             gptState.cmCoreAonBaseVa = NULL;
204         }
205     }
206     return retval;
209 /* Finalize module */
210 int gpt_destroy()
212     if (gptState.isSetup) {
213         gpt_disable();
215         if (gptState.cmCoreAonBaseVa) {
216             munmap((void *)gptState.cmCoreAonBaseVa, CM_CORE_AON__IPU_SIZE);
217             gptState.cmCoreAonBaseVa = NULL;
218         }
220         gptState.isSetup = false;
221     }
222     return EOK;