move ifxmips uboot to package/
[openwrt.git] / package / uboot-ifxmips / files / cpu / mips / danube / ifx_cgu.c
1 /*\r
2  * ########################################################################\r
3  *\r
4  *  This program is free software; you can distribute it and/or modify it\r
5  *  under the terms of the GNU General Public License (Version 2) as\r
6  *  published by the Free Software Foundation.\r
7  *\r
8  *  This program is distributed in the hope it will be useful, but WITHOUT\r
9  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
10  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
11  *  for more details.\r
12  *\r
13  *  You should have received a copy of the GNU General Public License along\r
14  *  with this program; if not, write to the Free Software Foundation, Inc.,\r
15  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.\r
16  *\r
17  * ########################################################################\r
18  *\r
19  * danube_cgu.c\r
20  *\r
21  *  Description:\r
22  *    device driver of clock generation unit of Danube chip\r
23  *  Author:\r
24  *    Samuels Xu Liang\r
25  *  Created:\r
26  *    19 Jul 2005\r
27  *  History & Modification Tag:\r
28  *  ___________________________________________________________________________\r
29  *  |  Tag   |                  Comments                   | Modifier & Time  |\r
30  *  |--------+---------------------------------------------+------------------|\r
31  *  |  S0.0  | First version of this driver and the tag is | Samuels Xu Liang |\r
32  *  |        | implied.                                    |   19 Jul 2005    |\r
33  *  ---------------------------------------------------------------------------\r
34  *\r
35  */\r
36 \r
37 \r
38 /*\r
39  * ####################################\r
40  *              Head File\r
41  * ####################################\r
42  */\r
43 \r
44 /*\r
45  *  Common Head File\r
46  */\r
47 #include <linux/config.h>\r
48 #include <linux/kernel.h>\r
49 #include <linux/module.h>\r
50 #include <linux/version.h>\r
51 #include <linux/types.h>\r
52 #include <linux/fs.h>\r
53 #include <linux/miscdevice.h>\r
54 #include <linux/init.h>\r
55 #include <asm/uaccess.h>\r
56 #include <asm/unistd.h>\r
57 #include <asm/irq.h>\r
58 #include <linux/errno.h>\r
59 \r
60 /*\r
61  *  Chip Specific Head File\r
62  */\r
63 #include "ifx_cgu.h"\r
64 \r
65 \r
66 /*\r
67  * ####################################\r
68  *              Definition\r
69  * ####################################\r
70  */\r
71 \r
72 #define DEBUG_ON_AMAZON                 1\r
73 #define DEBUG_PRINT_INFO                1\r
74 \r
75 /*\r
76  *  Frequency of Clock Direct Feed from The Analog Line Driver Chip\r
77  */\r
78 #define BASIC_INPUT_CLOCK_FREQUENCY     35328000\r
79 \r
80 /*\r
81  *  Bits Operation\r
82  */\r
83 #define GET_BITS(x, msb, lsb)           (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))\r
84 #define SET_BITS(x, msb, lsb, value)    (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))\r
85 \r
86 /*\r
87  *  CGU Register Mapping\r
88  */\r
89 #define DANUBE_CGU                      (KSEG1 + 0x1F103000)\r
90 #define DANUBE_CGU_DIV                  ((volatile u32*)(DANUBE_CGU + 0x0000))\r
91 #define DANUBE_CGU_PLL_NMK0             ((volatile u32*)(DANUBE_CGU + 0x0004))\r
92 #define DANUBE_CGU_PLL_SR0              ((volatile u32*)(DANUBE_CGU + 0x0008))\r
93 #define DANUBE_CGU_PLL_NMK1             ((volatile u32*)(DANUBE_CGU + 0x000C))\r
94 #define DANUBE_CGU_PLL_SR1              ((volatile u32*)(DANUBE_CGU + 0x0010))\r
95 #define DANUBE_CGU_PLL_SR2              ((volatile u32*)(DANUBE_CGU + 0x0014))\r
96 #define DANUBE_CGU_IF_CLK               ((volatile u32*)(DANUBE_CGU + 0x0018))\r
97 #define DANUBE_CGU_OSC_CTRL             ((volatile u32*)(DANUBE_CGU + 0x001C))\r
98 #define DANUBE_CGU_SMD                  ((volatile u32*)(DANUBE_CGU + 0x0020))\r
99 #define DANUBE_CGU_CRD                  ((volatile u32*)(DANUBE_CGU + 0x0024))\r
100 #define DANUBE_CGU_CT1SR                ((volatile u32*)(DANUBE_CGU + 0x0028))\r
101 #define DANUBE_CGU_CT2SR                ((volatile u32*)(DANUBE_CGU + 0x002C))\r
102 #define DANUBE_CGU_PCMCR                ((volatile u32*)(DANUBE_CGU + 0x0030))\r
103 #define DANUBE_CGU_MUX                  ((volatile u32*)(DANUBE_CGU + 0x0034))\r
104 \r
105 /*\r
106  *  CGU Divider Register\r
107  */\r
108 #define CGU_DIV_SFTR                    (*DANUBE_CGU_DIV & (1 << 31))\r
109 #define CGU_DIV_DIVE                    (*DANUBE_CGU_DIV & (1 << 16))\r
110 #define CGU_DIV_IOR                     GET_BITS(*DANUBE_CGU_DIV, 5, 4)\r
111 #define CGU_DIV_FKS                     GET_BITS(*DANUBE_CGU_DIV, 3, 2)\r
112 #define CGU_DIV_FBS                     GET_BITS(*DANUBE_CGU_DIV, 1, 0)\r
113 \r
114 /*\r
115  *  CGU PLL0 NMK Register\r
116  */\r
117 #define CGU_PLL_NMK0_PLLN               ((*DANUBE_CGU_PLL_NMK0 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24)\r
118 #define CGU_PLL_NMK0_PLLM               GET_BITS(*DANUBE_CGU_PLL_NMK0, 23, 20)\r
119 #define CGU_PLL_NMK0_PLLK               GET_BITS(*DANUBE_CGU_PLL_NMK0, 19, 0)\r
120 \r
121 /*\r
122  *  CGU PLL0 Status Register\r
123  */\r
124 #define CGU_PLL_SR0_PLLDIV              ((*DANUBE_CGU_PLL_SR0 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)\r
125 #define CGU_PLL_SR0_PLLDEN              (*DANUBE_CGU_PLL_SR0 & (1 << 26))\r
126 #define CGU_PLL_SR0_PLLPSE              GET_BITS(*DANUBE_CGU_PLL_SR0, 5, 4)\r
127 #define CGU_PLL_SR0_PLLB                (*DANUBE_CGU_PLL_SR0 & (1 << 2))\r
128 #define CGU_PLL_SR0_PLLL                (*DANUBE_CGU_PLL_SR0 & (1 << 1))\r
129 #define CGU_PLL_SR0_PLLEN               (*DANUBE_CGU_PLL_SR0 & (1 << 0))\r
130 \r
131 #define CGU_PLL_SR0_DSMSEL              1\r
132 #define CGU_PLL_SR0_PHASE_DIV_EN        1\r
133 \r
134 /*\r
135  *  CGU PLL1 NMK Register\r
136  */\r
137 #define CGU_PLL_NMK1_PLLN               ((*DANUBE_CGU_PLL_NMK1 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24)\r
138 #define CGU_PLL_NMK1_PLLM               GET_BITS(*DANUBE_CGU_PLL_NMK1, 23, 20)\r
139 #define CGU_PLL_NMK1_PLLK               GET_BITS(*DANUBE_CGU_PLL_NMK1, 19, 0)\r
140 \r
141 /*\r
142  *  CGU PLL1 Status Register\r
143  */\r
144 #define CGU_PLL_SR1_PLLDIV              ((*DANUBE_CGU_PLL_SR1 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)\r
145 #define CGU_PLL_SR1_PLLDEN              (*DANUBE_CGU_PLL_SR1 & (1 << 26))\r
146 #define CGU_PLL_SR1_PLLPSE              GET_BITS(*DANUBE_CGU_PLL_SR1, 5, 4)\r
147 #define CGU_PLL_SR1_PLLB                (*DANUBE_CGU_PLL_SR1 & (1 << 2))\r
148 #define CGU_PLL_SR1_PLLL                (*DANUBE_CGU_PLL_SR1 & (1 << 1))\r
149 #define CGU_PLL_SR1_PLLEN               (*DANUBE_CGU_PLL_SR1 & (1 << 0))\r
150 \r
151 #define CGU_PLL_SR1_DSMSEL              1\r
152 #define CGU_PLL_SR1_PHASE_DIV_EN        1\r
153 \r
154 /*\r
155  *  CGU PLL2 Status Register\r
156  */\r
157 #define CGU_PLL_SR2_PLLDIV              ((*DANUBE_CGU_PLL_SR2 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28)\r
158 #define CGU_PLL_SR2_PLLDEN              (*DANUBE_CGU_PLL_SR2 & (1 << 27))\r
159 #define CGU_PLL_SR2_PLLN                GET_BITS(*DANUBE_CGU_PLL_SR2, 25, 20)\r
160 #define CGU_PLL_SR2_PLLM                GET_BITS(*DANUBE_CGU_PLL_SR2, 19, 16)\r
161 #define CGU_PLL_SR2_PLLPS               (*DANUBE_CGU_PLL_SR2 & (1 << 5))\r
162 #define CGU_PLL_SR2_PLLPE               (*DANUBE_CGU_PLL_SR2 & (1 << 4))\r
163 #define CGU_PLL_SR2_PLLB                (*DANUBE_CGU_PLL_SR2 & (1 << 2))\r
164 #define CGU_PLL_SR2_PLLL                (*DANUBE_CGU_PLL_SR2 & (1 << 1))\r
165 #define CGU_PLL_SR2_PLLEN               (*DANUBE_CGU_PLL_SR2 & (1 << 0))\r
166 \r
167 /*\r
168  *  CGU Interface Clock Register\r
169  */\r
170 #define CGU_IF_CLK_CLKOD0               GET_BITS(*DANUBE_CGU_IF_CLK, 27, 26)\r
171 #define CGU_IF_CLK_CLKOD1               GET_BITS(*DANUBE_CGU_IF_CLK, 25, 24)\r
172 #define CGU_IF_CLK_CLKOD2               GET_BITS(*DANUBE_CGU_IF_CLK, 23, 22)\r
173 #define CGU_IF_CLK_CLKOD3               GET_BITS(*DANUBE_CGU_IF_CLK, 21, 20)\r
174 #define CGU_IF_CLK_PDA                  (*DANUBE_CGU_IF_CLK & (1 << 18))\r
175 #define CGU_IF_CLK_PCI_B                (*DANUBE_CGU_IF_CLK & (1 << 17))\r
176 #define CGU_IF_CLK_PCIBM                (*DANUBE_CGU_IF_CLK & (1 << 16))\r
177 #define CGU_IF_CLK_MIICS                (*DANUBE_CGU_IF_CLK & (1 << 3))\r
178 #define CGU_IF_CLK_USBCS                (*DANUBE_CGU_IF_CLK & (1 << 2))\r
179 #define CGU_IF_CLK_PCIF                 (*DANUBE_CGU_IF_CLK & (1 << 1))\r
180 #define CGU_IF_CLK_PCIS                 (*DANUBE_CGU_IF_CLK & (1 << 0))\r
181 \r
182 /*\r
183  *  CGU Oscillator Control Register\r
184  */\r
185 #define CGU_OSC_CTRL                    GET_BITS(*DANUBE_CGU_OSC_CTRL, 1, 0)\r
186 \r
187 /*\r
188  *  CGU SDRAM Memory Delay Register\r
189  */\r
190 #define CGU_SMD_CLKI                    (*DANUBE_CGU_SMD & (1 << 31))\r
191 #define CGU_SMD_MIDS                    GET_BITS(*DANUBE_CGU_SMD, 17, 12)\r
192 #define CGU_SMD_MODS                    GET_BITS(*DANUBE_CGU_SMD, 11, 6)\r
193 #define CGU_SMD_MDSEL                   GET_BITS(*DANUBE_CGU_SMD, 5, 0)\r
194 \r
195 /*\r
196  *  CGU CPU Clock Reduction Register\r
197  */\r
198 #define CGU_CRD_SFTR                    (*DANUBE_CGU_CRD & (1 << 31))\r
199 #define CGU_CRD_DIVE                    (*DANUBE_CGU_CRD & (1 << 16))\r
200 #define CGU_CRD_CRD1                    GET_BITS(*DANUBE_CGU_CRD, 3, 2)\r
201 #define CGU_CRD_CRD                     GET_BITS(*DANUBE_CGU_CRD, 1, 0)\r
202 \r
203 /*\r
204  *  CGU CT Status Register 1\r
205  */\r
206 #define CGU_CT1SR_PDOUT                 GET_BITS(*DANUBE_CGU_CT1SR, 13, 0)\r
207 \r
208 /*\r
209  *  CGU CT Status Register 2\r
210  */\r
211 #define CGU_CT2SR_PLL1K                 GET_BITS(*DANUBE_CGU_CT2SR, 9, 0)\r
212 \r
213 /*\r
214  *  CGU PCM Control Register\r
215  */\r
216 #define CGU_PCMCR_DCL1                  GET_BITS(*DANUBE_CGU_PCMCR, 27, 25)\r
217 #define CGU_PCMCR_MUXDCL                (*DANUBE_CGU_PCMCR & (1 << 22))\r
218 #define CGU_PCMCR_MUXFSC                (*DANUBE_CGU_PCMCR & (1 << 18))\r
219 #define CGU_PCMCR_PCM_SL                (*DANUBE_CGU_PCMCR & (1 << 13))\r
220 #define CGU_PCMCR_DNTR                  (*DANUBE_CGU_PCMCR & (1 << 12))\r
221 \r
222 /*\r
223  *  CGU Clock Mux Register\r
224  */\r
225 #define CGU_MUX_MII_CLK                 (*DANUBE_CGU_MUX & (1 << 6))\r
226 #define CGU_MUX_SUB_SYS                 GET_BITS(*DANUBE_CGU_MUX, 5, 3)\r
227 #define CGU_MUX_PP32                    GET_BITS(*DANUBE_CGU_MUX, 1, 0)\r
228 \r
229 \r
230 /*\r
231  * ####################################\r
232  * Preparation of Debug on Amazon Chip\r
233  * ####################################\r
234  */\r
235 \r
236 /*\r
237  *  If try module on Amazon chip, prepare some tricks to prevent invalid memory write.\r
238  */\r
239 #if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON\r
240     u32 g_pFakeRegisters[0x0100];\r
241 \r
242     #undef  DANUBE_CGU\r
243     #define DANUBE_CGU                  ((u32)g_pFakeRegisters)\r
244 #endif  //  defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON\r
245 \r
246 \r
247 /*\r
248  * ####################################\r
249  *              Data Type\r
250  * ####################################\r
251  */\r
252 \r
253 \r
254 /*\r
255  * ####################################\r
256  *             Declaration\r
257  * ####################################\r
258  */\r
259 \r
260 /*\r
261  *  Pre-declaration of File Operations\r
262  */\r
263 static ssize_t cgu_read(struct file *, char *, size_t, loff_t *);\r
264 static ssize_t cgu_write(struct file *, const char *, size_t, loff_t *);\r
265 static int cgu_ioctl(struct inode *, struct file *, unsigned int, unsigned long);\r
266 static int cgu_open(struct inode *, struct file *);\r
267 static int cgu_release(struct inode *, struct file *);\r
268 \r
269 /*\r
270  *  Pre-declaration of 64-bit Unsigned Integer Operation\r
271  */\r
272 static inline void uint64_multiply(unsigned int, unsigned int, unsigned int *);\r
273 static inline void uint64_divide(unsigned int *, unsigned int, unsigned int *, unsigned int *);\r
274 \r
275 /*\r
276  *  Calculate PLL Frequency\r
277  */\r
278 static inline u32 cal_dsm(u32, u32);\r
279 static inline u32 mash_dsm(u32, u32, u32);\r
280 static inline u32 ssff_dsm_1(u32, u32, u32);\r
281 static inline u32 ssff_dsm_2(u32, u32, u32);\r
282 static inline u32 dsm(u32 M, u32, u32, int, int);\r
283 static inline u32 cgu_get_pll0_fosc(void);\r
284 static inline u32 cgu_get_pll0_fps(void);\r
285 static inline u32 cgu_get_pll0_fdiv(void);\r
286 static inline u32 cgu_get_pll1_fosc(void);\r
287 static inline u32 cgu_get_pll1_fps(void);\r
288 static inline u32 cgu_get_pll1_fdiv(void);\r
289 static inline u32 cgu_get_pll2_fosc(void);\r
290 static inline u32 cgu_get_pll2_fps(void);\r
291 \r
292 /*\r
293  *  Export Functions\r
294  */\r
295 u32 cgu_get_mips_clock(int);\r
296 u32 cgu_get_cpu_clock(void);\r
297 u32 cgu_get_io_region_clock(void);\r
298 u32 cgu_get_fpi_bus_clock(int);\r
299 u32 cgu_get_pp32_clock(void);\r
300 u32 cgu_get_pci_clock(void);\r
301 u32 cgu_get_ethernet_clock(void);\r
302 u32 cgu_get_usb_clock(void);\r
303 u32 cgu_get_clockout(int);\r
304 \r
305 \r
306 /*\r
307  * ####################################\r
308  *            Local Variable\r
309  * ####################################\r
310  */\r
311 \r
312 static struct file_operations cgu_fops = {\r
313     owner:      THIS_MODULE,\r
314     llseek:     no_llseek,\r
315     read:       cgu_read,\r
316     write:      cgu_write,\r
317     ioctl:      cgu_ioctl,\r
318     open:       cgu_open,\r
319     release:    cgu_release\r
320 };\r
321 \r
322 static struct miscdevice cgu_miscdev = {\r
323     MISC_DYNAMIC_MINOR,\r
324     "danube_cgu_dev",\r
325     &cgu_fops\r
326 };\r
327 \r
328 \r
329 /*\r
330  * ####################################\r
331  *           Global Variable\r
332  * ####################################\r
333  */\r
334 \r
335 \r
336 /*\r
337  * ####################################\r
338  *            Local Function\r
339  * ####################################\r
340  */\r
341 \r
342 static ssize_t cgu_read(struct file *file, char *buf, size_t count, loff_t *ppos)\r
343 {\r
344     return -EPERM;\r
345 }\r
346 \r
347 static ssize_t cgu_write(struct file *file, const char *buf, size_t count, loff_t *ppos)\r
348 {\r
349     return -EPERM;\r
350 }\r
351 \r
352 static int cgu_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)\r
353 {\r
354     int ret = 0;\r
355     struct cgu_clock_rates rates;\r
356 \r
357     if ( _IOC_TYPE(cmd) != CGU_IOC_MAGIC\r
358         || _IOC_NR(cmd) >= CGU_IOC_MAXNR )\r
359         return -ENOTTY;\r
360 \r
361     if ( _IOC_DIR(cmd) & _IOC_READ )\r
362         ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd));\r
363     else if ( _IOC_DIR(cmd) & _IOC_WRITE )\r
364         ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd));\r
365     if ( ret )\r
366         return -EFAULT;\r
367 \r
368     switch ( cmd )\r
369     {\r
370     case CGU_GET_CLOCK_RATES:\r
371         /*  Calculate Clock Rates   */\r
372         rates.mips0     = cgu_get_mips_clock(0);\r
373         rates.mips1     = cgu_get_mips_clock(1);\r
374         rates.cpu       = cgu_get_cpu_clock();\r
375         rates.io_region = cgu_get_io_region_clock();\r
376         rates.fpi_bus1  = cgu_get_fpi_bus_clock(1);\r
377         rates.fpi_bus2  = cgu_get_fpi_bus_clock(2);\r
378         rates.pp32      = cgu_get_pp32_clock();\r
379         rates.pci       = cgu_get_pci_clock();\r
380         rates.ethernet  = cgu_get_ethernet_clock();\r
381         rates.usb       = cgu_get_usb_clock();\r
382         rates.clockout0 = cgu_get_clockout(0);\r
383         rates.clockout1 = cgu_get_clockout(1);\r
384         rates.clockout2 = cgu_get_clockout(2);\r
385         rates.clockout3 = cgu_get_clockout(3);\r
386         /*  Copy to User Space      */\r
387         copy_to_user((char*)arg, (char*)&rates, sizeof(rates));\r
388 \r
389         ret = 0;\r
390         break;\r
391     default:\r
392         ret = -ENOTTY;\r
393     }\r
394 \r
395     return ret;\r
396 }\r
397 \r
398 static int cgu_open(struct inode *inode, struct file *file)\r
399 {\r
400     return 0;\r
401 }\r
402 \r
403 static int cgu_release(struct inode *inode, struct file *file)\r
404 {\r
405     return 0;\r
406 }\r
407 \r
408 /*\r
409  *  Description:\r
410  *    calculate 64-bit multiplication result of two 32-bit unsigned integer\r
411  *  Input:\r
412  *    u32Multiplier1 --- u32 (32-bit), one of the multipliers\r
413  *    u32Multiplier2 --- u32 (32-bit), the other multiplier\r
414  *    u32Result      --- u32[2], array to retrieve the multiplication result,\r
415  *                       index 0 is high word, index 1 is low word\r
416  *  Output:\r
417 *    none\r
418  */\r
419 static inline void uint64_multiply(u32 u32Multiplier1, u32 u32Multiplier2, u32 u32Result[2])\r
420 {\r
421         u32 u32Multiplier1LowWord = u32Multiplier1 & 0xFFFF;\r
422         u32 u32Multiplier1HighWord = u32Multiplier1 >> 16;\r
423         u32 u32Multiplier2LowWord = u32Multiplier2 & 0xFFFF;\r
424         u32 u32Multiplier2HighWord = u32Multiplier2 >> 16;\r
425         u32 u32Combo1, u32Combo2, u32Combo3, u32Combo4;\r
426         u32 u32Word1, u32Word2, u32Word3, u32Word4;\r
427 \r
428         u32Combo1 = u32Multiplier1LowWord * u32Multiplier2LowWord;\r
429         u32Combo2 = u32Multiplier1HighWord * u32Multiplier2LowWord;\r
430         u32Combo3 = u32Multiplier1LowWord * u32Multiplier2HighWord;\r
431         u32Combo4 = u32Multiplier1HighWord * u32Multiplier2HighWord;\r
432 \r
433         u32Word1 = u32Combo1 & 0xFFFF;\r
434         u32Word2 = (u32Combo1 >> 16) + (u32Combo2 & 0xFFFF) + (u32Combo3 & 0xFFFF);\r
435         u32Word3 = (u32Combo2 >> 16) + (u32Combo3 >> 16) + (u32Combo4 & 0xFFFF) + (u32Word2 >> 16);\r
436         u32Word4 = (u32Combo4 >> 16) + (u32Word3 >> 16);\r
437 \r
438         u32Result[0] = (u32Word4 << 16) | u32Word3;\r
439         u32Result[1] = (u32Word2 << 16) | u32Word1;\r
440 }\r
441 \r
442 /*\r
443  *  Description:\r
444  *    divide 64-bit unsigned integer with 32-bit unsigned integer\r
445  *  Input:\r
446  *    u32Numerator   --- u32[2], index 0 is high word of numerator, while\r
447  *                       index 1 is low word of numerator\r
448  *    u32Denominator --- u32 (32-bit), the denominator in division, this\r
449  *                       parameter can not be zero, or lead to unpredictable\r
450  *                       result\r
451  *    pu32Quotient   --- u32 *, the pointer to retrieve 32-bit quotient, null\r
452  *                       pointer means ignore quotient\r
453  *    pu32Residue    --- u32 *, the pointer to retrieve 32-bit residue null\r
454  *                       pointer means ignore residue\r
455  *  Output:\r
456  *    none\r
457  */\r
458 static inline void uint64_divide(u32 u32Numerator[2], u32 u32Denominator, u32 *pu32Quotient, u32 *pu32Residue)\r
459 {\r
460         u32 u32DWord1, u32DWord2, u32DWord3;\r
461         u32 u32Quotient;\r
462         int i;\r
463 \r
464         u32DWord3 = 0;\r
465         u32DWord2 = u32Numerator[0];\r
466         u32DWord1 = u32Numerator[1];\r
467 \r
468         u32Quotient = 0;\r
469 \r
470         for ( i = 0; i < 64; i++ )\r
471         {\r
472                 u32DWord3 = (u32DWord3 << 1) | (u32DWord2 >> 31);\r
473                 u32DWord2 = (u32DWord2 << 1) | (u32DWord1 >> 31);\r
474                 u32DWord1 <<= 1;\r
475                 u32Quotient <<= 1;\r
476                 if ( u32DWord3 >= u32Denominator )\r
477                 {\r
478                         u32DWord3 -= u32Denominator;\r
479                         u32Quotient |= 1;\r
480                 }\r
481         }\r
482         if ( pu32Quotient )\r
483             *pu32Quotient = u32Quotient;\r
484         if ( pu32Residue )\r
485             *pu32Residue = u32DWord3;\r
486 }\r
487 \r
488 /*\r
489  *  Description:\r
490  *    common routine to calculate PLL frequency\r
491  *  Input:\r
492  *    num --- u32, numerator\r
493  *    den --- u32, denominator\r
494  *  Output:\r
495  *    u32 --- frequency the PLL output\r
496  */\r
497 static inline u32 cal_dsm(u32 num, u32 den)\r
498 {\r
499     u32 ret;\r
500     u32 temp[2];\r
501     u32 residue;\r
502 \r
503     uint64_multiply(num, BASIC_INPUT_CLOCK_FREQUENCY, temp);\r
504     uint64_divide(temp, den, &ret, &residue);\r
505     if ( (residue << 1) >= den )\r
506         ret++;\r
507 \r
508     return ret;\r
509 }\r
510 \r
511 /*\r
512  *  Description:\r
513  *    calculate PLL frequency following MASH-DSM\r
514  *  Input:\r
515  *    M   --- u32, denominator coefficient\r
516  *    N   --- u32, numerator integer coefficient\r
517  *    K   --- u32, numerator fraction coefficient\r
518  *  Output:\r
519  *    u32 --- frequency the PLL output\r
520  */\r
521 static inline u32 mash_dsm(u32 M, u32 N, u32 K)\r
522 {\r
523     u32 num = ((N + 1) << 10) + K;\r
524     u32 den = (M + 1) << 10;\r
525 \r
526     return cal_dsm(num, den);\r
527 }\r
528 \r
529 /*\r
530  *  Description:\r
531  *    calculate PLL frequency following SSFF-DSM (0.25 < fraction < 0.75)\r
532  *  Input:\r
533  *    M   --- u32, denominator coefficient\r
534  *    N   --- u32, numerator integer coefficient\r
535  *    K   --- u32, numerator fraction coefficient\r
536  *  Output:\r
537  *    u32 --- frequency the PLL output\r
538  */\r
539 static inline u32 ssff_dsm_1(u32 M, u32 N, u32 K)\r
540 {\r
541     u32 num = ((N + 1) << 11) + K + 512;\r
542     u32 den = (M + 1) << 11;\r
543 \r
544     return cal_dsm(num, den);\r
545 }\r
546 \r
547 /*\r
548  *  Description:\r
549  *    calculate PLL frequency following SSFF-DSM\r
550  *    (fraction < 0.125 || fraction > 0.875)\r
551  *  Input:\r
552  *    M   --- u32, denominator coefficient\r
553  *    N   --- u32, numerator integer coefficient\r
554  *    K   --- u32, numerator fraction coefficient\r
555  *  Output:\r
556  *    u32 --- frequency the PLL output\r
557  */\r
558 static inline u32 ssff_dsm_2(u32 M, u32 N, u32 K)\r
559 {\r
560     u32 num = K >= 512 ? ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;\r
561     u32 den = (M + 1) << 12;\r
562 \r
563     return cal_dsm(num, den);\r
564 }\r
565 \r
566 /*\r
567  *  Description:\r
568  *    calculate PLL frequency\r
569  *  Input:\r
570  *    M            --- u32, denominator coefficient\r
571  *    N            --- u32, numerator integer coefficient\r
572  *    K            --- u32, numerator fraction coefficient\r
573  *    dsmsel       --- int, 0: MASH-DSM, 1: SSFF-DSM\r
574  *    phase_div_en --- int, 0: 0.25 < fraction < 0.75\r
575  *                          1: fraction < 0.125 || fraction > 0.875\r
576  *  Output:\r
577  *    u32          --- frequency the PLL output\r
578  */\r
579 static inline u32 dsm(u32 M, u32 N, u32 K, int dsmsel, int phase_div_en)\r
580 {\r
581     if ( !dsmsel )\r
582         return mash_dsm(M, N, K);\r
583     else\r
584         if ( !phase_div_en )\r
585             return ssff_dsm_1(M, N, K);\r
586         else\r
587             return ssff_dsm_2(M, N, K);\r
588 }\r
589 \r
590 /*\r
591  *  Description:\r
592  *    get oscillate frequency of PLL0\r
593  *  Input:\r
594  *    none\r
595  *  Output:\r
596  *    u32 --- frequency of PLL0 Fosc\r
597  */\r
598 static inline u32 cgu_get_pll0_fosc(void)\r
599 {\r
600     return CGU_PLL_SR0_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_DSMSEL, CGU_PLL_SR0_PHASE_DIV_EN);\r
601 }\r
602 \r
603 /*\r
604  *  Description:\r
605  *    get output frequency of PLL0 phase shifter\r
606  *  Input:\r
607  *    none\r
608  *  Output:\r
609  *    u32 --- frequency of PLL0 Fps\r
610  */\r
611 static inline u32 cgu_get_pll0_fps(void)\r
612 {\r
613     register u32 fps = cgu_get_pll0_fosc();\r
614 \r
615     switch ( CGU_PLL_SR0_PLLPSE )\r
616     {\r
617     case 1:\r
618         /*  1.5     */\r
619         fps = ((fps << 1) + 1) / 3; break;\r
620     case 2:\r
621         /*  1.25    */\r
622         fps = ((fps << 2) + 2) / 5; break;\r
623     case 3:\r
624         /*  3.5     */\r
625         fps = ((fps << 1) + 3) / 7;\r
626     }\r
627     return fps;\r
628 }\r
629 \r
630 /*\r
631  *  Description:\r
632  *    get output frequency of PLL0 output divider\r
633  *  Input:\r
634  *    none\r
635  *  Output:\r
636  *    u32 --- frequency of PLL0 Fdiv\r
637  */\r
638 static inline u32 cgu_get_pll0_fdiv(void)\r
639 {\r
640     register u32 fdiv = cgu_get_pll0_fosc();\r
641 \r
642     if ( CGU_PLL_SR0_PLLDEN )\r
643         fdiv = (fdiv + (CGU_PLL_SR0_PLLDIV + 1) / 2) / (CGU_PLL_SR0_PLLDIV + 1);\r
644     return fdiv;\r
645 }\r
646 \r
647 /*\r
648  *  Description:\r
649  *    get oscillate frequency of PLL1\r
650  *  Input:\r
651  *    none\r
652  *  Output:\r
653  *    u32 --- frequency of PLL1 Fosc\r
654  */\r
655 static inline u32 cgu_get_pll1_fosc(void)\r
656 {\r
657     return CGU_PLL_SR1_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_DSMSEL, CGU_PLL_SR1_PHASE_DIV_EN);\r
658 }\r
659 \r
660 /*\r
661  *  Description:\r
662  *    get output frequency of PLL1 phase shifter\r
663  *  Input:\r
664  *    none\r
665  *  Output:\r
666  *    u32 --- frequency of PLL1 Fps\r
667  */\r
668 static inline u32 cgu_get_pll1_fps(void)\r
669 {\r
670     register u32 fps = cgu_get_pll1_fosc();\r
671 \r
672     switch ( CGU_PLL_SR1_PLLPSE )\r
673     {\r
674     case 1:\r
675         /*  1.5     */\r
676         fps = ((fps << 1) + 1) / 3; break;\r
677     case 2:\r
678         /*  1.25    */\r
679         fps = ((fps << 2) + 2) / 5; break;\r
680     case 3:\r
681         /*  3.5     */\r
682         fps = ((fps << 1) + 3) / 7;\r
683     }\r
684     return fps;\r
685 }\r
686 \r
687 /*\r
688  *  Description:\r
689  *    get output frequency of PLL1 output divider\r
690  *  Input:\r
691  *    none\r
692  *  Output:\r
693  *    u32 --- frequency of PLL1 Fdiv\r
694  */\r
695 static inline u32 cgu_get_pll1_fdiv(void)\r
696 {\r
697     register u32 fdiv = cgu_get_pll1_fosc();\r
698 \r
699     if ( CGU_PLL_SR1_PLLDEN )\r
700         fdiv = (fdiv + (CGU_PLL_SR1_PLLDIV + 1) / 2) / (CGU_PLL_SR1_PLLDIV + 1);\r
701     return fdiv;\r
702 }\r
703 \r
704 /*\r
705  *  Description:\r
706  *    get oscillate frequency of PLL2\r
707  *  Input:\r
708  *    none\r
709  *  Output:\r
710  *    u32 --- frequency of PLL2 Fosc\r
711  */\r
712 static inline u32 cgu_get_pll2_fosc(void)\r
713 {\r
714     u32 ret;\r
715     u32 temp[2];\r
716     u32 residue;\r
717 \r
718     uint64_multiply((CGU_PLL_SR2_PLLN + 1) * 8, cgu_get_pll0_fdiv(), temp);\r
719     uint64_divide(temp, CGU_PLL_SR2_PLLM + 1, &ret, &residue);\r
720     if ( (residue << 1) >= CGU_PLL_SR2_PLLM )\r
721         ret++;\r
722 \r
723     return ret;\r
724 }\r
725 \r
726 /*\r
727  *  Description:\r
728  *    get output frequency of PLL2 phase shifter\r
729  *  Input:\r
730  *    none\r
731  *  Output:\r
732  *    u32 --- frequency of PLL2 Fps\r
733  */\r
734 static inline u32 cgu_get_pll2_fps(void)\r
735 {\r
736     register u32 fps = cgu_get_pll2_fosc();\r
737 \r
738     if ( CGU_PLL_SR2_PLLPE )\r
739     {\r
740         if ( CGU_PLL_SR2_PLLPS )\r
741             /*  1.25    */\r
742             fps = ((fps << 3) + 4) / 9;\r
743         else\r
744             /*  1.125   */\r
745             fps = ((fps << 2) + 2) / 5;\r
746     }\r
747 \r
748     return fps;\r
749 }\r
750 \r
751 \r
752 /*\r
753  * ####################################\r
754  *           Global Function\r
755  * ####################################\r
756  */\r
757 \r
758 /*\r
759  *  Description:\r
760  *    get frequency of MIPS (0: core, 1: DSP)\r
761  *  Input:\r
762  *    cpu --- int, 0: core, 1: DSP\r
763  *  Output:\r
764  *    u32 --- frequency of MIPS coprocessor (0: core, 1: DSP)\r
765  */\r
766 u32 cgu_get_mips_clock(int cpu)\r
767 {\r
768     register u32 ret = cgu_get_pll0_fosc();\r
769 \r
770     if ( CGU_CRD_CRD )\r
771         ret = (ret + (CGU_CRD_CRD >> 1)) / (CGU_CRD_CRD + 1);\r
772     if ( cpu == 0 && CGU_CRD_CRD1 )\r
773         ret >>= CGU_CRD_CRD1;\r
774     return ret;\r
775 }\r
776 \r
777 /*\r
778  *  Description:\r
779  *    get frequency of MIPS core\r
780  *  Input:\r
781  *    none\r
782  *  Output:\r
783  *    u32 --- frequency of MIPS core\r
784  */\r
785 u32 cgu_get_cpu_clock(void)\r
786 {\r
787     return cgu_get_mips_clock(0);\r
788 }\r
789 \r
790 /*\r
791  *  Description:\r
792  *    get frequency of sub-system and memory controller\r
793  *  Input:\r
794  *    none\r
795  *  Output:\r
796  *    u32 --- frequency of sub-system and memory controller\r
797  */\r
798 u32 cgu_get_io_region_clock(void)\r
799 {\r
800     register u32 ret = (CGU_MUX_SUB_SYS > 4) ? cgu_get_pll0_fosc() : cgu_get_mips_clock(1);\r
801 \r
802     switch ( CGU_MUX_SUB_SYS )\r
803     {\r
804     case 0:\r
805         break;\r
806     case 1:\r
807     default:\r
808         ret = (ret + 1) >> 1; break;\r
809     case 2:\r
810         ret = (ret + 1) / 3; break;\r
811     case 3:\r
812         ret = (ret + 2) >> 2; break;\r
813     case 5:\r
814         ret = ((ret << 1) + 1) / 3; break;\r
815     case 6:\r
816         ret = ((ret << 1) + 2) / 5;\r
817     }\r
818 \r
819     return ret;\r
820 }\r
821 \r
822 /*\r
823  *  Description:\r
824  *    get frequency of FPI bus\r
825  *  Input:\r
826  *    fpi --- int, 1: FPI bus 1 (FBS1/Fast FPI Bus), 2: FPI bus 2 (FBS2)\r
827  *  Output:\r
828  *    u32 --- frequency of FPI bus\r
829  */\r
830 u32 cgu_get_fpi_bus_clock(int fpi)\r
831 {\r
832     register u32 ret = cgu_get_io_region_clock();\r
833 \r
834     if ( fpi == 2 )\r
835         ret >>= 1;\r
836     return ret;\r
837 }\r
838 \r
839 /*\r
840  *  Description:\r
841  *    get frequency of PP32 processor\r
842  *  Input:\r
843  *    none\r
844  *  Output:\r
845  *    u32 --- frequency of PP32 processor\r
846  */\r
847 u32 cgu_get_pp32_clock(void)\r
848 {\r
849     register u32 ret;\r
850 \r
851     switch ( CGU_MUX_PP32 )\r
852     {\r
853     case 0:\r
854     default:\r
855         ret = ((cgu_get_pll2_fosc() << 2) + 2) / 5; break;\r
856     case 1:\r
857         ret = ((cgu_get_pll2_fosc() << 3) + 4) / 9; break;\r
858     case 2:\r
859         ret = cgu_get_fpi_bus_clock(1); break;\r
860     case 3:\r
861         ret = cgu_get_mips_clock(1);\r
862     }\r
863 \r
864     return ret;\r
865 }\r
866 \r
867 /*\r
868  *  Description:\r
869  *    get frequency of PCI bus\r
870  *  Input:\r
871  *    none\r
872  *  Output:\r
873  *    u32 --- frequency of PCI bus\r
874  */\r
875 u32 cgu_get_pci_clock(void)\r
876 {\r
877     register u32 ret = 0;\r
878 \r
879     if ( !CGU_IF_CLK_PCIS )\r
880     {\r
881         ret = cgu_get_pll2_fosc();\r
882         if ( CGU_IF_CLK_PCIF )\r
883             ret = (ret + 2) / 5;\r
884         else\r
885             ret = (ret + 4) / 9;\r
886     }\r
887 \r
888     return ret;\r
889 }\r
890 \r
891 /*\r
892  *  Description:\r
893  *    get frequency of ethernet module (MII)\r
894  *  Input:\r
895  *    none\r
896  *  Output:\r
897  *    u32 --- frequency of ethernet module\r
898  */\r
899 u32 cgu_get_ethernet_clock(void)\r
900 {\r
901     register u32 ret = 0;\r
902 \r
903     if ( !CGU_IF_CLK_MIICS )\r
904     {\r
905         ret = cgu_get_pll2_fosc();\r
906         if ( CGU_MUX_MII_CLK )\r
907             ret = (ret + 3) / 6;\r
908         else\r
909             ret = (ret + 6) / 12;\r
910     }\r
911 \r
912     return ret;\r
913 }\r
914 \r
915 /*\r
916  *  Description:\r
917  *    get frequency of USB\r
918  *  Input:\r
919  *    none\r
920  *  Output:\r
921  *    u32 --- frequency of USB\r
922  */\r
923 u32 cgu_get_usb_clock(void)\r
924 {\r
925     return CGU_IF_CLK_USBCS ? 12000000 : (cgu_get_pll2_fosc() + 12) / 25;\r
926 }\r
927 \r
928 /*\r
929  *  Description:\r
930  *    get frequency of CLK_OUT pin\r
931  *  Input:\r
932  *    clkout --- int, clock out pin number\r
933  *  Output:\r
934  *    u32    --- frequency of CLK_OUT pin\r
935  */\r
936 u32 cgu_get_clockout(int clkout)\r
937 {\r
938     u32 fosc1 = cgu_get_pll1_fosc();\r
939     u32 fosc2 = cgu_get_pll2_fosc();\r
940 \r
941     if ( clkout > 3 || clkout < 0 )\r
942         return 0;\r
943 \r
944     switch ( ((u32)clkout << 2) | GET_BITS(*DANUBE_CGU_IF_CLK, 21 + clkout * 2, 20 + clkout * 2) )\r
945     {\r
946     case 0: /*  32.768KHz   */\r
947     case 14:\r
948         return (fosc1 + 6000) / 12000;\r
949     case 1: /*  1.536MHz    */\r
950         return (fosc1 + 128) / 256;\r
951     case 2: /*  2.5MHz      */\r
952         return (fosc2 + 60) / 120;\r
953     case 3: /*  12MHz       */\r
954     case 5:\r
955     case 12:\r
956         return (fosc2 + 12) / 25;\r
957     case 4: /*  40MHz       */\r
958         return (fosc2 * 2 + 7) / 15;\r
959     case 6: /*  24MHz       */\r
960         return (fosc2 * 2 + 12) / 25;\r
961     case 7: /*  48MHz       */\r
962         return (fosc2 * 4 + 12) / 25;\r
963     case 8: /*  25MHz       */\r
964     case 15:\r
965         return (fosc2 + 6) / 12;\r
966     case 9: /*  50MHz       */\r
967     case 13:\r
968         return (fosc2 + 3) / 6;\r
969     case 10:/*  30MHz       */\r
970         return (fosc2 + 5) / 10;\r
971     case 11:/*  60MHz       */\r
972         return (fosc2 + 2) / 5;\r
973     }\r
974 \r
975     return 0;\r
976 }\r
977 \r
978 \r
979 /*\r
980  * ####################################\r
981  *           Init/Cleanup API\r
982  * ####################################\r
983  */\r
984 \r
985 /*\r
986  *  Description:\r
987  *    register device\r
988  *  Input:\r
989  *    none\r
990  *  Output:\r
991  *    0    --- successful\r
992  *    else --- failure, usually it is negative value of error code\r
993  */\r
994 int __init danube_cgu_init(void)\r
995 {\r
996     int ret;\r
997 \r
998     ret = misc_register(&cgu_miscdev);\r
999     if ( ret )\r
1000     {\r
1001         printk(KERN_ERR "cgu: can't misc_register\n");\r
1002         return ret;\r
1003     }\r
1004     else\r
1005         printk(KERN_INFO "cgu: misc_register on minor = %d\n", cgu_miscdev.minor);\r
1006 \r
1007     /*\r
1008      *  initialize fake registers to do testing on Amazon\r
1009      */\r
1010 #if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON\r
1011     #ifdef  DEBUG_PRINT_INFO\r
1012     #undef  DEBUG_PRINT_INFO\r
1013     #endif\r
1014     #define DEBUG_PRINT_INFO    1\r
1015 \r
1016     *DANUBE_CGU_DIV         = 0x00010019;\r
1017     *DANUBE_CGU_PLL_NMK0    = 0x416002C3;\r
1018     *DANUBE_CGU_PLL_SR0     = 0x74000013;\r
1019     *DANUBE_CGU_PLL_NMK1    = 0x4C60009C;\r
1020     *DANUBE_CGU_PLL_SR1     = 0x54000013;\r
1021     *DANUBE_CGU_PLL_SR2     = 0x58890013;\r
1022     *DANUBE_CGU_IF_CLK      = 0x00000000;\r
1023     *DANUBE_CGU_OSC_CTRL    = 0x00000000;\r
1024     *DANUBE_CGU_SMD         = 0x00000000;\r
1025     *DANUBE_CGU_CRD         = 0x00010000;\r
1026     *DANUBE_CGU_CT1SR       = 0x00000000;\r
1027     *DANUBE_CGU_CT2SR       = CGU_PLL_NMK1_PLLK;\r
1028     *DANUBE_CGU_PCMCR       = 0x00000000;\r
1029     *DANUBE_CGU_MUX         = 0x00000008;\r
1030 #endif  //  defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON\r
1031 \r
1032     /*\r
1033      *  for testing only\r
1034      */\r
1035 #if defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO\r
1036     printk("pll0 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_PLLDIV);\r
1037     printk("pll1 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_PLLDIV);\r
1038     printk("pll2 N = %d, M = %d, DIV = %d\n", CGU_PLL_SR2_PLLN, CGU_PLL_SR2_PLLM, CGU_PLL_SR2_PLLDIV);\r
1039     printk("pll0_fosc    = %d\n", cgu_get_pll0_fosc());\r
1040     printk("pll0_fps     = %d\n", cgu_get_pll0_fps());\r
1041     printk("pll0_fdiv    = %d\n", cgu_get_pll0_fdiv());\r
1042     printk("pll1_fosc    = %d\n", cgu_get_pll1_fosc());\r
1043     printk("pll1_fps     = %d\n", cgu_get_pll1_fps());\r
1044     printk("pll1_fdiv    = %d\n", cgu_get_pll1_fdiv());\r
1045     printk("pll2_fosc    = %d\n", cgu_get_pll2_fosc());\r
1046     printk("pll2_fps     = %d\n", cgu_get_pll2_fps());\r
1047     printk("mips0 clock  = %d\n", cgu_get_mips_clock(0));\r
1048     printk("mips1 clock  = %d\n", cgu_get_mips_clock(1));\r
1049     printk("cpu clock    = %d\n", cgu_get_cpu_clock());\r
1050     printk("IO region    = %d\n", cgu_get_io_region_clock());\r
1051     printk("FPI bus 1    = %d\n", cgu_get_fpi_bus_clock(1));\r
1052     printk("FPI bus 2    = %d\n", cgu_get_fpi_bus_clock(2));\r
1053     printk("PP32 clock   = %d\n", cgu_get_pp32_clock());\r
1054     printk("PCI clock    = %d\n", cgu_get_pci_clock());\r
1055     printk("Ethernet     = %d\n", cgu_get_ethernet_clock());\r
1056     printk("USB clock    = %d\n", cgu_get_usb_clock());\r
1057     printk("Clockout0    = %d\n", cgu_get_clockout(0));\r
1058     printk("Clockout1    = %d\n", cgu_get_clockout(1));\r
1059     printk("Clockout2    = %d\n", cgu_get_clockout(2));\r
1060     printk("Clockout3    = %d\n", cgu_get_clockout(3));\r
1061 #endif  //  defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO\r
1062 \r
1063     return 0;\r
1064 }\r
1065 \r
1066 /*\r
1067  *  Description:\r
1068  *    deregister device\r
1069  *  Input:\r
1070  *    none\r
1071  *  Output:\r
1072  *    none\r
1073  */\r
1074 void __exit danube_cgu_exit(void)\r
1075 {\r
1076     int ret;\r
1077 \r
1078     ret = misc_deregister(&cgu_miscdev);\r
1079     if ( ret )\r
1080         printk(KERN_ERR "cgu: can't misc_deregister, get error number %d\n", -ret);\r
1081     else\r
1082         printk(KERN_INFO "cgu: misc_deregister successfully\n");\r
1083 }\r
1084 \r
1085 module_init(danube_cgu_init);\r
1086 module_exit(danube_cgu_exit);\r