Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[pandora-kernel.git] / arch / ppc / 8xx_io / commproc.c
1 /*
2  * General Purpose functions for the global management of the
3  * Communication Processor Module.
4  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
5  *
6  * In addition to the individual control of the communication
7  * channels, there are a few functions that globally affect the
8  * communication processor.
9  *
10  * Buffer descriptors must be allocated from the dual ported memory
11  * space.  The allocator for that is here.  When the communication
12  * process is reset, we reclaim the memory available.  There is
13  * currently no deallocator for this memory.
14  * The amount of space available is platform dependent.  On the
15  * MBX, the EPPC software loads additional microcode into the
16  * communication processor, and uses some of the DP ram for this
17  * purpose.  Current, the first 512 bytes and the last 256 bytes of
18  * memory are used.  Right now I am conservative and only use the
19  * memory that can never be used for microcode.  If there are
20  * applications that require more DP ram, we can expand the boundaries
21  * but then we have to be careful of any downloaded microcode.
22  */
23 #include <linux/errno.h>
24 #include <linux/sched.h>
25 #include <linux/kernel.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/param.h>
28 #include <linux/string.h>
29 #include <linux/mm.h>
30 #include <linux/interrupt.h>
31 #include <linux/irq.h>
32 #include <linux/module.h>
33 #include <asm/mpc8xx.h>
34 #include <asm/page.h>
35 #include <asm/pgtable.h>
36 #include <asm/8xx_immap.h>
37 #include <asm/cpm1.h>
38 #include <asm/io.h>
39 #include <asm/tlbflush.h>
40 #include <asm/rheap.h>
41
42 #define immr_map(member)                                                \
43 ({                                                                      \
44         u32 offset = offsetof(immap_t, member);                         \
45         void *addr = ioremap (IMAP_ADDR + offset,                       \
46                               FIELD_SIZEOF(immap_t, member));           \
47         addr;                                                           \
48 })
49
50 #define immr_map_size(member, size)                                     \
51 ({                                                                      \
52         u32 offset = offsetof(immap_t, member);                         \
53         void *addr = ioremap (IMAP_ADDR + offset, size);                \
54         addr;                                                           \
55 })
56
57 static void m8xx_cpm_dpinit(void);
58 cpm8xx_t        *cpmp;          /* Pointer to comm processor space */
59
60 /* CPM interrupt vector functions.
61 */
62 struct  cpm_action {
63         void    (*handler)(void *);
64         void    *dev_id;
65 };
66 static  struct  cpm_action cpm_vecs[CPMVEC_NR];
67 static  irqreturn_t cpm_interrupt(int irq, void * dev);
68 static  irqreturn_t cpm_error_interrupt(int irq, void *dev);
69 /* Define a table of names to identify CPM interrupt handlers in
70  * /proc/interrupts.
71  */
72 const char *cpm_int_name[] =
73         { "error",      "PC4",          "PC5",          "SMC2",
74           "SMC1",       "SPI",          "PC6",          "Timer 4",
75           "",           "PC7",          "PC8",          "PC9",
76           "Timer 3",    "",             "PC10",         "PC11",
77           "I2C",        "RISC Timer",   "Timer 2",      "",
78           "IDMA2",      "IDMA1",        "SDMA error",   "PC12",
79           "PC13",       "Timer 1",      "PC14",         "SCC4",
80           "SCC3",       "SCC2",         "SCC1",         "PC15"
81         };
82
83 static void
84 cpm_mask_irq(unsigned int irq)
85 {
86         int cpm_vec = irq - CPM_IRQ_OFFSET;
87
88         clrbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec));
89 }
90
91 static void
92 cpm_unmask_irq(unsigned int irq)
93 {
94         int cpm_vec = irq - CPM_IRQ_OFFSET;
95
96         setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, (1 << cpm_vec));
97 }
98
99 static void
100 cpm_ack(unsigned int irq)
101 {
102         /* We do not need to do anything here. */
103 }
104
105 static void
106 cpm_eoi(unsigned int irq)
107 {
108         int cpm_vec = irq - CPM_IRQ_OFFSET;
109
110         out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr, (1 << cpm_vec));
111 }
112
113 struct hw_interrupt_type cpm_pic = {
114         .typename       = " CPM      ",
115         .enable         = cpm_unmask_irq,
116         .disable        = cpm_mask_irq,
117         .ack            = cpm_ack,
118         .end            = cpm_eoi,
119 };
120
121 void
122 m8xx_cpm_reset(void)
123 {
124         volatile immap_t         *imp;
125         volatile cpm8xx_t       *commproc;
126
127         imp = (immap_t *)IMAP_ADDR;
128         commproc = (cpm8xx_t *)&imp->im_cpm;
129
130 #ifdef CONFIG_UCODE_PATCH
131         /* Perform a reset.
132         */
133         commproc->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
134
135         /* Wait for it.
136         */
137         while (commproc->cp_cpcr & CPM_CR_FLG);
138
139         cpm_load_patch(imp);
140 #endif
141
142         /* Set SDMA Bus Request priority 5.
143          * On 860T, this also enables FEC priority 6.  I am not sure
144          * this is what we really want for some applications, but the
145          * manual recommends it.
146          * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
147          */
148         out_be32(&imp->im_siu_conf.sc_sdcr, 1),
149
150         /* Reclaim the DP memory for our use. */
151         m8xx_cpm_dpinit();
152
153         /* Tell everyone where the comm processor resides.
154         */
155         cpmp = (cpm8xx_t *)commproc;
156 }
157
158 /* This is called during init_IRQ.  We used to do it above, but this
159  * was too early since init_IRQ was not yet called.
160  */
161 static struct irqaction cpm_error_irqaction = {
162         .handler = cpm_error_interrupt,
163         .mask = CPU_MASK_NONE,
164 };
165 static struct irqaction cpm_interrupt_irqaction = {
166         .handler = cpm_interrupt,
167         .mask = CPU_MASK_NONE,
168         .name = "CPM cascade",
169 };
170
171 void
172 cpm_interrupt_init(void)
173 {
174         int i;
175
176         /* Initialize the CPM interrupt controller.
177         */
178         out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr,
179             (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
180                 ((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK);
181         out_be32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr, 0);
182
183         /* install the CPM interrupt controller routines for the CPM
184          * interrupt vectors
185          */
186         for ( i = CPM_IRQ_OFFSET ; i < CPM_IRQ_OFFSET + NR_CPM_INTS ; i++ )
187                 irq_desc[i].chip = &cpm_pic;
188
189         /* Set our interrupt handler with the core CPU. */
190         if (setup_irq(CPM_INTERRUPT, &cpm_interrupt_irqaction))
191                 panic("Could not allocate CPM IRQ!");
192
193         /* Install our own error handler. */
194         cpm_error_irqaction.name = cpm_int_name[CPMVEC_ERROR];
195         if (setup_irq(CPM_IRQ_OFFSET + CPMVEC_ERROR, &cpm_error_irqaction))
196                 panic("Could not allocate CPM error IRQ!");
197
198         setbits32(&((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr, CICR_IEN);
199 }
200
201 /*
202  * Get the CPM interrupt vector.
203  */
204 int
205 cpm_get_irq(void)
206 {
207         int cpm_vec;
208
209         /* Get the vector by setting the ACK bit and then reading
210          * the register.
211          */
212         out_be16(&((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr, 1);
213         cpm_vec = in_be16(&((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr);
214         cpm_vec >>= 11;
215
216         return cpm_vec;
217 }
218
219 /* CPM interrupt controller cascade interrupt.
220 */
221 static  irqreturn_t
222 cpm_interrupt(int irq, void * dev)
223 {
224         /* This interrupt handler never actually gets called.  It is
225          * installed only to unmask the CPM cascade interrupt in the SIU
226          * and to make the CPM cascade interrupt visible in /proc/interrupts.
227          */
228         return IRQ_HANDLED;
229 }
230
231 /* The CPM can generate the error interrupt when there is a race condition
232  * between generating and masking interrupts.  All we have to do is ACK it
233  * and return.  This is a no-op function so we don't need any special
234  * tests in the interrupt handler.
235  */
236 static  irqreturn_t
237 cpm_error_interrupt(int irq, void *dev)
238 {
239         return IRQ_HANDLED;
240 }
241
242 /* A helper function to translate the handler prototype required by
243  * request_irq() to the handler prototype required by cpm_install_handler().
244  */
245 static irqreturn_t
246 cpm_handler_helper(int irq, void *dev_id)
247 {
248         int cpm_vec = irq - CPM_IRQ_OFFSET;
249
250         (*cpm_vecs[cpm_vec].handler)(dev_id);
251
252         return IRQ_HANDLED;
253 }
254
255 /* Install a CPM interrupt handler.
256  * This routine accepts a CPM interrupt vector in the range 0 to 31.
257  * This routine is retained for backward compatibility.  Rather than using
258  * this routine to install a CPM interrupt handler, you can now use
259  * request_irq() with an IRQ in the range CPM_IRQ_OFFSET to
260  * CPM_IRQ_OFFSET + NR_CPM_INTS - 1 (16 to 47).
261  *
262  * Notice that the prototype of the interrupt handler function must be
263  * different depending on whether you install the handler with
264  * request_irq() or cpm_install_handler().
265  */
266 void
267 cpm_install_handler(int cpm_vec, void (*handler)(void *), void *dev_id)
268 {
269         int err;
270
271         /* If null handler, assume we are trying to free the IRQ.
272         */
273         if (!handler) {
274                 free_irq(CPM_IRQ_OFFSET + cpm_vec, dev_id);
275                 return;
276         }
277
278         if (cpm_vecs[cpm_vec].handler != 0)
279                 printk(KERN_INFO "CPM interrupt %x replacing %x\n",
280                         (uint)handler, (uint)cpm_vecs[cpm_vec].handler);
281         cpm_vecs[cpm_vec].handler = handler;
282         cpm_vecs[cpm_vec].dev_id = dev_id;
283
284         if ((err = request_irq(CPM_IRQ_OFFSET + cpm_vec, cpm_handler_helper,
285                                         0, cpm_int_name[cpm_vec], dev_id)))
286                 printk(KERN_ERR "request_irq() returned %d for CPM vector %d\n",
287                                 err, cpm_vec);
288 }
289
290 /* Free a CPM interrupt handler.
291  * This routine accepts a CPM interrupt vector in the range 0 to 31.
292  * This routine is retained for backward compatibility.
293  */
294 void
295 cpm_free_handler(int cpm_vec)
296 {
297         request_irq(CPM_IRQ_OFFSET + cpm_vec, NULL, 0, 0,
298                 cpm_vecs[cpm_vec].dev_id);
299
300         cpm_vecs[cpm_vec].handler = NULL;
301         cpm_vecs[cpm_vec].dev_id = NULL;
302 }
303
304 /* Set a baud rate generator.  This needs lots of work.  There are
305  * four BRGs, any of which can be wired to any channel.
306  * The internal baud rate clock is the system clock divided by 16.
307  * This assumes the baudrate is 16x oversampled by the uart.
308  */
309 #define BRG_INT_CLK             (((bd_t *)__res)->bi_intfreq)
310 #define BRG_UART_CLK            (BRG_INT_CLK/16)
311 #define BRG_UART_CLK_DIV16      (BRG_UART_CLK/16)
312
313 void
314 cpm_setbrg(uint brg, uint rate)
315 {
316         volatile uint   *bp;
317
318         /* This is good enough to get SMCs running.....
319         */
320         bp = (uint *)&cpmp->cp_brgc1;
321         bp += brg;
322         /* The BRG has a 12-bit counter.  For really slow baud rates (or
323          * really fast processors), we may have to further divide by 16.
324          */
325         if (((BRG_UART_CLK / rate) - 1) < 4096)
326                 *bp = (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN;
327         else
328                 *bp = (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
329                                                 CPM_BRG_EN | CPM_BRG_DIV16;
330 }
331
332 /*
333  * dpalloc / dpfree bits.
334  */
335 static spinlock_t cpm_dpmem_lock;
336 /*
337  * 16 blocks should be enough to satisfy all requests
338  * until the memory subsystem goes up...
339  */
340 static rh_block_t cpm_boot_dpmem_rh_block[16];
341 static rh_info_t cpm_dpmem_info;
342
343 #define CPM_DPMEM_ALIGNMENT     8
344 static u8* dpram_vbase;
345 static uint dpram_pbase;
346
347 void m8xx_cpm_dpinit(void)
348 {
349         spin_lock_init(&cpm_dpmem_lock);
350
351         dpram_vbase = immr_map_size(im_cpm.cp_dpmem, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
352         dpram_pbase = (uint)&((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem;
353
354         /* Initialize the info header */
355         rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
356                         sizeof(cpm_boot_dpmem_rh_block) /
357                         sizeof(cpm_boot_dpmem_rh_block[0]),
358                         cpm_boot_dpmem_rh_block);
359
360         /*
361          * Attach the usable dpmem area.
362          * XXX: This is actually crap.  CPM_DATAONLY_BASE and
363          * CPM_DATAONLY_SIZE are a subset of the available dparm.  It varies
364          * with the processor and the microcode patches applied / activated.
365          * But the following should be at least safe.
366          */
367         rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
368 }
369
370 /*
371  * Allocate the requested size worth of DP memory.
372  * This function returns an offset into the DPRAM area.
373  * Use cpm_dpram_addr() to get the virtual address of the area.
374  */
375 unsigned long cpm_dpalloc(uint size, uint align)
376 {
377         unsigned long start;
378         unsigned long flags;
379
380         spin_lock_irqsave(&cpm_dpmem_lock, flags);
381         cpm_dpmem_info.alignment = align;
382         start = rh_alloc(&cpm_dpmem_info, size, "commproc");
383         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
384
385         return start;
386 }
387 EXPORT_SYMBOL(cpm_dpalloc);
388
389 int cpm_dpfree(unsigned long offset)
390 {
391         int ret;
392         unsigned long flags;
393
394         spin_lock_irqsave(&cpm_dpmem_lock, flags);
395         ret = rh_free(&cpm_dpmem_info, offset);
396         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
397
398         return ret;
399 }
400 EXPORT_SYMBOL(cpm_dpfree);
401
402 unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
403 {
404         unsigned long start;
405         unsigned long flags;
406
407         spin_lock_irqsave(&cpm_dpmem_lock, flags);
408         cpm_dpmem_info.alignment = align;
409         start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
410         spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
411
412         return start;
413 }
414 EXPORT_SYMBOL(cpm_dpalloc_fixed);
415
416 void cpm_dpdump(void)
417 {
418         rh_dump(&cpm_dpmem_info);
419 }
420 EXPORT_SYMBOL(cpm_dpdump);
421
422 void *cpm_dpram_addr(unsigned long offset)
423 {
424         return (void *)(dpram_vbase + offset);
425 }
426 EXPORT_SYMBOL(cpm_dpram_addr);
427
428 uint cpm_dpram_phys(u8* addr)
429 {
430         return (dpram_pbase + (uint)(addr - dpram_vbase));
431 }
432 EXPORT_SYMBOL(cpm_dpram_phys);