]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4_ATSAM4L_Atmel_Studio/src/asf/common/services/clock/sam4l/dfll.c
Add SAM4L demo.
[freertos] / FreeRTOS / Demo / CORTEX_M4_ATSAM4L_Atmel_Studio / src / asf / common / services / clock / sam4l / dfll.c
1 /**\r
2  * \file\r
3  *\r
4  * \brief Chip-specific DFLL implementation\r
5  *\r
6  * Copyright (c) 2012 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * \page License\r
11  *\r
12  * Redistribution and use in source and binary forms, with or without\r
13  * modification, are permitted provided that the following conditions are met:\r
14  *\r
15  * 1. Redistributions of source code must retain the above copyright notice,\r
16  *    this list of conditions and the following disclaimer.\r
17  *\r
18  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
19  *    this list of conditions and the following disclaimer in the documentation\r
20  *    and/or other materials provided with the distribution.\r
21  *\r
22  * 3. The name of Atmel may not be used to endorse or promote products derived\r
23  *    from this software without specific prior written permission.\r
24  *\r
25  * 4. This software may only be redistributed and used in connection with an\r
26  *    Atmel microcontroller product.\r
27  *\r
28  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
29  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
31  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
32  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
37  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
38  * POSSIBILITY OF SUCH DAMAGE.\r
39  *\r
40  * \asf_license_stop\r
41  *\r
42  */\r
43 #include <compiler.h>\r
44 #include <dfll.h>\r
45 \r
46 #define dfll_write_reg(reg, value) \\r
47         do { \\r
48                 while (!(SCIF->SCIF_PCLKSR & SCIF_PCLKSR_DFLL0RDY));                 \\r
49                 irqflags_t ATPASTE2(dfll_flags, __LINE__) = cpu_irq_save();          \\r
50                 SCIF->SCIF_UNLOCK = SCIF_UNLOCK_KEY(0xAAUL)                          \\r
51                         | SCIF_UNLOCK_ADDR((uint32_t)&SCIF->SCIF_##reg - (uint32_t)SCIF);\\r
52                 SCIF->SCIF_##reg = (value);                                          \\r
53                 cpu_irq_restore(ATPASTE2(dfll_flags, __LINE__));                     \\r
54         } while (0)\r
55 \r
56 \r
57 \r
58 void dfll_enable_open_loop(const struct dfll_config *cfg, uint32_t dfll_id)\r
59 {\r
60         irqflags_t flags;\r
61 \r
62         UNUSED(dfll_id);\r
63 \r
64         /* First, enable the DFLL, then configure it */\r
65         flags = cpu_irq_save();\r
66         SCIF->SCIF_UNLOCK = SCIF_UNLOCK_KEY(0xAAUL)\r
67                 | SCIF_UNLOCK_ADDR((uint32_t)&SCIF->SCIF_DFLL0CONF - (uint32_t)SCIF);\r
68         SCIF->SCIF_DFLL0CONF = SCIF_DFLL0CONF_EN;\r
69         cpu_irq_restore(flags);\r
70         dfll_write_reg(DFLL0CONF, cfg->conf | SCIF_DFLL0CONF_EN);\r
71         dfll_write_reg(DFLL0MUL, cfg->mul);\r
72         dfll_write_reg(DFLL0VAL, cfg->val);\r
73         dfll_write_reg(DFLL0SSG, cfg->ssg);\r
74 }\r
75 \r
76 void dfll_disable_open_loop(uint32_t dfll_id)\r
77 {\r
78         UNUSED(dfll_id);\r
79 \r
80         /* First, disable the DFLL. */\r
81         // Do a sync before reading a dfll conf register\r
82         SCIF->SCIF_DFLL0SYNC = SCIF_DFLL0SYNC_SYNC;\r
83         while (!(SCIF->SCIF_PCLKSR & SCIF_PCLKSR_DFLL0RDY));\r
84 \r
85         uint32_t conf = SCIF->SCIF_DFLL0CONF;\r
86         conf &= ~SCIF_DFLL0CONF_EN;\r
87         dfll_write_reg(DFLL0CONF, conf);\r
88 \r
89         /* Finally, stop the reference clock */\r
90         genclk_disable(0);\r
91 }\r
92 \r
93 void dfll_enable_closed_loop(const struct dfll_config *cfg, uint32_t dfll_id)\r
94 {\r
95         irqflags_t flags;\r
96 \r
97         UNUSED(dfll_id);\r
98 \r
99         /* Enable the reference clock */\r
100         genclk_enable(&cfg->ref_cfg, 0);\r
101 \r
102         /*\r
103          * Enable the DFLL first, but don't wait for the DFLL0RDY bit\r
104          * because if the DFLL has been disabled before, the DFLL0RDY\r
105          * bit stays cleared until it is re-enabled.\r
106          */\r
107         flags = cpu_irq_save();\r
108         SCIF->SCIF_UNLOCK = SCIF_UNLOCK_KEY(0xAAUL)\r
109                 | SCIF_UNLOCK_ADDR((uint32_t)&SCIF->SCIF_DFLL0CONF - (uint32_t)SCIF);\r
110         SCIF->SCIF_DFLL0CONF = SCIF_DFLL0CONF_EN;\r
111         cpu_irq_restore(flags);\r
112 \r
113         /*\r
114          * Then, configure the DFLL, taking care to wait for the\r
115          * DFLL0RDY bit before every step.\r
116          */\r
117         dfll_write_reg(DFLL0STEP, cfg->step);\r
118         dfll_write_reg(DFLL0MUL, cfg->mul);\r
119         dfll_write_reg(DFLL0SSG, cfg->ssg);\r
120         dfll_write_reg(DFLL0CONF, cfg->conf | SCIF_DFLL0CONF_EN);\r
121 }\r
122 \r
123 void dfll_disable_closed_loop(uint32_t dfll_id)\r
124 {\r
125         UNUSED(dfll_id);\r
126 \r
127         /* First, disable the DFLL. */\r
128         // Do a sync before reading a dfll conf register\r
129         SCIF->SCIF_DFLL0SYNC = SCIF_DFLL0SYNC_SYNC;\r
130         while (!(SCIF->SCIF_PCLKSR & SCIF_PCLKSR_DFLL0RDY));\r
131 \r
132         uint32_t conf = SCIF->SCIF_DFLL0CONF;\r
133         conf &= ~SCIF_DFLL0CONF_EN;\r
134         dfll_write_reg(DFLL0CONF, conf);\r
135 \r
136         /* Finally, stop the reference clock */\r
137         genclk_disable(0);\r
138 }\r
139 \r
140 void dfll_enable_config_defaults(uint32_t dfll_id)\r
141 {\r
142 #ifdef CONFIG_DFLL0_SOURCE\r
143         struct dfll_config dfllcfg;\r
144 #endif\r
145         static bool open_loop_done = false;\r
146 \r
147         if(SCIF->SCIF_DFLL0CONF & SCIF_DFLL0CONF_MODE) {\r
148                 // Closed-loop mode\r
149                 if (dfll_is_fine_locked(dfll_id)) {\r
150                         return; // DFLL already running\r
151                 }\r
152         }\r
153         if (open_loop_done == true) {\r
154                 return;\r
155         }\r
156 \r
157         switch (dfll_id) {\r
158 #ifdef CONFIG_DFLL0_SOURCE\r
159         case 0:\r
160                 dfll_enable_source(CONFIG_DFLL0_SOURCE);\r
161                 dfll_config_init_closed_loop_mode(&dfllcfg,\r
162                         CONFIG_DFLL0_SOURCE,\r
163                         CONFIG_DFLL0_DIV,\r
164                         CONFIG_DFLL0_MUL);\r
165 \r
166                 dfll_enable_closed_loop(&dfllcfg, dfll_id);\r
167                 while (!dfll_is_fine_locked(dfll_id));\r
168                 break;\r
169 #endif\r
170 \r
171         default:\r
172                 Assert(false);\r
173                 break;\r
174         }\r
175 }\r