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_cpm2.h>
30 #include <asm/cpm2.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 cpm_cpm2_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 cpm2_map_t		*cpm2_immr;
42 
43 void
cpm2_reset(void)44 cpm2_reset(void)
45 {
46 	volatile cpm2_map_t	 *imp;
47 	volatile cpm_cpm2_t	*commproc;
48 	uint			vpgaddr;
49 
50 	cpm2_immr = imp = (volatile cpm2_map_t *)CPM_MAP_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 = (cpm_cpm2_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
cpm2_dpalloc(uint size,uint align)76 cpm2_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
cpm2_hostalloc(uint size,uint align)103 cpm2_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
cpm2_setbrg(uint brg,uint rate)143 cpm2_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 *)&cpm2_immr->im_brgc1;
151 	}
152 	else {
153 		bp = (uint *)&cpm2_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
cpm2_fastbrg(uint brg,uint rate,int div16)164 cpm2_fastbrg(uint brg, uint rate, int div16)
165 {
166 	volatile uint	*bp;
167 
168 	if (brg < 4) {
169 		bp = (uint *)&cpm2_immr->im_brgc1;
170 	}
171 	else {
172 		bp = (uint *)&cpm2_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 }
180