]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/powerpc/quicc/v2_0/src/cpm.c
Initial revision
[karo-tx-redboot.git] / packages / hal / powerpc / quicc / v2_0 / src / cpm.c
1 //==========================================================================
2 //
3 //      cpm.c
4 //
5 //      PowerPC QUICC support functions
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 2003 Gary Thomas
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    Gary Thomas 
44 // Contributors: 
45 // Date:         2003-03-04
46 // Purpose:      Common support for the QUICC/CPM
47 // Description:  
48 //               
49 // Usage:
50 // Notes:        
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <pkgconf/hal.h>
57 #include <pkgconf/hal_powerpc_quicc.h>
58 #include <cyg/infra/cyg_type.h>
59 #include <cyg/infra/cyg_ass.h>
60 #include <cyg/hal/hal_arch.h>
61 #include <string.h>           // memset
62
63 // eCos headers decribing PowerQUICC:
64 #include <cyg/hal/quicc/ppc8xx.h>
65
66 // Information about DPRAM usage
67 // This lets the CPM/DPRAM information be shared by all environments
68 //
69 static short *nextBd = (short *)(CYGHWR_HAL_VSR_TABLE + 0x1F0);
70
71 /*
72  * Reset the communications processor
73  */
74
75 void
76 _mpc8xx_reset_cpm(void)
77 {
78     EPPC *eppc = eppc_base();
79     static int init_done = 0;
80
81     if (init_done) return;
82     init_done++;
83
84     eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY;
85     memset(eppc->pram, 0, sizeof(eppc->pram));
86     while (eppc->cp_cr & QUICC_CPM_CR_BUSY)
87         CYG_EMPTY_STATEMENT;
88
89     *nextBd = QUICC_BD_BASE;
90 }
91
92 //
93 // Allocate a chunk of memory in the shared CPM memory, typically
94 // used for buffer descriptors, etc.  The length will be aligned
95 // to a multiple of 8 bytes.
96 //
97 unsigned short
98 _mpc8xx_allocBd(int len)
99 {
100     unsigned short bd;
101
102     bd = *nextBd;
103     if ((bd < QUICC_BD_BASE) || (bd > QUICC_BD_END)) {
104         // Most likely not set up - make a guess :-(
105         bd = *nextBd = QUICC_BD_BASE+0x400;
106     }
107     CYG_ASSERT((len & 0x7) == 0, "BD length must be multiple of 8 bytes");
108     len = (len + 7) & ~7;  // Multiple of 8 bytes
109     *nextBd += len;
110     CYG_ASSERT(*nextBd < QUICC_BD_END, "Out of buffer descriptors!");
111     if (*nextBd >= QUICC_BD_END) {
112         *nextBd = QUICC_BD_BASE;
113     }
114     return bd;
115 }
116
117 #define BRG_MAX      4
118 #define BRG_UNAVAIL -1
119 #define BRG_FREE    -2
120 static unsigned long *brg[BRG_MAX];  // Available generators
121 static int alloc[BRG_MAX];           // Which port is assigned where
122                                      // -1 indicates unavailable
123                                      // -2 indicates free
124                                      // xx indicates port assignment
125
126 static void
127 _mpc8xx_mark_brg(int port, int brgnum)
128 {
129     if (brgnum >= BRG_MAX) {
130         return;  // Invalid selection
131     }
132     if (alloc[brgnum] == BRG_FREE) {
133         // Allocation unknown
134         alloc[brgnum] = port;
135     }
136 }
137
138 unsigned long *
139 _mpc8xx_allocate_brg(int port)
140 {
141     EPPC *eppc = eppc_base();
142     static int init = 0;
143     int brgnum;
144
145     if (!init) {
146         // Set up available pool
147 #if defined(CYGHWR_HAL_POWERPC_MPC8XX_852T)
148         // The 852T variant only has BRG3/BRG4
149         alloc[0] = BRG_UNAVAIL;
150         alloc[1] = BRG_UNAVAIL;
151 #else
152         brg[0] = (unsigned long *)&eppc->brgc1;  alloc[0] = BRG_FREE;
153         brg[1] = (unsigned long *)&eppc->brgc2;  alloc[1] = BRG_FREE;
154 #endif
155         brg[2] = (unsigned long *)&eppc->brgc3;  alloc[2] = BRG_FREE;
156         brg[3] = (unsigned long *)&eppc->brgc4;  alloc[3] = BRG_FREE;
157 #if !defined(CYGSEM_HAL_ROM_MONITOR)
158         // Figure out how hardware was set by previous ROM monitor
159 #if CYGNUM_HAL_QUICC_SMC1 > 0
160         _mpc8xx_mark_brg(QUICC_CPM_SMC1, (eppc->si_simode >> 12) & 0x07);
161 #endif
162 #if CYGNUM_HAL_QUICC_SMC2 > 0
163         _mpc8xx_mark_brg(QUICC_CPM_SMC2, (eppc->si_simode >> 28) & 0x07);
164 #endif
165 #if CYGNUM_HAL_QUICC_SCC1 > 0
166         _mpc8xx_mark_brg(QUICC_CPM_SCC1, (eppc->si_sicr >> 0) & 0x07);
167 #endif
168 #if CYGNUM_HAL_QUICC_SCC2 > 0
169         _mpc8xx_mark_brg(QUICC_CPM_SCC2, (eppc->si_sicr >> 8) & 0x07);
170 #endif
171 #if CYGNUM_HAL_QUICC_SCC3 > 0
172         _mpc8xx_mark_brg(QUICC_CPM_SCC3, (eppc->si_sicr >> 16) & 0x07);
173 #endif
174 #if CYGNUM_HAL_QUICC_SCC4 > 0
175         _mpc8xx_mark_brg(QUICC_CPM_SCC4, (eppc->si_sicr >> 24) & 0x07);
176 #endif
177 #endif
178         init = 1;
179     }
180     // Find a free generator (or if port has already been assigned)
181     for (brgnum = 0;  brgnum < BRG_MAX;  brgnum++) {
182         if (alloc[brgnum] >= 0) {
183             // See if it is for this port
184             if (alloc[brgnum] == port) {
185                 // It is - just reuse it (already set up)
186                 return brg[brgnum];
187             }
188         }
189     }
190     // Not currently assigned, try and find a free one
191     for (brgnum = 0;  brgnum < BRG_MAX;  brgnum++) {
192         if (alloc[brgnum] == BRG_FREE) {
193             // Allocate to this port.
194             alloc[brgnum] = port;
195             break;
196         }
197     }
198     CYG_ASSERT(brgnum < BRG_MAX, "Out of baud rate generators!");
199     // If no generator found - punt!
200     if (brgnum == BRG_MAX) {
201         brgnum = BRG_MAX-1;
202     }
203     // Set up clock routing for new assignment
204     switch (port) {
205 #if CYGNUM_HAL_QUICC_SMC1 > 0
206     case QUICC_CPM_SMC1:
207         eppc->si_simode = (eppc->si_simode & ~(0x07<<12)) | (brgnum<<12);
208         break;
209 #endif
210 #if CYGNUM_HAL_QUICC_SMC2 > 0
211     case QUICC_CPM_SMC2:
212         eppc->si_simode = (eppc->si_simode & ~(0x07<<28)) | (brgnum<<28);
213         break;
214 #endif
215 #if CYGNUM_HAL_QUICC_SCC1 > 0
216     case QUICC_CPM_SCC1:
217         eppc->si_sicr = (eppc->si_sicr & ~(0xFF<<0)) | (((brgnum<<3)|(brgnum<<0))<<0);
218         break;
219 #endif
220 #if CYGNUM_HAL_QUICC_SCC2 > 0
221     case QUICC_CPM_SCC2:
222         eppc->si_sicr = (eppc->si_sicr & ~(0xFF<<8)) | (((brgnum<<3)|(brgnum<<0))<<8);
223         break;
224 #endif
225 #if CYGNUM_HAL_QUICC_SCC3 > 0
226     case QUICC_CPM_SCC3:
227         eppc->si_sicr = (eppc->si_sicr & ~(0xFF<<16)) | (((brgnum<<3)|(brgnum<<0))<<16);
228         break;
229 #endif
230 #if CYGNUM_HAL_QUICC_SCC4 > 0
231     case QUICC_CPM_SCC4:
232         eppc->si_sicr = (eppc->si_sicr & ~(0xFF<<24)) | (((brgnum<<3)|(brgnum<<0))<<24);
233         break;
234 #endif
235     }
236     return brg[brgnum];
237 }
238
239 // EOF cpm.c