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