1*458db832SDavid du Colombier #include "u.h"
2*458db832SDavid du Colombier #include "../port/lib.h"
3*458db832SDavid du Colombier #include "mem.h"
4*458db832SDavid du Colombier #include "dat.h"
5*458db832SDavid du Colombier #include "fns.h"
6*458db832SDavid du Colombier #include "io.h"
7*458db832SDavid du Colombier #include "../port/error.h"
8*458db832SDavid du Colombier
9*458db832SDavid du Colombier /*
10*458db832SDavid du Colombier *
11*458db832SDavid du Colombier * mcc.c
12*458db832SDavid du Colombier *
13*458db832SDavid du Colombier * This is the driver for the Multi-Channel Communications Controller
14*458db832SDavid du Colombier * of the MPC8260. This version is constructed for the EST SBC8260 to
15*458db832SDavid du Colombier * handle data from an interface to an offboard T1 framer. The driver
16*458db832SDavid du Colombier * supports MCC2 + TDM A:2 (channel 128) which is connected to the
17*458db832SDavid du Colombier * external interface.
18*458db832SDavid du Colombier *
19*458db832SDavid du Colombier * Neville Chandler
20*458db832SDavid du Colombier * Lucent Technologies - Bell Labs
21*458db832SDavid du Colombier * March 2001
22*458db832SDavid du Colombier *
23*458db832SDavid du Colombier */
24*458db832SDavid du Colombier
25*458db832SDavid du Colombier #define PKT_LEN 40
26*458db832SDavid du Colombier #define MPC82XX_INIT_DELAY 0x10000
27*458db832SDavid du Colombier
28*458db832SDavid du Colombier #define HPIC 0xFC000000
29*458db832SDavid du Colombier #define HPIA 0xFC000010
30*458db832SDavid du Colombier #define HPID_A 0xFC000020
31*458db832SDavid du Colombier #define HPID 0xFC000030
32*458db832SDavid du Colombier
33*458db832SDavid du Colombier
34*458db832SDavid du Colombier #include "mcc2.h"
35*458db832SDavid du Colombier
36*458db832SDavid du Colombier static ssize_t mcc2_read( struct file *, char *, size_t, loff_t * );
37*458db832SDavid du Colombier static ssize_t mcc2_write( struct file *, const char *, size_t, loff_t *);
38*458db832SDavid du Colombier static loff_t mcc2_lseek( struct file *, loff_t, int );
39*458db832SDavid du Colombier static int mcc2_release( struct inode *, struct file * );
40*458db832SDavid du Colombier static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, unsigned long );
41*458db832SDavid du Colombier //static ssize_t mcc2_ioctl( struct inode *, struct file *, unsigned int, char * );
42*458db832SDavid du Colombier
43*458db832SDavid du Colombier void MPC82xxCpmInit( void );
44*458db832SDavid du Colombier void PortInit( void );
45*458db832SDavid du Colombier void PortSelectPin( unsigned short );
46*458db832SDavid du Colombier
47*458db832SDavid du Colombier void InitMemAlloc( void );
48*458db832SDavid du Colombier void HeapCreate( U32, U32, U32, U32, char *);
49*458db832SDavid du Colombier void HeapCreate( U32, U32, U32, U32, char *);
50*458db832SDavid du Colombier void *HeapSearchMem( U32, U32);
51*458db832SDavid du Colombier void *HeapAllocMem( U32, U32);
52*458db832SDavid du Colombier void HeapFreeMem( U32, void *);
53*458db832SDavid du Colombier
54*458db832SDavid du Colombier void InitLinkedList( void );
55*458db832SDavid du Colombier boolean DwCreateList( ListDB * );
56*458db832SDavid du Colombier void *DwMalloc( U32 );
57*458db832SDavid du Colombier void DwFree( U32, void * );
58*458db832SDavid du Colombier
59*458db832SDavid du Colombier void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
60*458db832SDavid du Colombier
61*458db832SDavid du Colombier #define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
62*458db832SDavid du Colombier
63*458db832SDavid du Colombier extern int ppc_spurious_interrupts;
64*458db832SDavid du Colombier extern int ppc_second_irq;
65*458db832SDavid du Colombier extern struct irqaction *ppc_irq_action[NR_IRQS];
66*458db832SDavid du Colombier extern unsigned int ppc_local_bh_count[NR_CPUS];
67*458db832SDavid du Colombier extern unsigned int ppc_local_irq_count[NR_CPUS];
68*458db832SDavid du Colombier extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
69*458db832SDavid du Colombier extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
70*458db832SDavid du Colombier extern atomic_t ppc_n_lost_interrupts;
71*458db832SDavid du Colombier
72*458db832SDavid du Colombier //static void disp_led( unsigned char );
73*458db832SDavid du Colombier
74*458db832SDavid du Colombier void Mcc2Init( void );
75*458db832SDavid du Colombier void MccDisable( unsigned char );
76*458db832SDavid du Colombier void MccEnable( unsigned char, unsigned char, unsigned char );
77*458db832SDavid du Colombier void MccRiscCmd( unsigned char, dwv_RISC_OPCODE, unsigned char );
78*458db832SDavid du Colombier boolean MccTest( void );
79*458db832SDavid du Colombier int MccTxBuffer( unsigned char, unsigned char, char *, unsigned short, unsigned short );
80*458db832SDavid du Colombier extern U32 PpcDisable( void );
81*458db832SDavid du Colombier extern void PpcMsrRestore( U32 );
82*458db832SDavid du Colombier
83*458db832SDavid du Colombier static int mcc2_major = MCC_MAJOR;
84*458db832SDavid du Colombier
85*458db832SDavid du Colombier static BOOLEAN insertBD_T( BD_PFIFO *, BD_P );
86*458db832SDavid du Colombier static BOOLEAN removBD_T( BD_PFIFO *, BD_P * );
87*458db832SDavid du Colombier BOOLEAN empty(volatile register FIFO *);
88*458db832SDavid du Colombier int insert( FIFO *, char * );
89*458db832SDavid du Colombier int remove( FIFO *, char ** );
90*458db832SDavid du Colombier void AppInit( void );
91*458db832SDavid du Colombier
92*458db832SDavid du Colombier #define physaddr(ADDR) (0x60020000 | ((ADDR) << 23) | (2 << 18))
93*458db832SDavid du Colombier
94*458db832SDavid du Colombier mcc_iorw_t mcc_iorw;
95*458db832SDavid du Colombier
96*458db832SDavid du Colombier #if 0
97*458db832SDavid du Colombier typedef struct mcc_io {
98*458db832SDavid du Colombier unsigned int cmd;
99*458db832SDavid du Colombier unsigned int address;
100*458db832SDavid du Colombier unsigned int *buf;
101*458db832SDavid du Colombier int ind;
102*458db832SDavid du Colombier int nbytes;
103*458db832SDavid du Colombier siramctl_t SiRam;
104*458db832SDavid du Colombier cpmux_t CpMux;
105*458db832SDavid du Colombier mcc_t Mcc_T;
106*458db832SDavid du Colombier iop8260_t Io_Ports;
107*458db832SDavid du Colombier } mcc_iorw_t;
108*458db832SDavid du Colombier #endif
109*458db832SDavid du Colombier
110*458db832SDavid du Colombier static void
ioctl_parm(unsigned int loop_mode)111*458db832SDavid du Colombier ioctl_parm( unsigned int loop_mode )
112*458db832SDavid du Colombier {
113*458db832SDavid du Colombier
114*458db832SDavid du Colombier /* Setup the SIMODE Register */
115*458db832SDavid du Colombier Si2Regs->SiAmr = SIxMR_SAD_BANK0_FIRST_HALF | /* SADx */
116*458db832SDavid du Colombier loop_mode | /* SDMx */
117*458db832SDavid du Colombier SIxMR_NO_BIT_RX_SYNC_DELAY | /* RFSDx */
118*458db832SDavid du Colombier SIxMR_DSC_CH_DATA_CLK_EQU | /* DSCx */
119*458db832SDavid du Colombier SIxMR_CRT_SPEPARATE_PINS | /* CRTx */
120*458db832SDavid du Colombier SIxMR_SLx_NORMAL_OPERATION | /* SLx */
121*458db832SDavid du Colombier SIxMR_CE_TX_RISING_RX_FALLING | /* CEx */
122*458db832SDavid du Colombier SIxMR_FE_FALLING_EDGE | /* FEx */
123*458db832SDavid du Colombier SIxMR_GM_GCI_SCIT_MODE | /* GMx */
124*458db832SDavid du Colombier SIxMR_NO_BIT_TX_SYNC_DELAY; /* TFSDx */
125*458db832SDavid du Colombier }
126*458db832SDavid du Colombier
127*458db832SDavid du Colombier #if 0
128*458db832SDavid du Colombier static void
disp_led(unsigned char byte)129*458db832SDavid du Colombier disp_led( unsigned char byte )
130*458db832SDavid du Colombier {
131*458db832SDavid du Colombier //int i;
132*458db832SDavid du Colombier
133*458db832SDavid du Colombier *leds = byte;
134*458db832SDavid du Colombier //for(i=0; i<1000; i++);
135*458db832SDavid du Colombier
136*458db832SDavid du Colombier }
137*458db832SDavid du Colombier #endif
138*458db832SDavid du Colombier
139*458db832SDavid du Colombier
140*458db832SDavid du Colombier
141*458db832SDavid du Colombier static ssize_t
mcc2_ioctl(struct inode * inode,struct file * file,unsigned int ioctl_cmd,unsigned long param)142*458db832SDavid du Colombier mcc2_ioctl( struct inode *inode, struct file *file,
143*458db832SDavid du Colombier unsigned int ioctl_cmd, // IOCTL number
144*458db832SDavid du Colombier unsigned long param )
145*458db832SDavid du Colombier // char *param ) // IOCTL parameter
146*458db832SDavid du Colombier {
147*458db832SDavid du Colombier static unsigned char mode;
148*458db832SDavid du Colombier char cp, *cptr;
149*458db832SDavid du Colombier void *vptr;
150*458db832SDavid du Colombier unsigned long *lptr;
151*458db832SDavid du Colombier int i, j;
152*458db832SDavid du Colombier unsigned int ld;
153*458db832SDavid du Colombier unsigned long lng;
154*458db832SDavid du Colombier volatile immap_t *Mmap;
155*458db832SDavid du Colombier
156*458db832SDavid du Colombier cptr = (char *)param;
157*458db832SDavid du Colombier mode = (unsigned char)*cptr;
158*458db832SDavid du Colombier Mmap = ((volatile immap_t *)IMAP_ADDR);
159*458db832SDavid du Colombier switch(ioctl_cmd)
160*458db832SDavid du Colombier {
161*458db832SDavid du Colombier case IOCTL_SET_MODE:
162*458db832SDavid du Colombier //mode = (unsigned char)*param;
163*458db832SDavid du Colombier mode = ((mcc_iorw_t *)param)->cmd;
164*458db832SDavid du Colombier switch( mode )
165*458db832SDavid du Colombier {
166*458db832SDavid du Colombier case NORMAL_OPERATION:
167*458db832SDavid du Colombier /* Setup the SIMODE Register */
168*458db832SDavid du Colombier D( printk("mcc2_ioctl: ioctl set NORMAL_OPERATION mode\n"); )
169*458db832SDavid du Colombier ioctl_parm( (unsigned int)SIxMR_SDM_NORMAL_OPERATION ); /* SDMx */
170*458db832SDavid du Colombier break;
171*458db832SDavid du Colombier
172*458db832SDavid du Colombier case AUTOMATIC_ECHO:
173*458db832SDavid du Colombier /* Setup the SIMODE Register */
174*458db832SDavid du Colombier D( printk("mcc2_ioctl: ioctl set AUTOMATIC_ECHO mode\n"); )
175*458db832SDavid du Colombier ioctl_parm( (unsigned int)SIxMR_SDM_AUTOMATIC_ECHO ); /* SDMx */
176*458db832SDavid du Colombier break;
177*458db832SDavid du Colombier
178*458db832SDavid du Colombier case INTERNAL_LOOPBACK:
179*458db832SDavid du Colombier /* Setup the SIMODE Register */
180*458db832SDavid du Colombier D( printk("mcc2_ioctl: ioctl set INTERNAL_LOOPBACK mode\n"); )
181*458db832SDavid du Colombier ioctl_parm( (unsigned int)SIxMR_SDM_INTERNAL_LOOPBACK ); /* SDMx */
182*458db832SDavid du Colombier break;
183*458db832SDavid du Colombier
184*458db832SDavid du Colombier case LOOPBACK_CONTROL:
185*458db832SDavid du Colombier /* Setup the SIMODE Register */
186*458db832SDavid du Colombier D( printk("mcc2_ioctl: ioctl set LOOPBACK_CONTROL mode\n"); )
187*458db832SDavid du Colombier ioctl_parm( (unsigned int)SIxMR_SDM_LOOPBACK_CONTROL ); /* SDMx */
188*458db832SDavid du Colombier break;
189*458db832SDavid du Colombier
190*458db832SDavid du Colombier
191*458db832SDavid du Colombier default:
192*458db832SDavid du Colombier printk("mcc2_ioctl: Error, unrecognized ioctl parameter, device operation unchanged.\n");
193*458db832SDavid du Colombier break;
194*458db832SDavid du Colombier
195*458db832SDavid du Colombier }
196*458db832SDavid du Colombier break;
197*458db832SDavid du Colombier
198*458db832SDavid du Colombier case IOCTL_RWX_MODE:
199*458db832SDavid du Colombier mode = ((mcc_iorw_t *)param)->cmd;
200*458db832SDavid du Colombier switch(mode)
201*458db832SDavid du Colombier {
202*458db832SDavid du Colombier case HPI_RD:
203*458db832SDavid du Colombier lng = (long)(((mcc_iorw_t *)param)->address);
204*458db832SDavid du Colombier lptr = ((unsigned long *)lng);
205*458db832SDavid du Colombier vptr = (void *)lptr;
206*458db832SDavid du Colombier if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
207*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during read from hpi.\n");
208*458db832SDavid du Colombier return -EFAULT;
209*458db832SDavid du Colombier }
210*458db832SDavid du Colombier break;
211*458db832SDavid du Colombier
212*458db832SDavid du Colombier
213*458db832SDavid du Colombier case HPI_WR:
214*458db832SDavid du Colombier lng = (long)(((mcc_iorw_t *)param)->address);
215*458db832SDavid du Colombier lptr = ((unsigned long *)lng);
216*458db832SDavid du Colombier vptr = (void *)lptr;
217*458db832SDavid du Colombier if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
218*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during write to hpi\n");
219*458db832SDavid du Colombier return -EFAULT;
220*458db832SDavid du Colombier }
221*458db832SDavid du Colombier break;
222*458db832SDavid du Colombier
223*458db832SDavid du Colombier
224*458db832SDavid du Colombier
225*458db832SDavid du Colombier case FPGA_RD:
226*458db832SDavid du Colombier lng = (long)(((mcc_iorw_t *)param)->address);
227*458db832SDavid du Colombier lptr = ((unsigned long *)lng);
228*458db832SDavid du Colombier vptr = (void *)lptr;
229*458db832SDavid du Colombier if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)vptr, (((mcc_iorw_t *)param)->nbytes))) {
230*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during read from FPGA.\n");
231*458db832SDavid du Colombier return -EFAULT;
232*458db832SDavid du Colombier }
233*458db832SDavid du Colombier break;
234*458db832SDavid du Colombier
235*458db832SDavid du Colombier
236*458db832SDavid du Colombier case FPGA_WR:
237*458db832SDavid du Colombier lng = (long)(((mcc_iorw_t *)param)->address);
238*458db832SDavid du Colombier lptr = ((unsigned long *)lng);
239*458db832SDavid du Colombier vptr = (void *)lptr;
240*458db832SDavid du Colombier if (copy_from_user( (void *)vptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
241*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during write to FPGA\n");
242*458db832SDavid du Colombier return -EFAULT;
243*458db832SDavid du Colombier }
244*458db832SDavid du Colombier break;
245*458db832SDavid du Colombier
246*458db832SDavid du Colombier
247*458db832SDavid du Colombier
248*458db832SDavid du Colombier
249*458db832SDavid du Colombier
250*458db832SDavid du Colombier case MEM_MODR:
251*458db832SDavid du Colombier cptr = (char *)Mmap;
252*458db832SDavid du Colombier cptr += ((mcc_iorw_t *)param)->address;
253*458db832SDavid du Colombier if (copy_to_user( (((mcc_iorw_t *)param)->buf), (void *)cptr, (((mcc_iorw_t *)param)->nbytes))) {
254*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during read of read-modify memory\n");
255*458db832SDavid du Colombier return -EFAULT;
256*458db832SDavid du Colombier }
257*458db832SDavid du Colombier break;
258*458db832SDavid du Colombier
259*458db832SDavid du Colombier case MEM_MODW:
260*458db832SDavid du Colombier cptr = (char *)Mmap;
261*458db832SDavid du Colombier cptr += ((mcc_iorw_t *)param)->address;
262*458db832SDavid du Colombier if (copy_from_user( (void *)cptr, (((mcc_iorw_t *)param)->buf), (((mcc_iorw_t *)param)->nbytes))) {
263*458db832SDavid du Colombier printk("mcc2_ioctl: Failed during modify of read-modify memory\n");
264*458db832SDavid du Colombier return -EFAULT;
265*458db832SDavid du Colombier }
266*458db832SDavid du Colombier break;
267*458db832SDavid du Colombier
268*458db832SDavid du Colombier case IO_PORTS:
269*458db832SDavid du Colombier break;
270*458db832SDavid du Colombier case SI_RAM_CTL1:
271*458db832SDavid du Colombier break;
272*458db832SDavid du Colombier case SI_RAM_CTL2:
273*458db832SDavid du Colombier if (copy_to_user( (void *)param, (siramctl_t *)&(Mmap->im_siramctl2), sizeof(siramctl_t))) {
274*458db832SDavid du Colombier printk("mcc2_ioctl: Failed to copy SI_RAM_CTL2 struct\n");
275*458db832SDavid du Colombier return -EFAULT;
276*458db832SDavid du Colombier }
277*458db832SDavid du Colombier break;
278*458db832SDavid du Colombier
279*458db832SDavid du Colombier
280*458db832SDavid du Colombier
281*458db832SDavid du Colombier default:
282*458db832SDavid du Colombier break;
283*458db832SDavid du Colombier }
284*458db832SDavid du Colombier break;
285*458db832SDavid du Colombier
286*458db832SDavid du Colombier default:
287*458db832SDavid du Colombier //if (copy_to_user((void *)param, &mode, sizeof(mode)))
288*458db832SDavid du Colombier printk("We are at the end ...\n");
289*458db832SDavid du Colombier return -EFAULT;
290*458db832SDavid du Colombier break;
291*458db832SDavid du Colombier }
292*458db832SDavid du Colombier break;
293*458db832SDavid du Colombier
294*458db832SDavid du Colombier default:
295*458db832SDavid du Colombier break;
296*458db832SDavid du Colombier }
297*458db832SDavid du Colombier
298*458db832SDavid du Colombier return 0;
299*458db832SDavid du Colombier }
300*458db832SDavid du Colombier
301*458db832SDavid du Colombier
302*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
303*458db832SDavid du Colombier //
304*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
305*458db832SDavid du Colombier
306*458db832SDavid du Colombier static ssize_t
307*458db832SDavid du Colombier mcc2_open( struct inode *inode, struct file *file )
308*458db832SDavid du Colombier {
309*458db832SDavid du Colombier MOD_INC_USE_COUNT;
310*458db832SDavid du Colombier return 0;
311*458db832SDavid du Colombier }
312*458db832SDavid du Colombier
313*458db832SDavid du Colombier
314*458db832SDavid du Colombier
315*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
316*458db832SDavid du Colombier //
317*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
318*458db832SDavid du Colombier
319*458db832SDavid du Colombier static int
320*458db832SDavid du Colombier mcc2_release( struct inode *inode, struct file *file )
321*458db832SDavid du Colombier {
322*458db832SDavid du Colombier MOD_DEC_USE_COUNT;
323*458db832SDavid du Colombier return 0;
324*458db832SDavid du Colombier }
325*458db832SDavid du Colombier
326*458db832SDavid du Colombier
327*458db832SDavid du Colombier
328*458db832SDavid du Colombier
329*458db832SDavid du Colombier
330*458db832SDavid du Colombier
331*458db832SDavid du Colombier #ifndef MODULE
332*458db832SDavid du Colombier
333*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
334*458db832SDavid du Colombier //
335*458db832SDavid du Colombier ////////////////////////////////////////////////////////////////////////////////
336*458db832SDavid du Colombier
337*458db832SDavid du Colombier long
338*458db832SDavid du Colombier mcc2_init( long mem_start, long mem_end )
339*458db832SDavid du Colombier {
340*458db832SDavid du Colombier
341*458db832SDavid du Colombier if ((mcc2_major = register_chrdev(MCC_MAJOR, MCC_NAME, &mcc2_fops)))
342*458db832SDavid du Colombier printk("mcc2_init: Unable to get major for mcc2 device %d\n", MCC_MAJOR);
343*458db832SDavid du Colombier else {
344*458db832SDavid du Colombier //MPC82xxSiuInit();
345*458db832SDavid du Colombier MPC82xxCpmInit();
346*458db832SDavid du Colombier }
347*458db832SDavid du Colombier return mem_start;
348*458db832SDavid du Colombier }
349*458db832SDavid du Colombier
350*458db832SDavid du Colombier #else
351*458db832SDavid du Colombier
352