xref: /plan9/sys/src/9/ppc/mcc.c (revision 458db83292ea45506704800dedf36a95598fc2ec)
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