]> git.karo-electronics.de Git - mv-sheeva.git/blob - arch/powerpc/sysdev/cpm2_common.c
859362fecb7c659a6e546ef92dc5610b843109ea
[mv-sheeva.git] / arch / powerpc / sysdev / cpm2_common.c
1 /*
2  * General Purpose functions for the global management of the
3  * 8260 Communication Processor Module.
4  * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
5  * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
6  *      2.3.99 Updates
7  *
8  * 2006 (c) MontaVista Software, Inc.
9  * Vitaly Bordug <vbordug@ru.mvista.com>
10  *      Merged to arch/powerpc from arch/ppc/syslib/cpm2_common.c
11  *
12  * This file is licensed under the terms of the GNU General Public License
13  * version 2. This program is licensed "as is" without any warranty of any
14  * kind, whether express or implied.
15  */
16
17 /*
18  *
19  * In addition to the individual control of the communication
20  * channels, there are a few functions that globally affect the
21  * communication processor.
22  *
23  * Buffer descriptors must be allocated from the dual ported memory
24  * space.  The allocator for that is here.  When the communication
25  * process is reset, we reclaim the memory available.  There is
26  * currently no deallocator for this memory.
27  */
28 #include <linux/errno.h>
29 #include <linux/sched.h>
30 #include <linux/kernel.h>
31 #include <linux/param.h>
32 #include <linux/string.h>
33 #include <linux/mm.h>
34 #include <linux/interrupt.h>
35 #include <linux/module.h>
36 #include <linux/of.h>
37
38 #include <asm/io.h>
39 #include <asm/irq.h>
40 #include <asm/mpc8260.h>
41 #include <asm/page.h>
42 #include <asm/pgtable.h>
43 #include <asm/cpm2.h>
44 #include <asm/rheap.h>
45 #include <asm/fs_pd.h>
46
47 #include <sysdev/fsl_soc.h>
48
49 #ifndef CONFIG_PPC_CPM_NEW_BINDING
50 static void cpm2_dpinit(void);
51 #endif
52
53 cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
54
55 /* We allocate this here because it is used almost exclusively for
56  * the communication processor devices.
57  */
58 cpm2_map_t __iomem *cpm2_immr;
59
60 #define CPM_MAP_SIZE    (0x40000)       /* 256k - the PQ3 reserve this amount
61                                            of space for CPM as it is larger
62                                            than on PQ2 */
63
64 void
65 cpm2_reset(void)
66 {
67 #ifdef CONFIG_PPC_85xx
68         cpm2_immr = ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
69 #else
70         cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
71 #endif
72
73         /* Reclaim the DP memory for our use.
74          */
75 #ifdef CONFIG_PPC_CPM_NEW_BINDING
76         cpm_muram_init();
77 #else
78         cpm2_dpinit();
79 #endif
80
81         /* Tell everyone where the comm processor resides.
82          */
83         cpmp = &cpm2_immr->im_cpm;
84 }
85
86 /* Set a baud rate generator.  This needs lots of work.  There are
87  * eight BRGs, which can be connected to the CPM channels or output
88  * as clocks.  The BRGs are in two different block of internal
89  * memory mapped space.
90  * The baud rate clock is the system clock divided by something.
91  * It was set up long ago during the initial boot phase and is
92  * is given to us.
93  * Baud rate clocks are zero-based in the driver code (as that maps
94  * to port numbers).  Documentation uses 1-based numbering.
95  */
96 #define BRG_INT_CLK     (get_brgfreq())
97 #define BRG_UART_CLK    (BRG_INT_CLK/16)
98
99 /* This function is used by UARTS, or anything else that uses a 16x
100  * oversampled clock.
101  */
102 void
103 cpm_setbrg(uint brg, uint rate)
104 {
105         u32 __iomem *bp;
106
107         /* This is good enough to get SMCs running.....
108         */
109         if (brg < 4) {
110                 bp = cpm2_map_size(im_brgc1, 16);
111         } else {
112                 bp = cpm2_map_size(im_brgc5, 16);
113                 brg -= 4;
114         }
115         bp += brg;
116         out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN);
117
118         cpm2_unmap(bp);
119 }
120
121 /* This function is used to set high speed synchronous baud rate
122  * clocks.
123  */
124 void
125 cpm2_fastbrg(uint brg, uint rate, int div16)
126 {
127         u32 __iomem *bp;
128         u32 val;
129
130         if (brg < 4) {
131                 bp = cpm2_map_size(im_brgc1, 16);
132         }
133         else {
134                 bp = cpm2_map_size(im_brgc5, 16);
135                 brg -= 4;
136         }
137         bp += brg;
138         val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
139         if (div16)
140                 val |= CPM_BRG_DIV16;
141
142         out_be32(bp, val);
143         cpm2_unmap(bp);
144 }
145
146 int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
147 {
148         int ret = 0;
149         int shift;
150         int i, bits = 0;
151         cpmux_t __iomem *im_cpmux;
152         u32 __iomem *reg;
153         u32 mask = 7;
154
155         u8 clk_map[][3] = {
156                 {CPM_CLK_FCC1, CPM_BRG5, 0},
157                 {CPM_CLK_FCC1, CPM_BRG6, 1},
158                 {CPM_CLK_FCC1, CPM_BRG7, 2},
159                 {CPM_CLK_FCC1, CPM_BRG8, 3},
160                 {CPM_CLK_FCC1, CPM_CLK9, 4},
161                 {CPM_CLK_FCC1, CPM_CLK10, 5},
162                 {CPM_CLK_FCC1, CPM_CLK11, 6},
163                 {CPM_CLK_FCC1, CPM_CLK12, 7},
164                 {CPM_CLK_FCC2, CPM_BRG5, 0},
165                 {CPM_CLK_FCC2, CPM_BRG6, 1},
166                 {CPM_CLK_FCC2, CPM_BRG7, 2},
167                 {CPM_CLK_FCC2, CPM_BRG8, 3},
168                 {CPM_CLK_FCC2, CPM_CLK13, 4},
169                 {CPM_CLK_FCC2, CPM_CLK14, 5},
170                 {CPM_CLK_FCC2, CPM_CLK15, 6},
171                 {CPM_CLK_FCC2, CPM_CLK16, 7},
172                 {CPM_CLK_FCC3, CPM_BRG5, 0},
173                 {CPM_CLK_FCC3, CPM_BRG6, 1},
174                 {CPM_CLK_FCC3, CPM_BRG7, 2},
175                 {CPM_CLK_FCC3, CPM_BRG8, 3},
176                 {CPM_CLK_FCC3, CPM_CLK13, 4},
177                 {CPM_CLK_FCC3, CPM_CLK14, 5},
178                 {CPM_CLK_FCC3, CPM_CLK15, 6},
179                 {CPM_CLK_FCC3, CPM_CLK16, 7},
180                 {CPM_CLK_SCC1, CPM_BRG1, 0},
181                 {CPM_CLK_SCC1, CPM_BRG2, 1},
182                 {CPM_CLK_SCC1, CPM_BRG3, 2},
183                 {CPM_CLK_SCC1, CPM_BRG4, 3},
184                 {CPM_CLK_SCC1, CPM_CLK11, 4},
185                 {CPM_CLK_SCC1, CPM_CLK12, 5},
186                 {CPM_CLK_SCC1, CPM_CLK3, 6},
187                 {CPM_CLK_SCC1, CPM_CLK4, 7},
188                 {CPM_CLK_SCC2, CPM_BRG1, 0},
189                 {CPM_CLK_SCC2, CPM_BRG2, 1},
190                 {CPM_CLK_SCC2, CPM_BRG3, 2},
191                 {CPM_CLK_SCC2, CPM_BRG4, 3},
192                 {CPM_CLK_SCC2, CPM_CLK11, 4},
193                 {CPM_CLK_SCC2, CPM_CLK12, 5},
194                 {CPM_CLK_SCC2, CPM_CLK3, 6},
195                 {CPM_CLK_SCC2, CPM_CLK4, 7},
196                 {CPM_CLK_SCC3, CPM_BRG1, 0},
197                 {CPM_CLK_SCC3, CPM_BRG2, 1},
198                 {CPM_CLK_SCC3, CPM_BRG3, 2},
199                 {CPM_CLK_SCC3, CPM_BRG4, 3},
200                 {CPM_CLK_SCC3, CPM_CLK5, 4},
201                 {CPM_CLK_SCC3, CPM_CLK6, 5},
202                 {CPM_CLK_SCC3, CPM_CLK7, 6},
203                 {CPM_CLK_SCC3, CPM_CLK8, 7},
204                 {CPM_CLK_SCC4, CPM_BRG1, 0},
205                 {CPM_CLK_SCC4, CPM_BRG2, 1},
206                 {CPM_CLK_SCC4, CPM_BRG3, 2},
207                 {CPM_CLK_SCC4, CPM_BRG4, 3},
208                 {CPM_CLK_SCC4, CPM_CLK5, 4},
209                 {CPM_CLK_SCC4, CPM_CLK6, 5},
210                 {CPM_CLK_SCC4, CPM_CLK7, 6},
211                 {CPM_CLK_SCC4, CPM_CLK8, 7},
212         };
213
214         im_cpmux = cpm2_map(im_cpmux);
215
216         switch (target) {
217         case CPM_CLK_SCC1:
218                 reg = &im_cpmux->cmx_scr;
219                 shift = 24;
220         case CPM_CLK_SCC2:
221                 reg = &im_cpmux->cmx_scr;
222                 shift = 16;
223                 break;
224         case CPM_CLK_SCC3:
225                 reg = &im_cpmux->cmx_scr;
226                 shift = 8;
227                 break;
228         case CPM_CLK_SCC4:
229                 reg = &im_cpmux->cmx_scr;
230                 shift = 0;
231                 break;
232         case CPM_CLK_FCC1:
233                 reg = &im_cpmux->cmx_fcr;
234                 shift = 24;
235                 break;
236         case CPM_CLK_FCC2:
237                 reg = &im_cpmux->cmx_fcr;
238                 shift = 16;
239                 break;
240         case CPM_CLK_FCC3:
241                 reg = &im_cpmux->cmx_fcr;
242                 shift = 8;
243                 break;
244         default:
245                 printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
246                 return -EINVAL;
247         }
248
249         if (mode == CPM_CLK_RX)
250                 shift += 3;
251
252         for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
253                 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
254                         bits = clk_map[i][2];
255                         break;
256                 }
257         }
258         if (i == ARRAY_SIZE(clk_map))
259             ret = -EINVAL;
260
261         bits <<= shift;
262         mask <<= shift;
263
264         out_be32(reg, (in_be32(reg) & ~mask) | bits);
265
266         cpm2_unmap(im_cpmux);
267         return ret;
268 }
269
270 int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
271 {
272         int ret = 0;
273         int shift;
274         int i, bits = 0;
275         cpmux_t __iomem *im_cpmux;
276         u8 __iomem *reg;
277         u8 mask = 3;
278
279         u8 clk_map[][3] = {
280                 {CPM_CLK_SMC1, CPM_BRG1, 0},
281                 {CPM_CLK_SMC1, CPM_BRG7, 1},
282                 {CPM_CLK_SMC1, CPM_CLK7, 2},
283                 {CPM_CLK_SMC1, CPM_CLK9, 3},
284                 {CPM_CLK_SMC2, CPM_BRG2, 0},
285                 {CPM_CLK_SMC2, CPM_BRG8, 1},
286                 {CPM_CLK_SMC2, CPM_CLK4, 2},
287                 {CPM_CLK_SMC2, CPM_CLK15, 3},
288         };
289
290         im_cpmux = cpm2_map(im_cpmux);
291
292         switch (target) {
293         case CPM_CLK_SMC1:
294                 reg = &im_cpmux->cmx_smr;
295                 mask = 3;
296                 shift = 4;
297                 break;
298         case CPM_CLK_SMC2:
299                 reg = &im_cpmux->cmx_smr;
300                 mask = 3;
301                 shift = 0;
302                 break;
303         default:
304                 printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
305                 return -EINVAL;
306         }
307
308         for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
309                 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
310                         bits = clk_map[i][2];
311                         break;
312                 }
313         }
314         if (i == ARRAY_SIZE(clk_map))
315             ret = -EINVAL;
316
317         bits <<= shift;
318         mask <<= shift;
319
320         out_8(reg, (in_8(reg) & ~mask) | bits);
321
322         cpm2_unmap(im_cpmux);
323         return ret;
324 }
325
326 #ifndef CONFIG_PPC_CPM_NEW_BINDING
327 /*
328  * dpalloc / dpfree bits.
329  */
330 static spinlock_t cpm_dpmem_lock;
331 /* 16 blocks should be enough to satisfy all requests
332  * until the memory subsystem goes up... */
333 static rh_block_t cpm_boot_dpmem_rh_block[16];
334 static rh_info_t cpm_dpmem_info;
335 static u8 __iomem *im_dprambase;
336
337 static void cpm2_dpinit(void)
338 {
339         spin_lock_init(&cpm_dpmem_lock);
340
341         /* initialize the info header */
342         rh_init(&cpm_dpmem_info, 1,
343                         sizeof(cpm_boot_dpmem_rh_block) /
344                         sizeof(cpm_boot_dpmem_rh_block[0]),
345                         cpm_boot_dpmem_rh_block);
346
347         im_dprambase = cpm2_immr;
348
349         /* Attach the usable dpmem area */
350         /* XXX: This is actually crap. CPM_DATAONLY_BASE and
351          * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
352          * varies with the processor and the microcode patches activated.
353          * But the following should be at least safe.
354          */
355         rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
356 }
357
358 /* This function returns an index into the DPRAM area.
359  */
360 unsigned long cpm_dpalloc(uint size, uint align)
361 {
362         unsigned long start;
363         unsigned long flags;
364
365         spin_lock_irqsave(&cpm_dpmem_lock, flags);
366         cpm_dpmem_info.alignment = align;
367         start = rh_alloc(&cpm_dpmem_info, size, "commproc");
368         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
369
370         return (uint)start;
371 }
372 EXPORT_SYMBOL(cpm_dpalloc);
373
374 int cpm_dpfree(unsigned long offset)
375 {
376         int ret;
377         unsigned long flags;
378
379         spin_lock_irqsave(&cpm_dpmem_lock, flags);
380         ret = rh_free(&cpm_dpmem_info, offset);
381         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
382
383         return ret;
384 }
385 EXPORT_SYMBOL(cpm_dpfree);
386
387 /* not sure if this is ever needed */
388 unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
389 {
390         unsigned long start;
391         unsigned long flags;
392
393         spin_lock_irqsave(&cpm_dpmem_lock, flags);
394         cpm_dpmem_info.alignment = align;
395         start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
396         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
397
398         return start;
399 }
400 EXPORT_SYMBOL(cpm_dpalloc_fixed);
401
402 void cpm_dpdump(void)
403 {
404         rh_dump(&cpm_dpmem_info);
405 }
406 EXPORT_SYMBOL(cpm_dpdump);
407
408 void *cpm_dpram_addr(unsigned long offset)
409 {
410         return (void *)(im_dprambase + offset);
411 }
412 EXPORT_SYMBOL(cpm_dpram_addr);
413 #endif /* !CONFIG_PPC_CPM_NEW_BINDING */
414
415 struct cpm2_ioports {
416         u32 dir, par, sor, odr, dat;
417         u32 res[3];
418 };
419
420 void cpm2_set_pin(int port, int pin, int flags)
421 {
422         struct cpm2_ioports __iomem *iop =
423                 (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
424
425         pin = 1 << (31 - pin);
426
427         if (flags & CPM_PIN_OUTPUT)
428                 setbits32(&iop[port].dir, pin);
429         else
430                 clrbits32(&iop[port].dir, pin);
431
432         if (!(flags & CPM_PIN_GPIO))
433                 setbits32(&iop[port].par, pin);
434         else
435                 clrbits32(&iop[port].par, pin);
436
437         if (flags & CPM_PIN_SECONDARY)
438                 setbits32(&iop[port].sor, pin);
439         else
440                 clrbits32(&iop[port].sor, pin);
441
442         if (flags & CPM_PIN_OPENDRAIN)
443                 setbits32(&iop[port].odr, pin);
444         else
445                 clrbits32(&iop[port].odr, pin);
446 }