ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / 8260_io / commproc.c
1 /*
2  * General Purpose functions for the global management of the
3  * 8260 Communication Processor Module.
4  * Copyright (c) 1999 Dan Malek (dmalek@jlc.net)
5  * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
6  *      2.3.99 Updates
7  *
8  * In addition to the individual control of the communication
9  * channels, there are a few functions that globally affect the
10  * communication processor.
11  *
12  * Buffer descriptors must be allocated from the dual ported memory
13  * space.  The allocator for that is here.  When the communication
14  * process is reset, we reclaim the memory available.  There is
15  * currently no deallocator for this memory.
16  */
17 #include <linux/errno.h>
18 #include <linux/sched.h>
19 #include <linux/kernel.h>
20 #include <linux/param.h>
21 #include <linux/string.h>
22 #include <linux/mm.h>
23 #include <linux/interrupt.h>
24 #include <linux/bootmem.h>
25 #include <asm/irq.h>
26 #include <asm/mpc8260.h>
27 #include <asm/page.h>
28 #include <asm/pgtable.h>
29 #include <asm/immap_8260.h>
30 #include <asm/cpm_8260.h>
31
32 static  uint    dp_alloc_base;  /* Starting offset in DP ram */
33 static  uint    dp_alloc_top;   /* Max offset + 1 */
34 static  uint    host_buffer;    /* One page of host buffer */
35 static  uint    host_end;       /* end + 1 */
36 cpm8260_t       *cpmp;          /* Pointer to comm processor space */
37
38 /* We allocate this here because it is used almost exclusively for
39  * the communication processor devices.
40  */
41 immap_t         *immr;
42
43 void
44 m8260_cpm_reset(void)
45 {
46         volatile immap_t         *imp;
47         volatile cpm8260_t      *commproc;
48         uint                    vpgaddr;
49
50         immr = imp = (volatile immap_t *)IMAP_ADDR;
51         commproc = &imp->im_cpm;
52
53         /* Reclaim the DP memory for our use.
54         */
55         dp_alloc_base = CPM_DATAONLY_BASE;
56         dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
57
58         /* Set the host page for allocation.
59         */
60         host_buffer =
61                 (uint) alloc_bootmem_pages(PAGE_SIZE * NUM_CPM_HOST_PAGES);
62         host_end = host_buffer + (PAGE_SIZE * NUM_CPM_HOST_PAGES);
63
64         vpgaddr = host_buffer;
65
66         /* Tell everyone where the comm processor resides.
67         */
68         cpmp = (cpm8260_t *)commproc;
69 }
70
71 /* Allocate some memory from the dual ported ram.
72  * To help protocols with object alignment restrictions, we do that
73  * if they ask.
74  */
75 uint
76 m8260_cpm_dpalloc(uint size, uint align)
77 {
78         uint    retloc;
79         uint    align_mask, off;
80         uint    savebase;
81
82         align_mask = align - 1;
83         savebase = dp_alloc_base;
84
85         if ((off = (dp_alloc_base & align_mask)) != 0)
86                 dp_alloc_base += (align - off);
87
88         if ((dp_alloc_base + size) >= dp_alloc_top) {
89                 dp_alloc_base = savebase;
90                 return(CPM_DP_NOSPACE);
91         }
92
93         retloc = dp_alloc_base;
94         dp_alloc_base += size;
95
96         return(retloc);
97 }
98
99 /* We also own one page of host buffer space for the allocation of
100  * UART "fifos" and the like.
101  */
102 uint
103 m8260_cpm_hostalloc(uint size, uint align)
104 {
105         uint    retloc;
106         uint    align_mask, off;
107         uint    savebase;
108
109         align_mask = align - 1;
110         savebase = host_buffer;
111
112         if ((off = (host_buffer & align_mask)) != 0)
113                 host_buffer += (align - off);
114
115         if ((host_buffer + size) >= host_end) {
116                 host_buffer = savebase;
117                 return(0);
118         }
119
120         retloc = host_buffer;
121         host_buffer += size;
122
123         return(retloc);
124 }
125
126 /* Set a baud rate generator.  This needs lots of work.  There are
127  * eight BRGs, which can be connected to the CPM channels or output
128  * as clocks.  The BRGs are in two different block of internal
129  * memory mapped space.
130  * The baud rate clock is the system clock divided by something.
131  * It was set up long ago during the initial boot phase and is
132  * is given to us.
133  * Baud rate clocks are zero-based in the driver code (as that maps
134  * to port numbers).  Documentation uses 1-based numbering.
135  */
136 #define BRG_INT_CLK     (((bd_t *)__res)->bi_brgfreq)
137 #define BRG_UART_CLK    (BRG_INT_CLK/16)
138
139 /* This function is used by UARTS, or anything else that uses a 16x
140  * oversampled clock.
141  */
142 void
143 m8260_cpm_setbrg(uint brg, uint rate)
144 {
145         volatile uint   *bp;
146
147         /* This is good enough to get SMCs running.....
148         */
149         if (brg < 4) {
150                 bp = (uint *)&immr->im_brgc1;
151         }
152         else {
153                 bp = (uint *)&immr->im_brgc5;
154                 brg -= 4;
155         }
156         bp += brg;
157         *bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
158 }
159
160 /* This function is used to set high speed synchronous baud rate
161  * clocks.
162  */
163 void
164 m8260_cpm_fastbrg(uint brg, uint rate, int div16)
165 {
166         volatile uint   *bp;
167
168         if (brg < 4) {
169                 bp = (uint *)&immr->im_brgc1;
170         }
171         else {
172                 bp = (uint *)&immr->im_brgc5;
173                 brg -= 4;
174         }
175         bp += brg;
176         *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
177         if (div16)
178                 *bp |= CPM_BRG_DIV16;
179 }