[POWERPC] pasemi: Implement MSI support
[linux-2.6] / 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 static DEFINE_SPINLOCK(cmd_lock);
87
88 #define MAX_CR_CMD_LOOPS        10000
89
90 int cpm_command(u32 command, u8 opcode)
91 {
92         int i, ret;
93         unsigned long flags;
94
95         spin_lock_irqsave(&cmd_lock, flags);
96
97         ret = 0;
98         out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
99         for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
100                 if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
101                         goto out;
102
103         printk(KERN_ERR "%s(): Not able to issue CPM command\n", __FUNCTION__);
104         ret = -EIO;
105 out:
106         spin_unlock_irqrestore(&cmd_lock, flags);
107         return ret;
108 }
109 EXPORT_SYMBOL(cpm_command);
110
111 /* Set a baud rate generator.  This needs lots of work.  There are
112  * eight BRGs, which can be connected to the CPM channels or output
113  * as clocks.  The BRGs are in two different block of internal
114  * memory mapped space.
115  * The baud rate clock is the system clock divided by something.
116  * It was set up long ago during the initial boot phase and is
117  * is given to us.
118  * Baud rate clocks are zero-based in the driver code (as that maps
119  * to port numbers).  Documentation uses 1-based numbering.
120  */
121 #define BRG_INT_CLK     (get_brgfreq())
122 #define BRG_UART_CLK    (BRG_INT_CLK/16)
123
124 /* This function is used by UARTS, or anything else that uses a 16x
125  * oversampled clock.
126  */
127 void
128 cpm_setbrg(uint brg, uint rate)
129 {
130         u32 __iomem *bp;
131
132         /* This is good enough to get SMCs running.....
133         */
134         if (brg < 4) {
135                 bp = cpm2_map_size(im_brgc1, 16);
136         } else {
137                 bp = cpm2_map_size(im_brgc5, 16);
138                 brg -= 4;
139         }
140         bp += brg;
141         out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN);
142
143         cpm2_unmap(bp);
144 }
145
146 /* This function is used to set high speed synchronous baud rate
147  * clocks.
148  */
149 void
150 cpm2_fastbrg(uint brg, uint rate, int div16)
151 {
152         u32 __iomem *bp;
153         u32 val;
154
155         if (brg < 4) {
156                 bp = cpm2_map_size(im_brgc1, 16);
157         }
158         else {
159                 bp = cpm2_map_size(im_brgc5, 16);
160                 brg -= 4;
161         }
162         bp += brg;
163         val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
164         if (div16)
165                 val |= CPM_BRG_DIV16;
166
167         out_be32(bp, val);
168         cpm2_unmap(bp);
169 }
170
171 int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
172 {
173         int ret = 0;
174         int shift;
175         int i, bits = 0;
176         cpmux_t __iomem *im_cpmux;
177         u32 __iomem *reg;
178         u32 mask = 7;
179
180         u8 clk_map[][3] = {
181                 {CPM_CLK_FCC1, CPM_BRG5, 0},
182                 {CPM_CLK_FCC1, CPM_BRG6, 1},
183                 {CPM_CLK_FCC1, CPM_BRG7, 2},
184                 {CPM_CLK_FCC1, CPM_BRG8, 3},
185                 {CPM_CLK_FCC1, CPM_CLK9, 4},
186                 {CPM_CLK_FCC1, CPM_CLK10, 5},
187                 {CPM_CLK_FCC1, CPM_CLK11, 6},
188                 {CPM_CLK_FCC1, CPM_CLK12, 7},
189                 {CPM_CLK_FCC2, CPM_BRG5, 0},
190                 {CPM_CLK_FCC2, CPM_BRG6, 1},
191                 {CPM_CLK_FCC2, CPM_BRG7, 2},
192                 {CPM_CLK_FCC2, CPM_BRG8, 3},
193                 {CPM_CLK_FCC2, CPM_CLK13, 4},
194                 {CPM_CLK_FCC2, CPM_CLK14, 5},
195                 {CPM_CLK_FCC2, CPM_CLK15, 6},
196                 {CPM_CLK_FCC2, CPM_CLK16, 7},
197                 {CPM_CLK_FCC3, CPM_BRG5, 0},
198                 {CPM_CLK_FCC3, CPM_BRG6, 1},
199                 {CPM_CLK_FCC3, CPM_BRG7, 2},
200                 {CPM_CLK_FCC3, CPM_BRG8, 3},
201                 {CPM_CLK_FCC3, CPM_CLK13, 4},
202                 {CPM_CLK_FCC3, CPM_CLK14, 5},
203                 {CPM_CLK_FCC3, CPM_CLK15, 6},
204                 {CPM_CLK_FCC3, CPM_CLK16, 7},
205                 {CPM_CLK_SCC1, CPM_BRG1, 0},
206                 {CPM_CLK_SCC1, CPM_BRG2, 1},
207                 {CPM_CLK_SCC1, CPM_BRG3, 2},
208                 {CPM_CLK_SCC1, CPM_BRG4, 3},
209                 {CPM_CLK_SCC1, CPM_CLK11, 4},
210                 {CPM_CLK_SCC1, CPM_CLK12, 5},
211                 {CPM_CLK_SCC1, CPM_CLK3, 6},
212                 {CPM_CLK_SCC1, CPM_CLK4, 7},
213                 {CPM_CLK_SCC2, CPM_BRG1, 0},
214                 {CPM_CLK_SCC2, CPM_BRG2, 1},
215                 {CPM_CLK_SCC2, CPM_BRG3, 2},
216                 {CPM_CLK_SCC2, CPM_BRG4, 3},
217                 {CPM_CLK_SCC2, CPM_CLK11, 4},
218                 {CPM_CLK_SCC2, CPM_CLK12, 5},
219                 {CPM_CLK_SCC2, CPM_CLK3, 6},
220                 {CPM_CLK_SCC2, CPM_CLK4, 7},
221                 {CPM_CLK_SCC3, CPM_BRG1, 0},
222                 {CPM_CLK_SCC3, CPM_BRG2, 1},
223                 {CPM_CLK_SCC3, CPM_BRG3, 2},
224                 {CPM_CLK_SCC3, CPM_BRG4, 3},
225                 {CPM_CLK_SCC3, CPM_CLK5, 4},
226                 {CPM_CLK_SCC3, CPM_CLK6, 5},
227                 {CPM_CLK_SCC3, CPM_CLK7, 6},
228                 {CPM_CLK_SCC3, CPM_CLK8, 7},
229                 {CPM_CLK_SCC4, CPM_BRG1, 0},
230                 {CPM_CLK_SCC4, CPM_BRG2, 1},
231                 {CPM_CLK_SCC4, CPM_BRG3, 2},
232                 {CPM_CLK_SCC4, CPM_BRG4, 3},
233                 {CPM_CLK_SCC4, CPM_CLK5, 4},
234                 {CPM_CLK_SCC4, CPM_CLK6, 5},
235                 {CPM_CLK_SCC4, CPM_CLK7, 6},
236                 {CPM_CLK_SCC4, CPM_CLK8, 7},
237         };
238
239         im_cpmux = cpm2_map(im_cpmux);
240
241         switch (target) {
242         case CPM_CLK_SCC1:
243                 reg = &im_cpmux->cmx_scr;
244                 shift = 24;
245         case CPM_CLK_SCC2:
246                 reg = &im_cpmux->cmx_scr;
247                 shift = 16;
248                 break;
249         case CPM_CLK_SCC3:
250                 reg = &im_cpmux->cmx_scr;
251                 shift = 8;
252                 break;
253         case CPM_CLK_SCC4:
254                 reg = &im_cpmux->cmx_scr;
255                 shift = 0;
256                 break;
257         case CPM_CLK_FCC1:
258                 reg = &im_cpmux->cmx_fcr;
259                 shift = 24;
260                 break;
261         case CPM_CLK_FCC2:
262                 reg = &im_cpmux->cmx_fcr;
263                 shift = 16;
264                 break;
265         case CPM_CLK_FCC3:
266                 reg = &im_cpmux->cmx_fcr;
267                 shift = 8;
268                 break;
269         default:
270                 printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
271                 return -EINVAL;
272         }
273
274         if (mode == CPM_CLK_RX)
275                 shift += 3;
276
277         for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
278                 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
279                         bits = clk_map[i][2];
280                         break;
281                 }
282         }
283         if (i == ARRAY_SIZE(clk_map))
284             ret = -EINVAL;
285
286         bits <<= shift;
287         mask <<= shift;
288
289         out_be32(reg, (in_be32(reg) & ~mask) | bits);
290
291         cpm2_unmap(im_cpmux);
292         return ret;
293 }
294
295 int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
296 {
297         int ret = 0;
298         int shift;
299         int i, bits = 0;
300         cpmux_t __iomem *im_cpmux;
301         u8 __iomem *reg;
302         u8 mask = 3;
303
304         u8 clk_map[][3] = {
305                 {CPM_CLK_SMC1, CPM_BRG1, 0},
306                 {CPM_CLK_SMC1, CPM_BRG7, 1},
307                 {CPM_CLK_SMC1, CPM_CLK7, 2},
308                 {CPM_CLK_SMC1, CPM_CLK9, 3},
309                 {CPM_CLK_SMC2, CPM_BRG2, 0},
310                 {CPM_CLK_SMC2, CPM_BRG8, 1},
311                 {CPM_CLK_SMC2, CPM_CLK4, 2},
312                 {CPM_CLK_SMC2, CPM_CLK15, 3},
313         };
314
315         im_cpmux = cpm2_map(im_cpmux);
316
317         switch (target) {
318         case CPM_CLK_SMC1:
319                 reg = &im_cpmux->cmx_smr;
320                 mask = 3;
321                 shift = 4;
322                 break;
323         case CPM_CLK_SMC2:
324                 reg = &im_cpmux->cmx_smr;
325                 mask = 3;
326                 shift = 0;
327                 break;
328         default:
329                 printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
330                 return -EINVAL;
331         }
332
333         for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
334                 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
335                         bits = clk_map[i][2];
336                         break;
337                 }
338         }
339         if (i == ARRAY_SIZE(clk_map))
340             ret = -EINVAL;
341
342         bits <<= shift;
343         mask <<= shift;
344
345         out_8(reg, (in_8(reg) & ~mask) | bits);
346
347         cpm2_unmap(im_cpmux);
348         return ret;
349 }
350
351 #ifndef CONFIG_PPC_CPM_NEW_BINDING
352 /*
353  * dpalloc / dpfree bits.
354  */
355 static spinlock_t cpm_dpmem_lock;
356 /* 16 blocks should be enough to satisfy all requests
357  * until the memory subsystem goes up... */
358 static rh_block_t cpm_boot_dpmem_rh_block[16];
359 static rh_info_t cpm_dpmem_info;
360 static u8 __iomem *im_dprambase;
361
362 static void cpm2_dpinit(void)
363 {
364         spin_lock_init(&cpm_dpmem_lock);
365
366         /* initialize the info header */
367         rh_init(&cpm_dpmem_info, 1,
368                         sizeof(cpm_boot_dpmem_rh_block) /
369                         sizeof(cpm_boot_dpmem_rh_block[0]),
370                         cpm_boot_dpmem_rh_block);
371
372         im_dprambase = cpm2_immr;
373
374         /* Attach the usable dpmem area */
375         /* XXX: This is actually crap. CPM_DATAONLY_BASE and
376          * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
377          * varies with the processor and the microcode patches activated.
378          * But the following should be at least safe.
379          */
380         rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
381 }
382
383 /* This function returns an index into the DPRAM area.
384  */
385 unsigned long cpm_dpalloc(uint size, uint align)
386 {
387         unsigned long start;
388         unsigned long flags;
389
390         spin_lock_irqsave(&cpm_dpmem_lock, flags);
391         cpm_dpmem_info.alignment = align;
392         start = rh_alloc(&cpm_dpmem_info, size, "commproc");
393         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
394
395         return (uint)start;
396 }
397 EXPORT_SYMBOL(cpm_dpalloc);
398
399 int cpm_dpfree(unsigned long offset)
400 {
401         int ret;
402         unsigned long flags;
403
404         spin_lock_irqsave(&cpm_dpmem_lock, flags);
405         ret = rh_free(&cpm_dpmem_info, offset);
406         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
407
408         return ret;
409 }
410 EXPORT_SYMBOL(cpm_dpfree);
411
412 /* not sure if this is ever needed */
413 unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
414 {
415         unsigned long start;
416         unsigned long flags;
417
418         spin_lock_irqsave(&cpm_dpmem_lock, flags);
419         cpm_dpmem_info.alignment = align;
420         start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
421         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
422
423         return start;
424 }
425 EXPORT_SYMBOL(cpm_dpalloc_fixed);
426
427 void cpm_dpdump(void)
428 {
429         rh_dump(&cpm_dpmem_info);
430 }
431 EXPORT_SYMBOL(cpm_dpdump);
432
433 void *cpm_dpram_addr(unsigned long offset)
434 {
435         return (void *)(im_dprambase + offset);
436 }
437 EXPORT_SYMBOL(cpm_dpram_addr);
438 #endif /* !CONFIG_PPC_CPM_NEW_BINDING */
439
440 struct cpm2_ioports {
441         u32 dir, par, sor, odr, dat;
442         u32 res[3];
443 };
444
445 void cpm2_set_pin(int port, int pin, int flags)
446 {
447         struct cpm2_ioports __iomem *iop =
448                 (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
449
450         pin = 1 << (31 - pin);
451
452         if (flags & CPM_PIN_OUTPUT)
453                 setbits32(&iop[port].dir, pin);
454         else
455                 clrbits32(&iop[port].dir, pin);
456
457         if (!(flags & CPM_PIN_GPIO))
458                 setbits32(&iop[port].par, pin);
459         else
460                 clrbits32(&iop[port].par, pin);
461
462         if (flags & CPM_PIN_SECONDARY)
463                 setbits32(&iop[port].sor, pin);
464         else
465                 clrbits32(&iop[port].sor, pin);
466
467         if (flags & CPM_PIN_OPENDRAIN)
468                 setbits32(&iop[port].odr, pin);
469         else
470                 clrbits32(&iop[port].odr, pin);
471 }