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