add vlynq support
[openwrt/svn-archive/archive.git] / openwrt / target / linux / linux-2.4 / patches / ar7 / 005-vlynq.patch
1 diff -urN linux.old/drivers/char/avalanche_vlynq/Makefile linux.dev/drivers/char/avalanche_vlynq/Makefile
2 --- linux.old/drivers/char/avalanche_vlynq/Makefile 1970-01-01 01:00:00.000000000 +0100
3 +++ linux.dev/drivers/char/avalanche_vlynq/Makefile 2005-07-22 06:32:53.345189608 +0200
4 @@ -0,0 +1,14 @@
5 +#
6 +# Makefile for the linux kernel.
7 +#
8 +# Note! Dependencies are done automagically by 'make dep', which also
9 +# removes any old dependencies. DON'T put your own dependencies here
10 +# unless it's something special (ie not a .c file).
11 +#
12 +# Note 2! The CFLAGS definitions are now in the main makefile...
13 +
14 +O_TARGET := avalanche_vlynq.o
15 +
16 +obj-y += vlynq_drv.o vlynq_hal.o vlynq_board.o
17 +
18 +include $(TOPDIR)/Rules.make
19 diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_board.c linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c
20 --- linux.old/drivers/char/avalanche_vlynq/vlynq_board.c 1970-01-01 01:00:00.000000000 +0100
21 +++ linux.dev/drivers/char/avalanche_vlynq/vlynq_board.c 2005-07-22 06:34:39.448059520 +0200
22 @@ -0,0 +1,182 @@
23 +/*
24 + * Jeff Harrell, jharrell@ti.com
25 + * Copyright (C) 2001 Texas Instruments, Inc. All rights reserved.
26 + *
27 + * This program is free software; you can distribute it and/or modify it
28 + * under the terms of the GNU General Public License (Version 2) as
29 + * published by the Free Software Foundation.
30 + *
31 + * This program is distributed in the hope it will be useful, but WITHOUT
32 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34 + * for more details.
35 + *
36 + * You should have received a copy of the GNU General Public License along
37 + * with this program; if not, write to the Free Software Foundation, Inc.,
38 + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
39 + *
40 + * Texas Instruments Sangam specific setup.
41 + */
42 +#include <linux/config.h>
43 +#include <asm/ar7/sangam.h>
44 +#include <asm/ar7/avalanche_misc.h>
45 +#include <asm/ar7/vlynq.h>
46 +
47 +#define SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR 30 /* MSB - 1 bit */
48 +#define SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR 31 /* MSB bit */
49 +#define SYS_VLYNQ_OPTIONS 0x7F; /* all options*/
50 +
51 +/* These defines are board specific */
52 +
53 +
54 +#define VLYNQ0_REMOTE_WINDOW1_OFFSET (0x0C000000)
55 +#define VLYNQ0_REMOTE_WINDOW1_SIZE (0x500)
56 +
57 +
58 +#define VLYNQ1_REMOTE_WINDOW1_OFFSET (0x0C000000)
59 +#define VLYNQ1_REMOTE_WINDOW1_SIZE (0x500)
60 +
61 +
62 +extern VLYNQ_DEV vlynqDevice0, vlynqDevice1;
63 +int vlynq_init_status[2] = {0, 0};
64 +static int reset_hack = 1;
65 +
66 +void vlynq_ar7wrd_dev_init()
67 +{
68 + *(unsigned long*) AVALANCHE_GPIO_ENBL |= (1<<18);
69 + vlynq_delay(20000);
70 + *(unsigned long*) AVALANCHE_GPIO_DIR &= ~(1<<18);
71 + vlynq_delay(20000);
72 + *(unsigned long*) AVALANCHE_GPIO_DATA_OUT&= ~(1<<18);
73 + vlynq_delay(50000);
74 + *(unsigned long*) AVALANCHE_GPIO_DATA_OUT|= (1<<18);
75 + vlynq_delay(50000);
76 +
77 + /* Initialize the MIPS host vlynq driver for a given vlynq interface */
78 + vlynqDevice0.dev_idx = 0; /* first vlynq module - this parameter is for reference only */
79 + vlynqDevice0.module_base = AVALANCHE_LOW_VLYNQ_CONTROL_BASE; /* vlynq0 module base address */
80 +
81 +#if defined(CONFIG_VLYNQ_CLK_LOCAL)
82 + vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_LOCAL;
83 +#else
84 + vlynqDevice0.clk_source = VLYNQ_CLK_SOURCE_REMOTE;
85 +#endif
86 + vlynqDevice0.clk_div = 0x01; /* board/hardware specific */
87 + vlynqDevice0.state = VLYNQ_DRV_STATE_UNINIT; /* uninitialized module */
88 +
89 + /* Populate vlynqDevice0.local_mem & Vlynq0.remote_mem based on system configuration */
90 + /*Local memory configuration */
91 +
92 + /* Demiurg : not good !*/
93 +#if 0
94 + vlynqDevice0.local_mem.Txmap= AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE & ~(0xc0000000) ; /* physical address */
95 + vlynqDevice0.remote_mem.RxOffset[0]= VLYNQ0_REMOTE_WINDOW1_OFFSET; /* This is specific to the board on the other end */
96 + vlynqDevice0.remote_mem.RxSize[0]=VLYNQ0_REMOTE_WINDOW1_SIZE;
97 +#endif
98 +
99 + /* Demiurg : This is how it should be ! */
100 + vlynqDevice0.local_mem.Txmap = PHYSADDR(AVALANCHE_LOW_VLYNQ_MEM_MAP_BASE);
101 +#define VLYNQ_ACX111_MEM_OFFSET 0xC0000000 /* Physical address of ACX111 memory */
102 +#define VLYNQ_ACX111_MEM_SIZE 0x00040000 /* Total size of the ACX111 memory */
103 +#define VLYNQ_ACX111_REG_OFFSET 0xF0000000 /* PHYS_ADDR of ACX111 control registers */
104 +#define VLYNQ_ACX111_REG_SIZE 0x00022000 /* Size of ACX111 registers area, MAC+PHY */
105 +#define ACX111_VL1_REMOTE_SIZE 0x1000000
106 + vlynqDevice0.remote_mem.RxOffset[0] = VLYNQ_ACX111_MEM_OFFSET;
107 + vlynqDevice0.remote_mem.RxSize[0] = VLYNQ_ACX111_MEM_SIZE ;
108 + vlynqDevice0.remote_mem.RxOffset[1] = VLYNQ_ACX111_REG_OFFSET;
109 + vlynqDevice0.remote_mem.RxSize[1] = VLYNQ_ACX111_REG_SIZE ;
110 + vlynqDevice0.remote_mem.Txmap = 0;
111 + vlynqDevice0.local_mem.RxOffset[0] = AVALANCHE_SDRAM_BASE;
112 + vlynqDevice0.local_mem.RxSize[0] = ACX111_VL1_REMOTE_SIZE;
113 +
114 +
115 + /* Local interrupt configuration */
116 + vlynqDevice0.local_irq.intLocal = VLYNQ_INT_LOCAL; /* Host handles vlynq interrupts*/
117 + vlynqDevice0.local_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* vlynq root isr used */
118 + vlynqDevice0.local_irq.map_vector = SYS_VLYNQ_LOCAL_INTERRUPT_VECTOR;
119 + vlynqDevice0.local_irq.intr_ptr = 0; /* Since remote interrupts part of vlynq root isr this is unused */
120 +
121 + /* Remote interrupt configuration */
122 + vlynqDevice0.remote_irq.intLocal = VLYNQ_INT_REMOTE; /* MIPS handles interrupts */
123 + vlynqDevice0.remote_irq.intRemote = VLYNQ_INT_ROOT_ISR; /* Not significant since MIPS handles interrupts */
124 + vlynqDevice0.remote_irq.map_vector = SYS_VLYNQ_REMOTE_INTERRUPT_VECTOR;
125 + vlynqDevice0. remote_irq.intr_ptr = AVALANCHE_INTC_BASE; /* Not significant since MIPS handles interrupts */
126 +
127 + if(reset_hack != 1)
128 + printk("About to re-init the VLYNQ.\n");
129 +
130 + if(vlynq_init(&vlynqDevice0,VLYNQ_INIT_PERFORM_ALL)== 0)
131 + {
132 + /* Suraj added the following to keep the 1130 going. */
133 + vlynq_interrupt_vector_set(&vlynqDevice0, 0 /* intr vector line running into 1130 vlynq */,
134 + 0 /* intr mapped onto the interrupt register on remote vlynq and this vlynq */,
135 + VLYNQ_REMOTE_DVC, 0 /* polarity active high */, 0 /* interrupt Level triggered */);
136 +
137 + /* System wide interrupt is 80 for 1130, please note. */
138 + vlynq_init_status[0] = 1;
139 + reset_hack = 2;
140 + }
141 + else
142 + {
143 + if(reset_hack == 1)
144 + printk("VLYNQ INIT FAILED: Please try cold reboot. \n");
145 + else
146 + printk("Failed to initialize the VLYNQ interface at insmod.\n");
147 +
148 + }
149 +}
150 +
151 +void vlynq_dev_init(void)
152 +{
153 + volatile unsigned int *reset_base = (unsigned int *) AVALANCHE_RESET_CONTROL_BASE;
154 +
155 + *reset_base &= ~((1 << AVALANCHE_LOW_VLYNQ_RESET_BIT)); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT)); */
156 +
157 + vlynq_delay(20000);
158 +
159 + /* Bring vlynq out of reset if not already done */
160 + *reset_base |= (1 << AVALANCHE_LOW_VLYNQ_RESET_BIT); /* | (1 << AVALANCHE_HIGH_VLYNQ_RESET_BIT); */
161 + vlynq_delay(20000); /* Allowing sufficient time to VLYNQ to settle down.*/
162 +
163 + vlynq_ar7wrd_dev_init( );
164 +
165 +}
166 +
167 +/* This function is board specific and should be ported for each board. */
168 +void remote_vlynq_dev_reset_ctrl(unsigned int module_reset_bit,
169 + AVALANCHE_RESET_CTRL_T reset_ctrl)
170 +{
171 + if(module_reset_bit >= 32)
172 + return;
173 +
174 + switch(module_reset_bit)
175 + {
176 + case 0:
177 + if(OUT_OF_RESET == reset_ctrl)
178 + {
179 + if(reset_hack) return;
180 +
181 + vlynq_delay(20000);
182 + printk("Un-resetting the remote device.\n");
183 + vlynq_dev_init();
184 + printk("Re-initialized the VLYNQ.\n");
185 + reset_hack = 2;
186 + }
187 + else if(IN_RESET == reset_ctrl)
188 + {
189 + *(unsigned long*) AVALANCHE_GPIO_DATA_OUT &= ~(1<<18);
190 +
191 + vlynq_delay(20000);
192 + printk("Resetting the remote device.\n");
193 + reset_hack = 0;
194 + }
195 + else
196 + ;
197 + break;
198 +
199 + default:
200 + break;
201 +
202 + }
203 +}
204 +
205 diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c
206 --- linux.old/drivers/char/avalanche_vlynq/vlynq_drv.c 1970-01-01 01:00:00.000000000 +0100
207 +++ linux.dev/drivers/char/avalanche_vlynq/vlynq_drv.c 2005-07-22 06:32:53.345189608 +0200
208 @@ -0,0 +1,242 @@
209 +/******************************************************************************
210 + * FILE PURPOSE: Vlynq Linux Device Driver Source
211 + ******************************************************************************
212 + * FILE NAME: vlynq_drv.c
213 + *
214 + * DESCRIPTION: Vlynq Linux Device Driver Source
215 + *
216 + * REVISION HISTORY:
217 + *
218 + * Date Description Author
219 + *-----------------------------------------------------------------------------
220 + * 17 July 2003 Initial Creation Anant Gole
221 + * 17 Dec 2003 Updates Sharath Kumar
222 + *
223 + * (C) Copyright 2003, Texas Instruments, Inc
224 + *******************************************************************************/
225 +
226 +#include <linux/config.h>
227 +#include <linux/init.h>
228 +#include <linux/module.h>
229 +#include <linux/sched.h>
230 +#include <linux/miscdevice.h>
231 +#include <linux/smp_lock.h>
232 +#include <linux/delay.h>
233 +#include <linux/proc_fs.h>
234 +#include <linux/capability.h>
235 +#include <asm/ar7/avalanche_intc.h>
236 +#include <asm/ar7/sangam.h>
237 +#include <asm/ar7/vlynq.h>
238 +
239 +
240 +#define TI_VLYNQ_VERSION "0.2"
241 +
242 +/* debug on ? */
243 +#define VLYNQ_DEBUG
244 +
245 +/* Macro for debug and error printf's */
246 +#ifdef VLYNQ_DEBUG
247 +#define DBGPRINT printk
248 +#else
249 +#define DBGPRINT(x)
250 +#endif
251 +
252 +#define ERRPRINT printk
253 +
254 +/* Define the max vlynq ports this driver will support.
255 + Device name strings are statically added here */
256 +#define MAX_VLYNQ_PORTS 2
257 +
258 +
259 +/* Type define for VLYNQ private structure */
260 +typedef struct vlynqPriv{
261 + int irq;
262 + VLYNQ_DEV *vlynqDevice;
263 +}VLYNQ_PRIV;
264 +
265 +extern int vlynq_init_status[2];
266 +
267 +/* Extern Global variable for vlynq devices used in initialization of the vlynq device
268 + * These variables need to be populated/initialized by the system as part of initialization
269 + * process. The vlynq enumerator can run at initialization and populate these globals
270 + */
271 +
272 +VLYNQ_DEV vlynqDevice0;
273 +VLYNQ_DEV vlynqDevice1;
274 +
275 +/* Defining dummy macro AVALANCHE_HIGH_VLYNQ_INT to take
276 + * care of compilation in case of single vlynq device
277 + */
278 +
279 +#ifndef AVALANCHE_HIGH_VLYNQ_INT
280 +#define AVALANCHE_HIGH_VLYNQ_INT 0
281 +#endif
282 +
283 +
284 +
285 +/* vlynq private object */
286 +VLYNQ_PRIV vlynq_priv[CONFIG_AR7_VLYNQ_PORTS] = {
287 + { LNXINTNUM(AVALANCHE_LOW_VLYNQ_INT),&vlynqDevice0},
288 + { LNXINTNUM(AVALANCHE_HIGH_VLYNQ_INT),&vlynqDevice1},
289 +};
290 +
291 +extern void vlynq_dev_init(void);
292 +
293 +
294 +/* =================================== all the operations */
295 +
296 +static int
297 +vlynq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
298 +{
299 + return 0;
300 +}
301 +
302 +static struct file_operations vlynq_fops = {
303 + owner: THIS_MODULE,
304 + ioctl: vlynq_ioctl,
305 +};
306 +
307 +/* Vlynq device object */
308 +static struct miscdevice vlynq_dev [MAX_VLYNQ_PORTS] = {
309 + { MISC_DYNAMIC_MINOR , "vlynq0", &vlynq_fops },
310 + { MISC_DYNAMIC_MINOR , "vlynq1", &vlynq_fops },
311 +};
312 +
313 +
314 +/* Proc read function */
315 +static int
316 +vlynq_read_link_proc(char *buf, char **start, off_t offset, int count, int *eof, void *unused)
317 +{
318 + int instance;
319 + int len = 0;
320 +
321 + len += sprintf(buf +len,"VLYNQ Devices : %d\n",CONFIG_AR7_VLYNQ_PORTS);
322 +
323 + for(instance =0;instance < CONFIG_AR7_VLYNQ_PORTS;instance++)
324 + {
325 + int link_state;
326 + char *link_msg[] = {" DOWN "," UP "};
327 +
328 + if(vlynq_init_status[instance] == 0)
329 + link_state = 0;
330 +
331 + else if (vlynq_link_check(vlynq_priv[instance].vlynqDevice))
332 + link_state = 1;
333 +
334 + else
335 + link_state = 0;
336 +
337 + len += sprintf(buf + len, "VLYNQ %d: Link state: %s\n",instance,link_msg[link_state]);
338 +
339 + }
340 + /* Print info about vlynq device 1 */
341 +
342 + return len;
343 +}
344 +
345 +
346 +/* Proc function to display driver version */
347 +static int
348 +vlynq_read_ver_proc(char *buf, char **start, off_t offset, int count, int *eof, void *data)
349 +{
350 + int instance;
351 + int len=0;
352 +
353 + len += sprintf(buf +len,"\nTI Linux VLYNQ Driver Version %s\n",TI_VLYNQ_VERSION);
354 + return len;
355 +}
356 +
357 +
358 +
359 +
360 +/* Wrapper for vlynq ISR */
361 +static void lnx_vlynq_root_isr(int irq, void * arg, struct pt_regs *regs)
362 +{
363 + vlynq_root_isr(arg);
364 +}
365 +
366 +/* =================================== init and cleanup */
367 +
368 +int vlynq_init_module(void)
369 +{
370 + int ret;
371 + int unit = 0;
372 + int instance_count = CONFIG_AR7_VLYNQ_PORTS;
373 + volatile int *ptr;
374 +
375 + vlynq_dev_init();
376 +
377 + DBGPRINT("Vlynq CONFIG_AR7_VLYNQ_PORTS=%d\n", CONFIG_AR7_VLYNQ_PORTS);
378 + /* If num of configured vlynq ports > supported by driver return error */
379 + if (instance_count > MAX_VLYNQ_PORTS)
380 + {
381 + ERRPRINT("ERROR: vlynq_init_module(): Max %d supported\n", MAX_VLYNQ_PORTS);
382 + return (-1);
383 + }
384 +
385 + /* register the misc device */
386 + for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++)
387 + {
388 + ret = misc_register(&vlynq_dev[unit]);
389 +
390 + if(ret < 0)
391 + {
392 + ERRPRINT("ERROR:Could not register vlynq device:%d\n",unit);
393 + continue;
394 + }
395 + else
396 + DBGPRINT("Vlynq Device %s registered with minor no %d as misc device. Result=%d\n",
397 + vlynq_dev[unit].name, vlynq_dev[unit].minor, ret);
398 +#if 0
399 +
400 + DBGPRINT("Calling vlynq init\n");
401 +
402 + /* Read the global variable for VLYNQ device structure and initialize vlynq driver */
403 + ret = vlynq_init(vlynq_priv[unit].vlynqDevice,VLYNQ_INIT_PERFORM_ALL );
404 +#endif
405 +
406 + if(vlynq_init_status[unit] == 0)
407 + {
408 + printk("VLYNQ %d : init failed\n",unit);
409 + continue;
410 + }
411 +
412 + /* Check link before proceeding */
413 + if (!vlynq_link_check(vlynq_priv[unit].vlynqDevice))
414 + {
415 + DBGPRINT("\nError: Vlynq link not available.trying once before Exiting");
416 + }
417 + else
418 + {
419 + DBGPRINT("Vlynq instance:%d Link UP\n",unit);
420 +
421 + /* Install the vlynq local root ISR */
422 + request_irq(vlynq_priv[unit].irq,lnx_vlynq_root_isr,0,vlynq_dev[unit].name,vlynq_priv[unit].vlynqDevice);
423 + }
424 + }
425 +
426 + /* Creating proc entry for the devices */
427 + create_proc_read_entry("avalanche/vlynq_link", 0, NULL, vlynq_read_link_proc, NULL);
428 + create_proc_read_entry("avalanche/vlynq_ver", 0, NULL, vlynq_read_ver_proc, NULL);
429 +
430 + return 0;
431 +}
432 +
433 +void vlynq_cleanup_module(void)
434 +{
435 + int unit = 0;
436 +
437 + for (unit = 0; unit < CONFIG_AR7_VLYNQ_PORTS; unit++)
438 + {
439 + DBGPRINT("vlynq_cleanup_module(): Unregistring misc device %s\n",vlynq_dev[unit].name);
440 + misc_deregister(&vlynq_dev[unit]);
441 + }
442 +
443 + remove_proc_entry("avalanche/vlynq_link", NULL);
444 + remove_proc_entry("avalanche/vlynq_ver", NULL);
445 +}
446 +
447 +
448 +module_init(vlynq_init_module);
449 +module_exit(vlynq_cleanup_module);
450 +
451 diff -urN linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c
452 --- linux.old/drivers/char/avalanche_vlynq/vlynq_hal.c 1970-01-01 01:00:00.000000000 +0100
453 +++ linux.dev/drivers/char/avalanche_vlynq/vlynq_hal.c 2005-07-22 06:32:53.359187480 +0200
454 @@ -0,0 +1,1214 @@
455 +/***************************************************************************
456 +**+----------------------------------------------------------------------+**
457 +**| **** |**
458 +**| **** |**
459 +**| ******o*** |**
460 +**| ********_///_**** |**
461 +**| ***** /_//_/ **** |**
462 +**| ** ** (__/ **** |**
463 +**| ********* |**
464 +**| **** |**
465 +**| *** |**
466 +**| |**
467 +**| Copyright (c) 2003 Texas Instruments Incorporated |**
468 +**| ALL RIGHTS RESERVED |**
469 +**| |**
470 +**| Permission is hereby granted to licensees of Texas Instruments |**
471 +**| Incorporated (TI) products to use this computer program for the sole |**
472 +**| purpose of implementing a licensee product based on TI products. |**
473 +**| No other rights to reproduce, use, or disseminate this computer |**
474 +**| program, whether in part or in whole, are granted. |**
475 +**| |**
476 +**| TI makes no representation or warranties with respect to the |**
477 +**| performance of this computer program, and specifically disclaims |**
478 +**| any responsibility for any damages, special or consequential, |**
479 +**| connected with the use of this program. |**
480 +**| |**
481 +**+----------------------------------------------------------------------+**
482 +***************************************************************************/
483 +
484 +/***************************************************************************
485 + * ------------------------------------------------------------------------------
486 + * Module : vlynq_hal.c
487 + * Description : This file implements VLYNQ HAL API.
488 + * ------------------------------------------------------------------------------
489 + ***************************************************************************/
490 +
491 +#include <linux/stddef.h>
492 +#include <linux/types.h>
493 +#include <asm/ar7/vlynq.h>
494 +
495 +/**** Local Function prototypes *******/
496 +static int vlynqInterruptInit(VLYNQ_DEV *pdev);
497 +static void vlynq_configClock(VLYNQ_DEV *pdev);
498 +
499 +/*** Second argument must be explicitly type casted to
500 + * (VLYNQ_DEV*) inside the following functions */
501 +static void vlynq_local_module_isr(void *arg1, void *arg2, void *arg3);
502 +static void vlynq_remote_module_isr(void *arg1, void *arg2, void *arg3);
503 +
504 +
505 +volatile int vlynq_delay_value = 0;
506 +
507 +/* Code adopted from original vlynq driver */
508 +void vlynq_delay(unsigned int clktime)
509 +{
510 + int i = 0;
511 + volatile int *ptr = &vlynq_delay_value;
512 + *ptr = 0;
513 +
514 + /* We are assuming that the each cycle takes about
515 + * 23 assembly instructions. */
516 + for(i = 0; i < (clktime + 23)/23; i++)
517 + {
518 + *ptr = *ptr + 1;
519 + }
520 +}
521 +
522 +
523 +/* ----------------------------------------------------------------------------
524 + * Function : vlynq_configClock()
525 + * Description: Configures clock settings based on input parameters
526 + * Adapted from original vlyna driver from Cable
527 + */
528 +static void vlynq_configClock(VLYNQ_DEV * pdev)
529 +{
530 + unsigned int tmp;
531 +
532 + switch( pdev->clk_source)
533 + {
534 + case VLYNQ_CLK_SOURCE_LOCAL: /* we output the clock, clk_div in range [1..8]. */
535 + tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ;
536 + VLYNQ_CTRL_REG = tmp;
537 + VLYNQ_R_CTRL_REG = 0ul;
538 + break;
539 + case VLYNQ_CLK_SOURCE_REMOTE: /* we need to set the clock pin as input */
540 + VLYNQ_CTRL_REG = 0ul;
541 + tmp = ((pdev->clk_div - 1) << 16) | VLYNQ_CTL_CLKDIR_MASK ;
542 + VLYNQ_R_CTRL_REG = tmp;
543 + break;
544 + default: /* do nothing about the clock, but clear other bits. */
545 + tmp = ~(VLYNQ_CTL_CLKDIR_MASK | VLYNQ_CTL_CLKDIV_MASK);
546 + VLYNQ_CTRL_REG &= tmp;
547 + break;
548 + }
549 +}
550 +
551 + /* ----------------------------------------------------------------------------
552 + * Function : vlynq_link_check()
553 + * Description: This function checks the current VLYNQ for a link.
554 + * An arbitrary amount of time is allowed for the link to come up .
555 + * Returns 0 for "no link / failure " and 1 for "link available".
556 + * -----------------------------------------------------------------------------
557 + */
558 +unsigned int vlynq_link_check( VLYNQ_DEV * pdev)
559 +{
560 + /*sleep for 64 cycles, allow link to come up*/
561 + vlynq_delay(64);
562 +
563 + /* check status register return OK if link is found. */
564 + if (VLYNQ_STATUS_REG & VLYNQ_STS_LINK_MASK)
565 + {
566 + return 1; /* Link Available */
567 + }
568 + else
569 + {
570 + return 0; /* Link Failure */
571 + }
572 +}
573 +
574 +/* ----------------------------------------------------------------------------
575 + * Function : vlynq_init()
576 + * Description: Initialization function accepting paramaters for VLYNQ module
577 + * initialization. The Options bitmap decides what operations are performed
578 + * as a part of initialization. The Input parameters are obtained through the
579 + * sub fields of VLYNQ_DEV structure.
580 + */
581 +
582 +int vlynq_init(VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options)
583 +{
584 + unsigned int map;
585 + unsigned int val=0,cnt,tmp;
586 + unsigned int counter=0;
587 + VLYNQ_INTERRUPT_CNTRL *intSetting=NULL;
588 +
589 + /* validate arguments */
590 + if( VLYNQ_OUTRANGE(pdev->clk_source, VLYNQ_CLK_SOURCE_REMOTE, VLYNQ_CLK_SOURCE_NONE) ||
591 + VLYNQ_OUTRANGE(pdev->clk_div, 8, 1) )
592 + {
593 + return VLYNQ_INVALID_ARG;
594 + }
595 +
596 + /** perform all sanity checks first **/
597 + if(pdev->state != VLYNQ_DRV_STATE_UNINIT)
598 + return VLYNQ_INVALID_DRV_STATE;
599 +
600 + /** Initialize local and remote register set addresses- additional
601 + * provision to access the registers directly if need be */
602 + pdev->local = (VLYNQ_REG_SET*)pdev->module_base;
603 + pdev->remote = (VLYNQ_REG_SET*) (pdev->module_base + VLYNQ_REMOTE_REGS_OFFSET);
604 +
605 + /* Detect faulty int configuration that might induce int pkt looping */
606 + if ( (options & VLYNQ_INIT_LOCAL_INTERRUPTS) && (options & VLYNQ_INIT_REMOTE_INTERRUPTS) )
607 + {
608 + /* case when both local and remote are configured */
609 + if((pdev->local_irq.intLocal== VLYNQ_INT_REMOTE ) /* interrupts transfered to remote from local */
610 + && (pdev->remote_irq.intLocal== VLYNQ_INT_REMOTE) /* interrupts transfered from remote to local */
611 + && ((pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) || (pdev->remote_irq.intRemote == VLYNQ_INT_ROOT_ISR)) )
612 + {
613 + return (VLYNQ_INT_CONFIG_ERR);
614 + }
615 + }
616 +
617 + pdev->state = VLYNQ_DRV_STATE_ININIT;
618 + pdev->intCount = 0;
619 + pdev->isrCount = 0;
620 +
621 + /*** Its assumed that the vlynq module has been brought out of reset
622 + * before invocation of vlynq_init. Since, this operation is board specific
623 + * it must be handled outside this generic driver */
624 +
625 + /* Assert reset the remote device, call reset_cb,
626 + * reset CB holds Reset according to the device needs. */
627 + VLYNQ_RESETCB(VLYNQ_RESET_ASSERT);
628 +
629 + /* Handle VLYNQ clock, HW default (Sense On Reset) is
630 + * usually input for all the devices. */
631 + if (options & VLYNQ_INIT_CONFIG_CLOCK)
632 + {
633 + vlynq_configClock(pdev);
634 + }
635 +
636 + /* Call reset_cb again. It will release the remote device
637 + * from reset, and wait for a while. */
638 + VLYNQ_RESETCB(VLYNQ_RESET_DEASSERT);
639 +
640 + if(options & VLYNQ_INIT_CHECK_LINK )
641 + {
642 + /* Check for link up during initialization*/
643 + while( counter < 25 )
644 + {
645 + /* loop around giving a chance for link status to settle down */
646 + counter++;
647 + if(vlynq_link_check(pdev))
648 + {
649 + /* Link is up exit loop*/
650 + break;
651 + }
652 +
653 + vlynq_delay(4000);
654 + }/*end of while counter loop */
655 +
656 + if(!vlynq_link_check(pdev))
657 + {
658 + /* Handle this case as abort */
659 + pdev->state = VLYNQ_DRV_STATE_ERROR;
660 + VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL);
661 + return VLYNQ_LINK_DOWN;
662 + }/* end of if not vlynq_link_check conditional block */
663 +
664 + }/*end of if options & VLYNQ_INIT_CHECK_LINK conditional block */
665 +
666 +
667 + if (options & VLYNQ_INIT_LOCAL_MEM_REGIONS)
668 + {
669 + /* Initialise local memory regions . This initialization lets
670 + * the local host access remote device memory regions*/
671 + int i;
672 +
673 + /* configure the VLYNQ portal window to a PHYSICAL
674 + * address of the local CPU */
675 + VLYNQ_ALIGN4(pdev->local_mem.Txmap);
676 + VLYNQ_TXMAP_REG = (pdev->local_mem.Txmap);
677 +
678 + /*This code assumes input parameter is itself a physical address */
679 + for(i=0; i < VLYNQ_MAX_MEMORY_REGIONS ; i++)
680 + {
681 + /* Physical address on the remote */
682 + map = i+1;
683 + VLYNQ_R_RXMAP_SIZE_REG(map) = 0;
684 + if( pdev->remote_mem.RxSize[i])
685 + {
686 + VLYNQ_ALIGN4(pdev->remote_mem.RxOffset[i]);
687 + VLYNQ_ALIGN4(pdev->remote_mem.RxSize[i]);
688 + VLYNQ_R_RXMAP_OFFSET_REG(map) = pdev->remote_mem.RxOffset[i];
689 + VLYNQ_R_RXMAP_SIZE_REG(map) = pdev->remote_mem.RxSize[i];
690 + }
691 + }
692 + }
693 +
694 + if(options & VLYNQ_INIT_REMOTE_MEM_REGIONS )
695 + {
696 + int i;
697 +
698 + /* Initialise remote memory regions. This initialization lets remote
699 + * device access local host memory regions. It configures the VLYNQ portal
700 + * window to a PHYSICAL address of the remote */
701 + VLYNQ_ALIGN4(pdev->remote_mem.Txmap);
702 + VLYNQ_R_TXMAP_REG = pdev->remote_mem.Txmap;
703 +
704 + for( i=0; i<VLYNQ_MAX_MEMORY_REGIONS; i++)
705 + {
706 + /* Physical address on the local */
707 + map = i+1;
708 + VLYNQ_RXMAP_SIZE_REG(map) = 0;
709 + if( pdev->local_mem.RxSize[i])
710 + {
711 + VLYNQ_ALIGN4(pdev->local_mem.RxOffset[i]);
712 + VLYNQ_ALIGN4(pdev->local_mem.RxSize[i]);
713 + VLYNQ_RXMAP_OFFSET_REG(map) = (pdev->local_mem.RxOffset[i]);
714 + VLYNQ_RXMAP_SIZE_REG(map) = (pdev->local_mem.RxSize[i]);
715 + }
716 + }
717 + }
718 +
719 + /* Adapted from original vlynq driver from cable - Calculate VLYNQ bus width */
720 + pdev->width = 3 + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_STATUS_REG)
721 + + VLYNQ_STATUS_FLD_WIDTH(VLYNQ_R_STATUS_REG);
722 +
723 + /* chance to initialize the device, e.g. to boost VLYNQ
724 + * clock by modifying pdev->clk_div or and verify the width. */
725 + VLYNQ_RESETCB(VLYNQ_RESET_LINKESTABLISH);
726 +
727 + /* Handle VLYNQ clock, HW default (Sense On Reset) is
728 + * usually input for all the devices. */
729 + if(options & VLYNQ_INIT_CONFIG_CLOCK )
730 + {
731 + vlynq_configClock(pdev);
732 + }
733 +
734 + /* last check for link*/
735 + if(options & VLYNQ_INIT_CHECK_LINK )
736 + {
737 + /* Final Check for link during initialization*/
738 + while( counter < 25 )
739 + {
740 + /* loop around giving a chance for link status to settle down */
741 + counter++;
742 + if(vlynq_link_check(pdev))
743 + {
744 + /* Link is up exit loop*/
745 + break;
746 + }
747 +
748 + vlynq_delay(4000);
749 + }/*end of while counter loop */
750 +
751 + if(!vlynq_link_check(pdev))
752 + {
753 + /* Handle this case as abort */
754 + pdev->state = VLYNQ_DRV_STATE_ERROR;
755 + VLYNQ_RESETCB( VLYNQ_RESET_INITFAIL);
756 + return VLYNQ_LINK_DOWN;
757 + }/* end of if not vlynq_link_check conditional block */
758 +
759 + } /* end of if options & VLYNQ_INIT_CHECK_LINK */
760 +
761 + if(options & VLYNQ_INIT_LOCAL_INTERRUPTS )
762 + {
763 + /* Configure local interrupt settings */
764 + intSetting = &(pdev->local_irq);
765 +
766 + /* Map local module status interrupts to interrupt vector*/
767 + val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ;
768 +
769 + /* enable local module status interrupts */
770 + val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT;
771 +
772 + if ( intSetting->intLocal == VLYNQ_INT_LOCAL )
773 + {
774 + /*set the intLocal bit*/
775 + val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT;
776 + }
777 +
778 + /* Irrespective of whether interrupts are handled locally, program
779 + * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1
780 + * i.e remote packets are set intPending register->which will result in
781 + * same packet being sent out) has been done already
782 + */
783 +
784 + if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR)
785 + {
786 + /* Set the int2Cfg register, so that remote interrupt
787 + * packets are written to intPending register */
788 + val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT;
789 +
790 + /* Set intPtr register to point to intPending register */
791 + VLYNQ_INT_PTR_REG = VLYNQ_INT_PENDING_REG_PTR ;
792 + }
793 + else
794 + {
795 + /*set the interrupt pointer register*/
796 + VLYNQ_INT_PTR_REG = intSetting->intr_ptr;
797 + /* Dont bother to modify int2Cfg as it would be zero */
798 + }
799 +
800 + /** Clear bits related to INT settings in control register **/
801 + VLYNQ_CTRL_REG = VLYNQ_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK);
802 +
803 + /** Or the bits to be set with Control register **/
804 + VLYNQ_CTRL_REG = VLYNQ_CTRL_REG | val;
805 +
806 + /* initialise local ICB */
807 + if(vlynqInterruptInit(pdev)==VLYNQ_MEMALLOC_FAIL)
808 + return VLYNQ_MEMALLOC_FAIL;
809 +
810 + /* Install handler for local module status interrupts. By default when
811 + * local interrupt setting is initialised, the local module status are
812 + * enabled and handler hooked up */
813 + if(vlynq_install_isr(pdev, intSetting->map_vector, vlynq_local_module_isr,
814 + pdev, NULL, NULL) == VLYNQ_INVALID_ARG)
815 + return VLYNQ_INVALID_ARG;
816 + } /* end of init local interrupts */
817 +
818 + if(options & VLYNQ_INIT_REMOTE_INTERRUPTS )
819 + {
820 + /* Configure remote interrupt settings from configuration */
821 + intSetting = &(pdev->remote_irq);
822 +
823 + /* Map remote module status interrupts to remote interrupt vector*/
824 + val = intSetting->map_vector << VLYNQ_CTL_INTVEC_SHIFT ;
825 + /* enable remote module status interrupts */
826 + val |= 0x01 << VLYNQ_CTL_INTEN_SHIFT;
827 +
828 + if ( intSetting->intLocal == VLYNQ_INT_LOCAL )
829 + {
830 + /*set the intLocal bit*/
831 + val |= 0x01 << VLYNQ_CTL_INTLOCAL_SHIFT;
832 + }
833 +
834 + /* Irrespective of whether interrupts are handled locally, program
835 + * int2Cfg. Error checking for accidental loop(when intLocal=0 and int2Cfg=1
836 + * i.e remote packets are set intPending register->which will result in
837 + * same packet being sent out) has been done already
838 + */
839 +
840 + if (intSetting->intRemote == VLYNQ_INT_ROOT_ISR)
841 + {
842 + /* Set the int2Cfg register, so that remote interrupt
843 + * packets are written to intPending register */
844 + val |= 0x01 << VLYNQ_CTL_INT2CFG_SHIFT;
845 + /* Set intPtr register to point to intPending register */
846 + VLYNQ_R_INT_PTR_REG = VLYNQ_R_INT_PENDING_REG_PTR ;
847 + }
848 + else
849 + {
850 + /*set the interrupt pointer register*/
851 + VLYNQ_R_INT_PTR_REG = intSetting->intr_ptr;
852 + /* Dont bother to modify int2Cfg as it would be zero */
853 + }
854 +
855 + if( (intSetting->intLocal == VLYNQ_INT_REMOTE) &&
856 + (options & VLYNQ_INIT_LOCAL_INTERRUPTS) &&
857 + (pdev->local_irq.intRemote == VLYNQ_INT_ROOT_ISR) )
858 + {
859 + /* Install handler for remote module status interrupts. By default when
860 + * remote interrupts are forwarded to local root_isr then remote_module_isr is
861 + * enabled and handler hooked up */
862 + if(vlynq_install_isr(pdev,intSetting->map_vector,vlynq_remote_module_isr,
863 + pdev, NULL, NULL) == VLYNQ_INVALID_ARG)
864 + return VLYNQ_INVALID_ARG;
865 + }
866 +
867 +
868 + /** Clear bits related to INT settings in control register **/
869 + VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG & (~VLYNQ_CTL_INTFIELDS_CLEAR_MASK);
870 +
871 + /** Or the bits to be set with the remote Control register **/
872 + VLYNQ_R_CTRL_REG = VLYNQ_R_CTRL_REG | val;
873 +
874 + } /* init remote interrupt settings*/
875 +
876 + if(options & VLYNQ_INIT_CLEAR_ERRORS )
877 + {
878 + /* Clear errors during initialization */
879 + tmp = VLYNQ_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK);
880 + VLYNQ_STATUS_REG = tmp;
881 + tmp = VLYNQ_R_STATUS_REG & (VLYNQ_STS_RERROR_MASK | VLYNQ_STS_LERROR_MASK);
882 + VLYNQ_R_STATUS_REG = tmp;
883 + }
884 +
885 + /* clear int status */
886 + val = VLYNQ_INT_STAT_REG;
887 + VLYNQ_INT_STAT_REG = val;
888 +
889 + /* finish initialization */
890 + pdev->state = VLYNQ_DRV_STATE_RUN;
891 + VLYNQ_RESETCB( VLYNQ_RESET_INITOK);
892 + return VLYNQ_SUCCESS;
893 +
894 +}
895 +
896 +
897 +/* ----------------------------------------------------------------------------
898 + * Function : vlynqInterruptInit()
899 + * Description: This local function is used to set up the ICB table for the
900 + * VLYNQ_STATUS_REG vlynq module. The input parameter "pdev" points the vlynq
901 + * device instance whose ICB is allocated.
902 + * Return : returns VLYNQ_SUCCESS or vlynq error for failure
903 + * -----------------------------------------------------------------------------
904 + */
905 +static int vlynqInterruptInit(VLYNQ_DEV *pdev)
906 +{
907 + int i, numslots;
908 +
909 + /* Memory allocated statically.
910 + * Initialise ICB,free list.Indicate primary slot empty.
911 + * Intialise intVector <==> map_vector translation table*/
912 + for(i=0; i < VLYNQ_NUM_INT_BITS; i++)
913 + {
914 + pdev->pIntrCB[i].isr = NULL;
915 + pdev->pIntrCB[i].next = NULL; /*nothing chained */
916 + pdev->vector_map[i] = -1; /* indicates unmapped */
917 + }
918 +
919 + /* In the ICB slots, [VLYNQ_NUM_INT_BITS i.e 32 to ICB array size) are expansion slots
920 + * required only when interrupt chaining/sharing is supported. In case
921 + * of chained interrupts the list starts from primary slot and the
922 + * additional slots are obtained from the common free area */
923 +
924 + /* Initialise freelist */
925 +
926 + numslots = VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS;
927 +
928 + if (numslots > VLYNQ_NUM_INT_BITS)
929 + {
930 + pdev->freelist = &(pdev->pIntrCB[VLYNQ_NUM_INT_BITS]);
931 +
932 + for(i = VLYNQ_NUM_INT_BITS; i < (numslots-1) ; i++)
933 + {
934 + pdev->pIntrCB[i].next = &(pdev->pIntrCB[i+1]);
935 + pdev->pIntrCB[i].isr = NULL;
936 + }
937 + pdev->pIntrCB[i].next=NULL; /* Indicate end of freelist*/
938 + pdev->pIntrCB[i].isr=NULL;
939 + }
940 + else
941 + {
942 + pdev->freelist = NULL;
943 + }
944 +
945 + /** Reset mapping for IV 0-7 **/
946 + VLYNQ_IVR_03TO00_REG = 0;
947 + VLYNQ_IVR_07TO04_REG = 0;
948 +
949 + return VLYNQ_SUCCESS;
950 +}
951 +
952 +/** remember that hooking up of root ISR handler with the interrupt controller
953 + * is not done as a part of this driver. Typically, it must be done after
954 + * invoking vlynq_init*/
955 +
956 +
957 + /* ----------------------------------------------------------------------------
958 + * ISR with the SOC interrupt controller. This ISR typically scans
959 + * the Int PENDING/SET register in the VLYNQ module and calls the
960 + * appropriate ISR associated with the correponding vector number.
961 + * -----------------------------------------------------------------------------
962 + */
963 +void vlynq_root_isr(void *arg)
964 +{
965 + int source; /* Bit position of pending interrupt, start from 0 */
966 + unsigned int interrupts, clrInterrupts;
967 + VLYNQ_DEV * pdev;
968 + VLYNQ_INTR_CNTRL_ICB *entry;
969 +
970 + pdev=(VLYNQ_DEV*)(arg); /*obtain the vlynq device pointer*/
971 +
972 + interrupts = VLYNQ_INT_STAT_REG; /* Get the list of pending interrupts */
973 + VLYNQ_INT_STAT_REG = interrupts; /* clear the int CR register */
974 + clrInterrupts = interrupts; /* save them for further analysis */
975 +
976 + debugPrint("vlynq_root_isr: dev %u. INTCR = 0x%08lx\n", pdev->dev_idx, clrInterrupts,0,0,0,0);
977 +
978 + /* Scan interrupt bits */
979 + source =0;
980 + while( clrInterrupts != 0)
981 + {
982 + /* test if bit is set? */
983 + if( 0x1ul & clrInterrupts)
984 + {
985 + entry = &(pdev->pIntrCB[source]); /* Get the ISR entry */
986 + pdev->intCount++; /* update interrupt count */
987 + if(entry->isr != NULL)
988 + {
989 + do
990 + {
991 + pdev->isrCount++; /* update isr invocation count */
992 + /* Call the user ISR and update the count for ISR */
993 + entry->isrCount++;
994 + entry->isr(entry->arg1, entry->arg2, entry->arg3);
995 + if (entry->next == NULL) break;
996 + entry = entry->next;
997 +
998 + } while (entry->isr != NULL);
999 + }
1000 + else
1001 + {
1002 + debugPrint(" ISR not installed for vlynq vector:%d\n",source,0,0,0,0,0);
1003 + }
1004 + }
1005 + clrInterrupts >>= 1; /* Next source bit */
1006 + ++source;
1007 + } /* endWhile clrInterrupts != 0 */
1008 +}
1009 +
1010 +
1011 + /* ----------------------------------------------------------------------------
1012 + * Function : vlynq_local__module_isr()
1013 + * Description: This ISR is attached to the local VLYNQ interrupt vector
1014 + * by the Vlynq Driver when local interrupts are being handled. i.e.
1015 + * intLocal=1. This ISR handles local Vlynq module status interrupts only
1016 + * AS a part of this ISR, user callback in VLYNQ_DEV structure
1017 + * is invoked.
1018 + * VLYNQ_DEV is passed as arg1. arg2 and arg3 are unused.
1019 + * -----------------------------------------------------------------------------
1020 + */
1021 +static void vlynq_local_module_isr(void *arg1,void *arg2, void *arg3)
1022 +{
1023 + VLYNQ_REPORT_CB func;
1024 + unsigned int dwStatRegVal;
1025 + VLYNQ_DEV * pdev;
1026 +
1027 + pdev = (VLYNQ_DEV*) arg1;
1028 + /* Callback function is read from the device pointer that is passed as an argument */
1029 + func = pdev->report_cb;
1030 +
1031 + /* read local status register */
1032 + dwStatRegVal = VLYNQ_STATUS_REG;
1033 +
1034 + /* clear pending events */
1035 + VLYNQ_STATUS_REG = dwStatRegVal;
1036 +
1037 + /* invoke user callback */
1038 + if( func != NULL)
1039 + func( pdev, VLYNQ_LOCAL_DVC, dwStatRegVal);
1040 +
1041 +}
1042 +
1043 + /* ----------------------------------------------------------------------------
1044 + * Function : vlynq_remote_module_isr()
1045 + * Description: This ISR is attached to the remote VLYNQ interrupt vector
1046 + * by the Vlynq Driver when remote interrupts are being handled locally. i.e.
1047 + * intLocal=1. This ISR handles local Vlynq module status interrupts only
1048 + * AS a part of this ISR, user callback in VLYNQ_DEV structure
1049 + * is invoked.
1050 + * The parameters irq,regs ar unused.
1051 + * -----------------------------------------------------------------------------
1052 + */
1053 +static void vlynq_remote_module_isr(void *arg1,void *arg2, void *arg3)
1054 +{
1055 + VLYNQ_REPORT_CB func;
1056 + unsigned int dwStatRegVal;
1057 + VLYNQ_DEV * pdev;
1058 +
1059 +
1060 + pdev = (VLYNQ_DEV*) arg1;
1061 +
1062 + /* Callback function is read from the device pointer that is passed as an argument */
1063 + func = pdev->report_cb;
1064 +
1065 + /* read local status register */
1066 + dwStatRegVal = VLYNQ_R_STATUS_REG;
1067 +
1068 + /* clear pending events */
1069 + VLYNQ_R_STATUS_REG = dwStatRegVal;
1070 +
1071 + /* invoke user callback */
1072 + if( func != NULL)
1073 + func( pdev, VLYNQ_REMOTE_DVC, dwStatRegVal);
1074 +
1075 +}
1076 +
1077 +/* ----------------------------------------------------------------------------
1078 + * Function : vlynq_interrupt_get_count()
1079 + * Description: This function returns the number of times a particular intr
1080 + * has been invoked.
1081 + *
1082 + * It returns 0, if erroneous map_vector is specified or if the corres isr
1083 + * has not been registered with VLYNQ.
1084 + */
1085 +unsigned int vlynq_interrupt_get_count(VLYNQ_DEV *pdev,
1086 + unsigned int map_vector)
1087 +{
1088 + VLYNQ_INTR_CNTRL_ICB *entry;
1089 + unsigned int count = 0;
1090 +
1091 + if (map_vector > (VLYNQ_NUM_INT_BITS-1))
1092 + return count;
1093 +
1094 + entry = &(pdev->pIntrCB[map_vector]);
1095 +
1096 + if (entry)
1097 + count = entry->isrCount;
1098 +
1099 + return (count);
1100 +}
1101 +
1102 +
1103 +/* ----------------------------------------------------------------------------
1104 + * Function : vlynq_install_isr()
1105 + * Description: This function installs ISR for Vlynq interrupt vector
1106 + * bits(in IntPending register). This function should be used only when
1107 + * Vlynq interrupts are being handled locally(remote may be programmed to send
1108 + * interrupt packets).Also, the int2cfg should be 1 and the least significant
1109 + * 8 bits of the Interrupt Pointer Register must point to Interrupt
1110 + * Pending/Set Register).
1111 + * If host int2cfg=0 and the Interrupt Pointer register contains
1112 + * the address of the interrupt set register in the interrupt controller
1113 + * module of the local device , then the ISR for the remote interrupt must be
1114 + * directly registered with the Interrupt controller and must not use this API
1115 + * Note: this function simply installs the ISR in ICB It doesnt modify
1116 + * any register settings
1117 + */
1118 +int
1119 +vlynq_install_isr(VLYNQ_DEV *pdev,
1120 + unsigned int map_vector,
1121 + VLYNQ_INTR_CNTRL_ISR isr,
1122 + void *arg1, void *arg2, void *arg3)
1123 +{
1124 + VLYNQ_INTR_CNTRL_ICB *entry;
1125 +
1126 + if ( (map_vector > (VLYNQ_NUM_INT_BITS-1)) || (isr == NULL) )
1127 + return VLYNQ_INVALID_ARG;
1128 +
1129 + entry = &(pdev->pIntrCB[map_vector]);
1130 +
1131 + if(entry->isr == NULL)
1132 + {
1133 + entry->isr = isr;
1134 + entry->arg1 = arg1;
1135 + entry->arg2 = arg2;
1136 + entry->arg3 = arg3;
1137 + entry->next = NULL;
1138 + }
1139 + else
1140 + {
1141 + /** No more empty slots,return error */
1142 + if(pdev->freelist == NULL)
1143 + return VLYNQ_MEMALLOC_FAIL;
1144 +
1145 + while(entry->next != NULL)
1146 + {
1147 + entry = entry->next;
1148 + }
1149 +
1150 + /* Append new node to the chain */
1151 + entry->next = pdev->freelist;
1152 + /* Remove the appended node from freelist */
1153 + pdev->freelist = pdev->freelist->next;
1154 + entry= entry->next;
1155 +
1156 + /*** Set the ICB fields ***/
1157 + entry->isr = isr;
1158 + entry->arg1 = arg1;
1159 + entry->arg2 = arg2;
1160 + entry->arg3 = arg3;
1161 + entry->next = NULL;
1162 + }
1163 +
1164 + return VLYNQ_SUCCESS;
1165 +}
1166 +
1167 +
1168 +
1169 +/* ----------------------------------------------------------------------------
1170 + * Function : vlynq_uninstall_isr
1171 + * Description: This function is used to uninstall a previously
1172 + * registered ISR. In case of shared/chained interrupts, the
1173 + * void * arg parameter must uniquely identify the ISR to be
1174 + * uninstalled.
1175 + * Note: this function simply uninstalls the ISR in ICB
1176 + * It doesnt modify any register settings
1177 + */
1178 +int
1179 +vlynq_uninstall_isr(VLYNQ_DEV *pdev,
1180 + unsigned int map_vector,
1181 + void *arg1, void *arg2, void *arg3)
1182 +{
1183 + VLYNQ_INTR_CNTRL_ICB *entry,*temp;
1184 +
1185 + if (map_vector > (VLYNQ_NUM_INT_BITS-1))
1186 + return VLYNQ_INVALID_ARG;
1187 +
1188 + entry = &(pdev->pIntrCB[map_vector]);
1189 +
1190 + if(entry->isr == NULL )
1191 + return VLYNQ_ISR_NON_EXISTENT;
1192 +
1193 + if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) )
1194 + {
1195 + if(entry->next == NULL)
1196 + {
1197 + entry->isr=NULL;
1198 + return VLYNQ_SUCCESS;
1199 + }
1200 + else
1201 + {
1202 + temp = entry->next;
1203 + /* Copy next node in the chain to prim.slot */
1204 + entry->isr = temp->isr;
1205 + entry->arg1 = temp->arg1;
1206 + entry->arg2 = temp->arg2;
1207 + entry->arg3 = temp->arg3;
1208 + entry->next = temp->next;
1209 + /* Free the just copied node */
1210 + temp->isr = NULL;
1211 + temp->arg1 = NULL;
1212 + temp->arg2 = NULL;
1213 + temp->arg3 = NULL;
1214 + temp->next = pdev->freelist;
1215 + pdev->freelist = temp;
1216 + return VLYNQ_SUCCESS;
1217 + }
1218 + }
1219 + else
1220 + {
1221 + temp = entry;
1222 + while ( (entry = temp->next) != NULL)
1223 + {
1224 + if ( (entry->arg1 == arg1) && (entry->arg2 == arg2) && (entry->arg3 == arg3) )
1225 + {
1226 + /* remove node from chain */
1227 + temp->next = entry->next;
1228 + /* Add the removed node to freelist */
1229 + entry->isr = NULL;
1230 + entry->arg1 = NULL;
1231 + entry->arg2 = NULL;
1232 + entry->arg3 = NULL;
1233 + entry->next = pdev->freelist;
1234 + entry->isrCount = 0;
1235 + pdev->freelist = entry;
1236 + return VLYNQ_SUCCESS;
1237 + }
1238 + temp = entry;
1239 + }
1240 +
1241 + return VLYNQ_ISR_NON_EXISTENT;
1242 + }
1243 +}
1244 +
1245 +
1246 +
1247 +
1248 +/* ----------------------------------------------------------------------------
1249 + * function : vlynq_interrupt_vector_set()
1250 + * description:configures interrupt vector mapping,interrupt type
1251 + * polarity -all in one go.
1252 + */
1253 +int
1254 +vlynq_interrupt_vector_set(VLYNQ_DEV *pdev, /* vlynq device */
1255 + unsigned int int_vector, /* int vector on vlynq device */
1256 + unsigned int map_vector, /* bit for this interrupt */
1257 + VLYNQ_DEV_TYPE dev_type, /* local or remote device */
1258 + VLYNQ_INTR_POLARITY pol, /* polarity of interrupt */
1259 + VLYNQ_INTR_TYPE type) /* pulsed/level interrupt */
1260 +{
1261 + volatile unsigned int * vecreg;
1262 + unsigned int val=0;
1263 + unsigned int bytemask=0XFF;
1264 +
1265 + /* use the lower 8 bits of val to set the value , shift it to
1266 + * appropriate byte position in the ivr and write it to the
1267 + * corresponding register */
1268 +
1269 + /* validate the number of interrupts supported */
1270 + if (int_vector >= VLYNQ_IVR_MAXIVR)
1271 + return VLYNQ_INVALID_ARG;
1272 +
1273 + if(map_vector > (VLYNQ_NUM_INT_BITS - 1) )
1274 + return VLYNQ_INVALID_ARG;
1275 +
1276 + if (dev_type == VLYNQ_LOCAL_DVC)
1277 + {
1278 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1279 + }
1280 + else
1281 + {
1282 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1283 + }
1284 +
1285 + /* Update the intVector<==> bit position translation table */
1286 + pdev->vector_map[map_vector] = int_vector;
1287 +
1288 + /* val has been initialised to zero. we only have to turn on appropriate bits*/
1289 + if(type == VLYNQ_INTR_PULSED)
1290 + val |= VLYNQ_IVR_INTTYPE_MASK;
1291 +
1292 + if(pol == VLYNQ_INTR_ACTIVE_LOW)
1293 + val |= VLYNQ_IVR_INTPOL_MASK;
1294 +
1295 + val |= map_vector;
1296 +
1297 + /** clear the correct byte position and then or val **/
1298 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1299 +
1300 + /** write to correct byte position in vecreg*/
1301 + *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
1302 +
1303 + /* Setting a interrupt vector, leaves the interrupt disabled
1304 + * which must be enabled subsequently */
1305 +
1306 + return VLYNQ_SUCCESS;
1307 +}
1308 +
1309 +
1310 +/* ----------------------------------------------------------------------------
1311 + * Function : vlynq_interrupt_vector_cntl()
1312 + * Description:enables/disable interrupt
1313 + */
1314 +int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev,
1315 + unsigned int int_vector,
1316 + VLYNQ_DEV_TYPE dev_type,
1317 + unsigned int enable)
1318 +{
1319 + volatile unsigned int *vecReg;
1320 + unsigned int val=0;
1321 + unsigned int intenMask=0x80;
1322 +
1323 + /* validate the number of interrupts supported */
1324 + if (int_vector >= VLYNQ_IVR_MAXIVR)
1325 + return VLYNQ_INVALID_ARG;
1326 +
1327 + if (dev_type == VLYNQ_LOCAL_DVC)
1328 + {
1329 + vecReg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1330 + }
1331 + else
1332 + {
1333 + vecReg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1334 + }
1335 +
1336 + /** Clear the correct byte position and then or val **/
1337 + *vecReg = (*vecReg) & ( ~(intenMask << ( (int_vector %4)*8) ) );
1338 +
1339 + if(enable)
1340 + {
1341 + val |= VLYNQ_IVR_INTEN_MASK;
1342 + /** Write to correct byte position in vecReg*/
1343 + *vecReg = (*vecReg) | (val << ( (int_vector % 4)*8) ) ;
1344 + }
1345 +
1346 + return VLYNQ_SUCCESS;
1347 +
1348 +}/* end of function vlynq_interrupt_vector_cntl */
1349 +
1350 +
1351 +
1352 +/* ----------------------------------------------------------------------------
1353 + * Function : vlynq_interrupt_vector_map()
1354 + * Description:Configures interrupt vector mapping alone
1355 + */
1356 +int
1357 +vlynq_interrupt_vector_map( VLYNQ_DEV *pdev,
1358 + VLYNQ_DEV_TYPE dev_type,
1359 + unsigned int int_vector,
1360 + unsigned int map_vector)
1361 +{
1362 + volatile unsigned int * vecreg;
1363 + unsigned int val=0;
1364 + unsigned int bytemask=0x1f; /* mask to turn off bits corresponding to int vector */
1365 +
1366 + /* use the lower 8 bits of val to set the value , shift it to
1367 + * appropriate byte position in the ivr and write it to the
1368 + * corresponding register */
1369 +
1370 + /* validate the number of interrupts supported */
1371 + if (int_vector >= VLYNQ_IVR_MAXIVR)
1372 + return VLYNQ_INVALID_ARG;
1373 +
1374 + if(map_vector > (VLYNQ_NUM_INT_BITS - 1) )
1375 + return VLYNQ_INVALID_ARG;
1376 +
1377 + if (dev_type == VLYNQ_LOCAL_DVC)
1378 + {
1379 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1380 + }
1381 + else
1382 + {
1383 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1384 + }
1385 +
1386 + /* Update the intVector<==> bit position translation table */
1387 + pdev->vector_map[map_vector] = int_vector;
1388 +
1389 + /** val has been initialised to zero. we only have to turn on
1390 + * appropriate bits*/
1391 + val |= map_vector;
1392 +
1393 + /** clear the correct byte position and then or val **/
1394 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1395 +
1396 + /** write to correct byte position in vecreg*/
1397 + *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
1398 +
1399 + return VLYNQ_SUCCESS;
1400 +}
1401 +
1402 +
1403 +/* ----------------------------------------------------------------------------
1404 + * function : vlynq_interrupt_set_polarity()
1405 + * description:configures interrupt polarity .
1406 + */
1407 +int
1408 +vlynq_interrupt_set_polarity( VLYNQ_DEV *pdev ,
1409 + VLYNQ_DEV_TYPE dev_type,
1410 + unsigned int map_vector,
1411 + VLYNQ_INTR_POLARITY pol)
1412 +{
1413 + volatile unsigned int * vecreg;
1414 + int int_vector;
1415 + unsigned int val=0;
1416 + unsigned int bytemask=0x20; /** mask to turn off bits corresponding to int polarity */
1417 +
1418 + /* get the int_vector from map_vector */
1419 + int_vector = pdev->vector_map[map_vector];
1420 +
1421 + if(int_vector == -1)
1422 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1423 +
1424 + /* use the lower 8 bits of val to set the value , shift it to
1425 + * appropriate byte position in the ivr and write it to the
1426 + * corresponding register */
1427 +
1428 + if (dev_type == VLYNQ_LOCAL_DVC)
1429 + {
1430 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1431 + }
1432 + else
1433 + {
1434 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1435 + }
1436 +
1437 + /* val has been initialised to zero. we only have to turn on
1438 + * appropriate bits, if need be*/
1439 +
1440 + /** clear the correct byte position and then or val **/
1441 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1442 +
1443 + if( pol == VLYNQ_INTR_ACTIVE_LOW)
1444 + {
1445 + val |= VLYNQ_IVR_INTPOL_MASK;
1446 + /** write to correct byte position in vecreg*/
1447 + *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
1448 + }
1449 +
1450 + return VLYNQ_SUCCESS;
1451 +}
1452 +
1453 +int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev ,
1454 + VLYNQ_DEV_TYPE dev_type,
1455 + unsigned int map_vector)
1456 +{
1457 + volatile unsigned int * vecreg;
1458 + int int_vector;
1459 + unsigned int val=0;
1460 +
1461 + /* get the int_vector from map_vector */
1462 + int_vector = pdev->vector_map[map_vector];
1463 +
1464 + if (map_vector > (VLYNQ_NUM_INT_BITS-1))
1465 + return(-1);
1466 +
1467 + if(int_vector == -1)
1468 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1469 +
1470 + /* use the lower 8 bits of val to set the value , shift it to
1471 + * appropriate byte position in the ivr and write it to the
1472 + * corresponding register */
1473 +
1474 + if (dev_type == VLYNQ_LOCAL_DVC)
1475 + {
1476 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1477 + }
1478 + else
1479 + {
1480 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1481 + }
1482 +
1483 + /** read the information into val **/
1484 + val = (*vecreg) & ((VLYNQ_IVR_INTPOL_MASK << ( (int_vector %4)*8) ) );
1485 +
1486 + return (val ? (VLYNQ_INTR_ACTIVE_LOW) : (VLYNQ_INTR_ACTIVE_HIGH));
1487 +}
1488 +
1489 +
1490 +/* ----------------------------------------------------------------------------
1491 + * function : vlynq_interrupt_set_type()
1492 + * description:configures interrupt type .
1493 + */
1494 +int vlynq_interrupt_set_type( VLYNQ_DEV *pdev,
1495 + VLYNQ_DEV_TYPE dev_type,
1496 + unsigned int map_vector,
1497 + VLYNQ_INTR_TYPE type)
1498 +{
1499 + volatile unsigned int * vecreg;
1500 + unsigned int val=0;
1501 + int int_vector;
1502 +
1503 + /** mask to turn off bits corresponding to interrupt type */
1504 + unsigned int bytemask=0x40;
1505 +
1506 + /* get the int_vector from map_vector */
1507 + int_vector = pdev->vector_map[map_vector];
1508 + if(int_vector == -1)
1509 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1510 +
1511 + /* use the lower 8 bits of val to set the value , shift it to
1512 + * appropriate byte position in the ivr and write it to the
1513 + * corresponding register */
1514 + if (dev_type == VLYNQ_LOCAL_DVC)
1515 + {
1516 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1517 + }
1518 + else
1519 + {
1520 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1521 + }
1522 +
1523 + /** val has been initialised to zero. we only have to turn on
1524 + * appropriate bits if need be*/
1525 +
1526 + /** clear the correct byte position and then or val **/
1527 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1528 +
1529 + if( type == VLYNQ_INTR_PULSED)
1530 + {
1531 + val |= VLYNQ_IVR_INTTYPE_MASK;
1532 + /** write to correct byte position in vecreg*/
1533 + *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
1534 + }
1535 +
1536 + return VLYNQ_SUCCESS;
1537 +}
1538 +
1539 +/* ----------------------------------------------------------------------------
1540 + * function : vlynq_interrupt_get_type()
1541 + * description:returns interrupt type .
1542 + */
1543 +int vlynq_interrupt_get_type( VLYNQ_DEV *pdev, VLYNQ_DEV_TYPE dev_type,
1544 + unsigned int map_vector)
1545 +{
1546 + volatile unsigned int * vecreg;
1547 + unsigned int val=0;
1548 + int int_vector;
1549 +
1550 + if (map_vector > (VLYNQ_NUM_INT_BITS-1))
1551 + return(-1);
1552 +
1553 + /* get the int_vector from map_vector */
1554 + int_vector = pdev->vector_map[map_vector];
1555 + if(int_vector == -1)
1556 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1557 +
1558 + /* use the lower 8 bits of val to set the value , shift it to
1559 + * appropriate byte position in the ivr and write it to the
1560 + * corresponding register */
1561 + if (dev_type == VLYNQ_LOCAL_DVC)
1562 + {
1563 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1564 + }
1565 + else
1566 + {
1567 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1568 + }
1569 +
1570 + /** Read the correct bit position into val **/
1571 + val = (*vecreg) & ((VLYNQ_IVR_INTTYPE_MASK << ( (int_vector %4)*8) ) );
1572 +
1573 + return (val ? (VLYNQ_INTR_PULSED) : (VLYNQ_INTR_LEVEL));
1574 +}
1575 +
1576 +/* ----------------------------------------------------------------------------
1577 + * function : vlynq_interrupt_enable()
1578 + * description:Enable interrupt by writing to IVR register.
1579 + */
1580 +int vlynq_interrupt_enable( VLYNQ_DEV *pdev,
1581 + VLYNQ_DEV_TYPE dev_type,
1582 + unsigned int map_vector)
1583 +{
1584 + volatile unsigned int * vecreg;
1585 + unsigned int val=0;
1586 + int int_vector;
1587 +
1588 + /** mask to turn off bits corresponding to interrupt enable */
1589 + unsigned int bytemask=0x80;
1590 +
1591 + /* get the int_vector from map_vector */
1592 + int_vector = pdev->vector_map[map_vector];
1593 + if(int_vector == -1)
1594 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1595 +
1596 + /* use the lower 8 bits of val to set the value , shift it to
1597 + * appropriate byte position in the ivr and write it to the
1598 + * corresponding register */
1599 +
1600 + if (dev_type == VLYNQ_LOCAL_DVC)
1601 + {
1602 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1603 + }
1604 + else
1605 + {
1606 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1607 + }
1608 +
1609 + /** val has been initialised to zero. we only have to turn on
1610 + * bit corresponding to interrupt enable*/
1611 + val |= VLYNQ_IVR_INTEN_MASK;
1612 +
1613 + /** clear the correct byte position and then or val **/
1614 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1615 +
1616 + /** write to correct byte position in vecreg*/
1617 + *vecreg = (*vecreg) | (val << ( (int_vector % 4)*8) ) ;
1618 +
1619 + return VLYNQ_SUCCESS;
1620 +}
1621 +
1622 +
1623 +/* ----------------------------------------------------------------------------
1624 + * function : vlynq_interrupt_disable()
1625 + * description:Disable interrupt by writing to IVR register.
1626 + */
1627 +int
1628 +vlynq_interrupt_disable( VLYNQ_DEV *pdev,
1629 + VLYNQ_DEV_TYPE dev_type,
1630 + unsigned int map_vector)
1631 +{
1632 + volatile unsigned int * vecreg;
1633 + int int_vector;
1634 +
1635 + /** mask to turn off bits corresponding to interrupt enable */
1636 + unsigned int bytemask=0x80;
1637 +
1638 + /* get the int_vector from map_vector */
1639 + int_vector = pdev->vector_map[map_vector];
1640 + if(int_vector == -1)
1641 + return VLYNQ_INTVEC_MAP_NOT_FOUND;
1642 +
1643 + /* use the lower 8 bits of val to set the value , shift it to
1644 + * appropriate byte position in the ivr and write it to the
1645 + * corresponding register */
1646 + if (dev_type == VLYNQ_LOCAL_DVC)
1647 + {
1648 + vecreg = (volatile unsigned int *) (VLYNQ_IVR_OFFSET(int_vector));
1649 + }
1650 + else
1651 + {
1652 + vecreg = (volatile unsigned int *) (VLYNQ_R_IVR_OFFSET(int_vector));
1653 + }
1654 +
1655 + /* We disable the interrupt by simply turning off the bit
1656 + * corresponding to Interrupt enable.
1657 + * Clear the interrupt enable bit in the correct byte position **/
1658 + *vecreg = (*vecreg) & ( ~(bytemask << ( (int_vector %4)*8) ) );
1659 +
1660 + /* Dont have to set any bit positions */
1661 +
1662 + return VLYNQ_SUCCESS;
1663 +
1664 +}
1665 +
1666 +
1667 +
1668 +
1669 diff -urN linux.old/drivers/char/Config.in linux.dev/drivers/char/Config.in
1670 --- linux.old/drivers/char/Config.in 2005-07-10 20:50:43.556826000 +0200
1671 +++ linux.dev/drivers/char/Config.in 2005-07-22 06:32:53.359187480 +0200
1672 @@ -192,6 +192,13 @@
1673 tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL
1674 fi
1675
1676 +if [ "$CONFIG_AR7" = "y" ]; then
1677 + bool 'VLYNQ support for the TI SOC' CONFIG_AR7_VLYNQ
1678 + dep_bool 'VLYNQ clock source Internal' CONFIG_VLYNQ_CLK_LOCAL $CONFIG_AR7_VLYNQ
1679 +
1680 + define_int CONFIG_AR7_VLYNQ_PORTS 2
1681 +fi
1682 +
1683 source drivers/i2c/Config.in
1684
1685 mainmenu_option next_comment
1686 diff -urN linux.old/drivers/char/Makefile linux.dev/drivers/char/Makefile
1687 --- linux.old/drivers/char/Makefile 2005-07-10 20:50:43.556826000 +0200
1688 +++ linux.dev/drivers/char/Makefile 2005-07-22 06:32:53.360187328 +0200
1689 @@ -191,16 +191,23 @@
1690 endif
1691
1692 #
1693 +# Texas Intruments VLYNQ driver
1694 +#
1695 +
1696 +subdir-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq
1697 +obj-$(CONFIG_AR7_VLYNQ) += avalanche_vlynq/avalanche_vlynq.o
1698 +
1699 +#
1700 # Texas Intruments LED driver
1701 #
1702 -ifeq ($(CONFIG_MIPS_AVALANCHE_LED),y)
1703 -obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
1704 -subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
1705 +ifeq ($(CONFIG_AR7_LED),y)
1706 +obj-$(CONFIG_AR7_LED) += avalanche_led/avalanche_led.o
1707 +subdir-$(CONFIG_AR7_LED) += avalanche_led
1708 endif
1709
1710 -ifeq ($(CONFIG_MIPS_AVALANCHE_LED),m)
1711 -obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
1712 -subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
1713 +ifeq ($(CONFIG_AR7_LED),m)
1714 +obj-$(CONFIG_AR7_LED) += avalanche_led/avalanche_led.o
1715 +subdir-$(CONFIG_AR7_LED) += avalanche_led
1716 endif
1717
1718 obj-$(CONFIG_HIL) += hp_keyb.o
1719 diff -urN linux.old/include/asm-mips/ar7/vlynq.h linux.dev/include/asm-mips/ar7/vlynq.h
1720 --- linux.old/include/asm-mips/ar7/vlynq.h 1970-01-01 01:00:00.000000000 +0100
1721 +++ linux.dev/include/asm-mips/ar7/vlynq.h 2005-07-22 06:32:53.361187176 +0200
1722 @@ -0,0 +1,610 @@
1723 +/***************************************************************************
1724 +**+----------------------------------------------------------------------+**
1725 +**| **** |**
1726 +**| **** |**
1727 +**| ******o*** |**
1728 +**| ********_///_**** |**
1729 +**| ***** /_//_/ **** |**
1730 +**| ** ** (__/ **** |**
1731 +**| ********* |**
1732 +**| **** |**
1733 +**| *** |**
1734 +**| |**
1735 +**| Copyright (c) 2003 Texas Instruments Incorporated |**
1736 +**| ALL RIGHTS RESERVED |**
1737 +**| |**
1738 +**| Permission is hereby granted to licensees of Texas Instruments |**
1739 +**| Incorporated (TI) products to use this computer program for the sole |**
1740 +**| purpose of implementing a licensee product based on TI products. |**
1741 +**| No other rights to reproduce, use, or disseminate this computer |**
1742 +**| program, whether in part or in whole, are granted. |**
1743 +**| |**
1744 +**| TI makes no representation or warranties with respect to the |**
1745 +**| performance of this computer program, and specifically disclaims |**
1746 +**| any responsibility for any damages, special or consequential, |**
1747 +**| connected with the use of this program. |**
1748 +**| |**
1749 +**+----------------------------------------------------------------------+**
1750 +***************************************************************************/
1751 +
1752 +/*********************************************************************************
1753 + * ------------------------------------------------------------------------------
1754 + * Module : vlynq_hal.h
1755 + * Description :
1756 + * This header file provides the set of functions exported by the
1757 + * VLYNQ HAL. This file is included from the SOC specific VLYNQ driver wrapper.
1758 + * ------------------------------------------------------------------------------
1759 + *********************************************************************************/
1760 +
1761 +#ifndef _VLYNQ_HAL_H_
1762 +#define _VLYNQ_HAL_H_
1763 +
1764 +/* Enable/Disable debug feature */
1765 +#undef VLYNQ_DEBUG
1766 +
1767 +#ifdef VLYNQ_DEBUG /* This needs to be OS abstracted - for testing use vxworks/linux calls */
1768 +#define debugPrint(format,args...)
1769 +#else
1770 +#define debugPrint(format,args...)
1771 +#endif
1772 +
1773 + /* number of VLYNQ memory regions supported */
1774 +#define VLYNQ_MAX_MEMORY_REGIONS 0x04
1775 +
1776 + /* Max.number of external interrupt inputs supported by VLYNQ module */
1777 +#define VLYNQ_IVR_MAXIVR 0x08
1778 +
1779 +#define VLYNQ_CLK_DIV_MAX 0x08
1780 +#define VLYNQ_CLK_DIV_MIN 0x01
1781 +
1782 +
1783 +/*** the total number of entries allocated for ICB would be
1784 + * 32(for 32 bits in IntPending register) + VLYNQ_IVR_CHAIN_SLOTS*/
1785 +#define VLYNQ_IVR_CHAIN_SLOTS 10
1786 +
1787 +
1788 +/* Error defines */
1789 +#define VLYNQ_SUCCESS 0
1790 +
1791 +#define VLYNQ_ERRCODE_BASE 0 /* Chosen by system */
1792 +#define VLYNQ_INVALID_ARG -(VLYNQ_ERRCODE_BASE+1)
1793 +#define VLYNQ_INVALID_DRV_STATE -(VLYNQ_ERRCODE_BASE+2)
1794 +#define VLYNQ_INT_CONFIG_ERR -(VLYNQ_ERRCODE_BASE+3)
1795 +#define VLYNQ_LINK_DOWN -(VLYNQ_ERRCODE_BASE+4)
1796 +#define VLYNQ_MEMALLOC_FAIL -(VLYNQ_ERRCODE_BASE+5)
1797 +#define VLYNQ_ISR_NON_EXISTENT -(VLYNQ_ERRCODE_BASE+6)
1798 +#define VLYNQ_INTVEC_MAP_NOT_FOUND -(VLYNQ_ERRCODE_BASE+7)
1799 +
1800 +/* Vlynq Defines and Macros */
1801 +
1802 +#define VLYNQ_NUM_INT_BITS 32 /* 32 bit interrupt staus register */
1803 +
1804 +/* Base address of module */
1805 +#define VLYNQ_BASE (pdev->module_base)
1806 +
1807 +#define VLYNQ_REMOTE_REGS_OFFSET 0x0080
1808 +
1809 +#define VLYNQ_REV_OFFSET 0x0000
1810 +#define VLYNQ_CTRL_OFFSET 0x0004
1811 +#define VLYNQ_STATUS_OFFSET 0x0008
1812 +#define VLYNQ_INT_STAT_OFFSET 0x0010
1813 +#define VLYNQ_INT_PEND_OFFSET 0x0014
1814 +#define VLYNQ_INT_PTR_OFFSET 0x0018
1815 +#define VLYNQ_TXMAP_OFFSET 0x001c
1816 +
1817 +#define VLYNQ_RX0MAP_SIZE_REG_OFFSET 0x0020
1818 +#define VLYNQ_RX0MAP_OFFSET_REG_OFFSET 0x0024
1819 +
1820 +#define VLYNQ_CHIP_VER_OFFSET 0x0040
1821 +#define VLYNQ_IVR_REGS_OFFSET 0x0060
1822 +
1823 +#define VLYNQ_INT_PENDING_REG_PTR 0x14
1824 +#define VLYNQ_R_INT_PENDING_REG_PTR VLYNQ_REMOTE_REGS_OFFSET + 0x14
1825 +
1826 +#define VLYNQ_REV_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_REV_OFFSET))
1827 +#define VLYNQ_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CTRL_OFFSET))
1828 +#define VLYNQ_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_STATUS_OFFSET))
1829 +#define VLYNQ_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_STAT_OFFSET))
1830 +#define VLYNQ_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PEND_OFFSET))
1831 +#define VLYNQ_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_INT_PTR_OFFSET))
1832 +#define VLYNQ_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_TXMAP_OFFSET))
1833 +
1834 +/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
1835 +#define VLYNQ_RXMAP_SIZE_REG(map) \
1836 + *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_SIZE_REG_OFFSET+( (map-1)<<3)))
1837 +
1838 +/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
1839 +#define VLYNQ_RXMAP_OFFSET_REG(map) \
1840 + *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_RX0MAP_OFFSET_REG_OFFSET+( (map-1)<<3)))
1841 +
1842 +#define VLYNQ_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE+VLYNQ_CHIP_VER_OFFSET))
1843 +
1844 +/* 0 =< ivr <= 31; currently ivr < VLYNQ_IVR_MAXIVR=8) */
1845 +#define VLYNQ_IVR_OFFSET(ivr) \
1846 + (VLYNQ_BASE + VLYNQ_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3) )
1847 +
1848 +#define VLYNQ_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(0)) )
1849 +#define VLYNQ_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_IVR_OFFSET(4)) )
1850 +/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
1851 +
1852 +#define VLYNQ_IVR_INTEN(ivr) (((unsigned int)(0x80)) << ((((unsigned)(ivr)) % 4) * 8))
1853 +#define VLYNQ_IVR_INTTYPE(ivr) (((unsigned int)(0x40)) << ((((unsigned)(ivr)) % 4) * 8))
1854 +#define VLYNQ_IVR_INTPOL(ivr) (((unsigned int)(0x20)) << ((((unsigned)(ivr)) % 4) * 8))
1855 +#define VLYNQ_IVR_INTVEC(ivr) (((unsigned int)(0x1F)) << ((((unsigned)(ivr)) % 4) * 8))
1856 +#define VLYNQ_IVR_INTALL(ivr) (((unsigned int)(0xFF)) << ((((unsigned)(ivr)) % 4) * 8))
1857 +
1858 +
1859 +
1860 +/*********************************
1861 + * Remote VLYNQ register set *
1862 + *********************************/
1863 +
1864 +#define VLYNQ_R_REV_OFFSET 0x0080
1865 +#define VLYNQ_R_CTRL_OFFSET 0x0084
1866 +#define VLYNQ_R_STATUS_OFFSET 0x0088
1867 +#define VLYNQ_R_INT_STAT_OFFSET 0x0090
1868 +#define VLYNQ_R_INT_PEND_OFFSET 0x0094
1869 +#define VLYNQ_R_INT_PTR_OFFSET 0x0098
1870 +#define VLYNQ_R_TXMAP_OFFSET 0x009c
1871 +
1872 +#define VLYNQ_R_RX0MAP_SIZE_REG_OFFSET 0x00A0
1873 +#define VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET 0x00A4
1874 +
1875 +#define VLYNQ_R_CHIP_VER_OFFSET 0x00C0
1876 +#define VLYNQ_R_IVR_REGS_OFFSET 0x00E0
1877 +
1878 +#define VLYNQ_R_REV_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_REV_OFFSET))
1879 +#define VLYNQ_R_CTRL_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CTRL_OFFSET))
1880 +#define VLYNQ_R_STATUS_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_STATUS_OFFSET))
1881 +#define VLYNQ_R_INT_STAT_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_STAT_OFFSET))
1882 +#define VLYNQ_R_INT_PEND_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PEND_OFFSET))
1883 +#define VLYNQ_R_INT_PTR_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_INT_PTR_OFFSET))
1884 +#define VLYNQ_R_TXMAP_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_TXMAP_OFFSET))
1885 +
1886 +/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
1887 +#define VLYNQ_R_RXMAP_SIZE_REG(map) \
1888 + *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_SIZE_REG_OFFSET + ((map-1)<<3)))
1889 +
1890 +/** map takes on values between 1 to VLYNQ_MAX_MEMORY_REGIONS **/
1891 +#define VLYNQ_R_RXMAP_OFFSET_REG(map) \
1892 + *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_RX0MAP_OFFSET_REG_OFFSET + ((map-1)<<3)))
1893 +
1894 +#define VLYNQ_R_CHIP_VER_REG *((volatile unsigned int *)(VLYNQ_BASE + VLYNQ_R_CHIP_VER_OFFSET)
1895 +
1896 +#define VLYNQ_R_IVR_OFFSET(ivr) \
1897 + (VLYNQ_BASE + VLYNQ_R_IVR_REGS_OFFSET +((((unsigned)(ivr)) & 31) & ~3))
1898 +
1899 +
1900 +/*** Can be extended for 11TO08...31TO28 when all 31 are supported**/
1901 +#define VLYNQ_R_IVR_03TO00_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(0)) )
1902 +#define VLYNQ_R_IVR_07TO04_REG *((volatile unsigned int*) (VLYNQ_R_IVR_OFFSET(4)) )
1903 +
1904 +
1905 +/****End of remote register set definition******/
1906 +
1907 +
1908 +/*** Masks for individual register fields ***/
1909 +
1910 +#define VLYNQ_MODULE_ID_MASK 0xffff0000
1911 +#define VLYNQ_MAJOR_REV_MASK 0x0000ff00
1912 +#define VLYNQ_MINOR_REV_MASK 0x000000ff
1913 +
1914 +
1915 +#define VLYNQ_CTL_ILOOP_MASK 0x00000002
1916 +#define VLYNQ_CTL_INT2CFG_MASK 0x00000080
1917 +#define VLYNQ_CTL_INTVEC_MASK 0x00001f00
1918 +#define VLYNQ_CTL_INTEN_MASK 0x00002000
1919 +#define VLYNQ_CTL_INTLOCAL_MASK 0x00004000
1920 +#define VLYNQ_CTL_CLKDIR_MASK 0x00008000
1921 +#define VLYNQ_CTL_CLKDIV_MASK 0x00070000
1922 +#define VLYNQ_CTL_MODE_MASK 0x00e00000
1923 +
1924 +
1925 +#define VLYNQ_STS_LINK_MASK 0x00000001 /* Link is active */
1926 +#define VLYNQ_STS_MPEND_MASK 0x00000002 /* Pending master requests */
1927 +#define VLYNQ_STS_SPEND_MASK 0x00000004 /* Pending slave requests */
1928 +#define VLYNQ_STS_NFEMPTY0_MASK 0x00000008 /* Master data FIFO not empty */
1929 +#define VLYNQ_STS_NFEMPTY1_MASK 0x00000010 /* Master command FIFO not empty */
1930 +#define VLYNQ_STS_NFEMPTY2_MASK 0x00000020 /* Slave data FIFO not empty */
1931 +#define VLYNQ_STS_NFEMPTY3_MASK 0x00000040 /* Slave command FIFO not empty */
1932 +#define VLYNQ_STS_LERROR_MASK 0x00000080 /* Local error, w/c */
1933 +#define VLYNQ_STS_RERROR_MASK 0x00000100 /* remote error w/c */
1934 +#define VLYNQ_STS_OFLOW_MASK 0x00000200
1935 +#define VLYNQ_STS_IFLOW_MASK 0x00000400
1936 +#define VLYNQ_STS_MODESUP_MASK 0x00E00000 /* Highest mode supported */
1937 +#define VLYNQ_STS_SWIDTH_MASK 0x07000000 /* Used for reading the width of VLYNQ bus */
1938 +#define VLYNQ_STS_DEBUG_MASK 0xE0000000
1939 +
1940 +#define VLYNQ_CTL_INTVEC_SHIFT 0x08
1941 +#define VLYNQ_CTL_INTEN_SHIFT 0x0D
1942 +#define VLYNQ_CTL_INT2CFG_SHIFT 0x07
1943 +#define VLYNQ_CTL_INTLOCAL_SHIFT 0x0E
1944 +
1945 +#define VLYNQ_CTL_INTFIELDS_CLEAR_MASK 0x7F80
1946 +
1947 +#define VLYNQ_CHIPVER_DEVREV_MASK 0xffff0000
1948 +#define VLYNQ_CHIPVER_DEVID_MASK 0x0000ffff
1949 +
1950 +#define VLYNQ_IVR_INTEN_MASK 0x80
1951 +#define VLYNQ_IVR_INTTYPE_MASK 0x40
1952 +#define VLYNQ_IVR_INTPOL_MASK 0x20
1953 +
1954 +
1955 +/**** Helper macros ****/
1956 +
1957 +#define VLYNQ_RESETCB(arg) \
1958 + if( pdev->reset_cb != NULL) \
1959 + { \
1960 + (pdev->reset_cb)(pdev, (arg)); \
1961 + }
1962 +
1963 +#define VLYNQ_STATUS_FLD_WIDTH(sts) (((sts) & VLYNQ_STS_SWIDTH_MASK) >> 24 )
1964 +#define VLYNQ_CTL_INTVEC(x) (((x) & 31) << 8 )
1965 +
1966 +#define VLYNQ_INRANGE(x,hi,lo) (((x) <= (hi)) && ((x) >= (lo)))
1967 +#define VLYNQ_OUTRANGE(x,hi,lo) (((x) > (hi)) || ((x) < (lo)))
1968 +
1969 +#define VLYNQ_ALIGN4(x) (x)=(x)&(~3)
1970 +
1971 +
1972 +/*************************************
1973 + * Enums *
1974 + *************************************/
1975 +
1976 +/* Initialization options define what operations are
1977 + * undertaken during vlynq module initialization */
1978 +typedef enum
1979 +{
1980 + /* Init host local memory regions.This allows
1981 + * local host access remote memory regions */
1982 + VLYNQ_INIT_LOCAL_MEM_REGIONS = 0x01,
1983 + /* Init host remote memory regions.This allows
1984 + * remote device access local memory regions */
1985 + VLYNQ_INIT_REMOTE_MEM_REGIONS =0x02,
1986 + /* Init local interrupt config*/
1987 + VLYNQ_INIT_LOCAL_INTERRUPTS =0x04,
1988 + /* Init remote interrupt config*/
1989 + VLYNQ_INIT_REMOTE_INTERRUPTS =0x08,
1990 + /* Check link during initialization*/
1991 + VLYNQ_INIT_CHECK_LINK =0x10,
1992 + /* configure clock during init */
1993 + VLYNQ_INIT_CONFIG_CLOCK =0x20,
1994 + /* Clear errors during init */
1995 + VLYNQ_INIT_CLEAR_ERRORS =0x40,
1996 + /* All options */
1997 + VLYNQ_INIT_PERFORM_ALL =0x7F
1998 +}VLYNQ_INIT_OPTIONS;
1999 +
2000 +
2001 +/* VLYNQ_DEV_TYPE identifies local or remote device */
2002 +typedef enum
2003 +{
2004 + VLYNQ_LOCAL_DVC = 0, /* vlynq local device (SOC's vlynq module) */
2005 + VLYNQ_REMOTE_DVC = 1 /* vlynq remote device (remote vlynq module) */
2006 +}VLYNQ_DEV_TYPE;
2007 +
2008 +
2009 +/* VLYNQ_CLK_SOURCE identifies the vlynq module clock source */
2010 +typedef enum
2011 +{
2012 + VLYNQ_CLK_SOURCE_NONE = 0, /* do not initialize clock generator*/
2013 + VLYNQ_CLK_SOURCE_LOCAL = 1, /* clock is generated by local machine */
2014 + VLYNQ_CLK_SOURCE_REMOTE = 2 /* clock is generated by remote machine */
2015 +}VLYNQ_CLK_SOURCE;
2016 +
2017 +
2018 +/* VLYNQ_DRV_STATE indicates the current driver state */
2019 +typedef enum
2020 +{
2021 + VLYNQ_DRV_STATE_UNINIT = 0, /* driver is uninitialized */
2022 + VLYNQ_DRV_STATE_ININIT = 1, /* VLYNQ is being initialized */
2023 + VLYNQ_DRV_STATE_RUN = 2, /* VLYNQ is running properly */
2024 + VLYNQ_DRV_STATE_HOLD = 3, /* driver stopped temporarily */
2025 + VLYNQ_DRV_STATE_ERROR = 4 /* driver stopped on unrecoverable error */
2026 +}VLYNQ_DRV_STATE;
2027 +
2028 +
2029 +/* VLYNQ_BUS_WIDTH identifies the vlynq module bus width */
2030 +typedef enum
2031 +{
2032 + VLYNQ_BUS_WIDTH_3 = 3,
2033 + VLYNQ_BUS_WIDTH_5 = 5,
2034 + VLYNQ_BUS_WIDTH_7 = 7,
2035 + VLYNQ_BUS_WIDTH_9 = 9
2036 +}VLYNQ_BUS_WIDTH;
2037 +
2038 +
2039 +/* VLYNQ_LOCAL_INT_CONFIG indicates whether the local vlynq
2040 + * interrupts are processed by the host or passed on to the
2041 + * remote device.
2042 + */
2043 +typedef enum
2044 +{
2045 + VLYNQ_INT_REMOTE = 0, /* Interrupt packets sent to remote, intlocal=0 */
2046 + VLYNQ_INT_LOCAL = 1 /* Interrupts are handled locally, intlocal=1 */
2047 +}VLYNQ_LOCAL_INT_CONFIG;
2048 +
2049 +
2050 +/* VLYNQ_REMOTE_INT_CONFIG indicates whether the remote
2051 + * interrupts are to be handled by the SOC system ISR
2052 + * or via the vlynq root ISR
2053 + */
2054 +typedef enum
2055 +{
2056 + VLYNQ_INT_ROOT_ISR = 0, /* remote ints handled via vlynq root ISR */
2057 + VLYNQ_INT_SYSTEM_ISR = 1 /* remote ints handled via system ISR */
2058 +}VLYNQ_REMOTE_INT_CONFIG;
2059 +
2060 +
2061 +/* VLYNQ_INTR_POLARITY - vlynq interrupt polarity setting */
2062 +typedef enum
2063 +{
2064 + VLYNQ_INTR_ACTIVE_HIGH = 0,
2065 + VLYNQ_INTR_ACTIVE_LOW = 1
2066 +}VLYNQ_INTR_POLARITY;
2067 +
2068 +
2069 +/* VLYNQ_INTR_TYPE - vlynq interrupt type */
2070 +typedef enum
2071 +{
2072 + VLYNQ_INTR_LEVEL = 0,
2073 + VLYNQ_INTR_PULSED = 1
2074 +}VLYNQ_INTR_TYPE;
2075 +
2076 +
2077 +/* VLYNQ_RESET_MODE - vlynq reset mode */
2078 +typedef enum
2079 +{
2080 + VLYNQ_RESET_ASSERT, /* hold device in reset state */
2081 + VLYNQ_RESET_DEASSERT, /* release device from reset state */
2082 + VLYNQ_RESET_INITFAIL, /* handle the device in case driver initialization fails */
2083 + VLYNQ_RESET_LINKESTABLISH, /* handle the device in case driver established link */
2084 + VLYNQ_RESET_INITFAIL2, /* Driver initialization failed but VLYNQ link exist. */
2085 + VLYNQ_RESET_INITOK /* Driver initialization finished OK. */
2086 +}VLYNQ_RESET_MODE;
2087 +
2088 +
2089 +
2090 +/*************************************
2091 + * Typedefs *
2092 + *************************************/
2093 +
2094 +struct VLYNQ_DEV_t; /*forward declaration*/
2095 +
2096 +/*--------Function Pointers defintions -----------*/
2097 +
2098 +/* prototype for interrupt handler definition */
2099 +typedef void (*VLYNQ_INTR_CNTRL_ISR)(void *arg1,void *arg2,void *arg3);
2100 +
2101 +typedef void
2102 +(*VLYNQ_RESET_REMOTE)(struct VLYNQ_DEV_t *pDev, VLYNQ_RESET_MODE mode);
2103 +
2104 +typedef void
2105 +(*VLYNQ_REPORT_CB)( struct VLYNQ_DEV_t *pDev, /* This VLYNQ */
2106 + VLYNQ_DEV_TYPE aSrcDvc, /* Event Cause -local/remote? */
2107 + unsigned int dwStatRegVal); /* Value of the relevant status register */
2108 +
2109 +
2110 +/*-------Structure Definitions------------*/
2111 +
2112 +typedef struct VLYNQ_MEMORY_MAP_t
2113 +{
2114 + unsigned int Txmap;
2115 + unsigned int RxOffset[VLYNQ_MAX_MEMORY_REGIONS];
2116 + unsigned int RxSize[VLYNQ_MAX_MEMORY_REGIONS];
2117 +}VLYNQ_MEMORY_MAP;
2118 +
2119 +
2120 +/**VLYNQ_INTERRUPT_CNTRL - defines the vlynq module interrupt
2121 + * settings in vlynq Control register */
2122 +typedef struct VLYNQ_INTERRUPT_CNTRL_t
2123 +{
2124 + /* vlynq interrupts handled by host or remote - maps to
2125 + * intLocal bit in vlynq control register */
2126 + VLYNQ_LOCAL_INT_CONFIG intLocal;
2127 +
2128 + /* remote interrupts handled by vlynq isr or host system
2129 + * interrupt controller - maps to the int2Cfg in vlynq
2130 + * control register */
2131 + VLYNQ_REMOTE_INT_CONFIG intRemote;
2132 +
2133 + /* bit in pending/set register used for module interrupts*/
2134 + unsigned int map_vector;
2135 +
2136 + /* used only if remote interrupts are to be handled by system ISR*/
2137 + unsigned int intr_ptr;
2138 +
2139 +}VLYNQ_INTERRUPT_CNTRL;
2140 +
2141 +
2142 +/* VLYNQ_INTR_CNTRL_ICB - defines the Interrupt control block which hold
2143 + * the interrupt dispatch table. The vlynq_root_isr() indexes into this
2144 + * table to identify the ISR to be invoked
2145 + */
2146 +typedef struct VLYNQ_INTR_CNTRL_ICB_t
2147 +{
2148 + VLYNQ_INTR_CNTRL_ISR isr; /* Clear errors during initialization */
2149 + void *arg1 ; /* Arg 1 for the ISR */
2150 + void *arg2 ; /* Arg 2 for the ISR */
2151 + void *arg3 ; /* Arg 3 for the ISR */
2152 + unsigned int isrCount; /* number of ISR invocations so far */
2153 + struct VLYNQ_INTR_CNTRL_ICB_t *next;
2154 +}VLYNQ_INTR_CNTRL_ICB;
2155 +
2156 +/* overlay of vlynq register set */
2157 +typedef struct VLYNQ_REG_SET_t
2158 +{
2159 + unsigned int revision; /*offset : 0x00 */
2160 + unsigned int control; /* 0x04*/
2161 + unsigned int status; /* 0x08*/
2162 + unsigned int pad1; /* 0x0c*/
2163 + unsigned int intStatus; /*0x10*/
2164 + unsigned int intPending; /*0x14*/
2165 + unsigned int intPtr; /*0x18*/
2166 + unsigned int txMap; /*0x1C*/
2167 + unsigned int rxSize1; /*0x20*/
2168 + unsigned int rxOffset1; /*0x24*/
2169 + unsigned int rxSize2; /*0x28*/
2170 + unsigned int rxOffset2; /*0x2C*/
2171 + unsigned int rxSize3; /*0x30*/
2172 + unsigned int rxOffset3; /*0x34*/
2173 + unsigned int rxSize4; /*0x38*/
2174 + unsigned int rxOffset4; /*0x3C*/
2175 + unsigned int chipVersion; /*0x40*/
2176 + unsigned int pad2[8];
2177 + unsigned int ivr30; /*0x60*/
2178 + unsigned int ivr74; /*0x64*/
2179 + unsigned int pad3[7];
2180 +}VLYNQ_REG_SET;
2181 +
2182 +
2183 +typedef struct VLYNQ_DEV_t
2184 +{
2185 + /** module index:1,2,3... used for debugging purposes */
2186 + unsigned int dev_idx;
2187 +
2188 + /*VLYNQ module base address */
2189 + unsigned int module_base;
2190 +
2191 + /* clock source selection */
2192 + VLYNQ_CLK_SOURCE clk_source;
2193 +
2194 + /* Clock Divider.Val=1 to 8. VLYNQ_clk = VBUSCLK/clk_div */
2195 + unsigned int clk_div;
2196 +
2197 + /* State of the VLYNQ driver, set to VLYNQ_DRV_STATE_UNINIT, when initializing */
2198 + VLYNQ_DRV_STATE state;
2199 +
2200 + /* Valid VLYNQ bus width, filled by driver */
2201 + VLYNQ_BUS_WIDTH width;
2202 +
2203 + /* local memory mapping */
2204 + VLYNQ_MEMORY_MAP local_mem;
2205 +
2206 + /* remote memory mapping */
2207 + VLYNQ_MEMORY_MAP remote_mem;
2208 +
2209 + /* Local module interrupt params */
2210 + VLYNQ_INTERRUPT_CNTRL local_irq;
2211 +
2212 + /* remote module interrupt params */
2213 + VLYNQ_INTERRUPT_CNTRL remote_irq;
2214 +
2215 + /*** ICB related fields **/
2216 +
2217 + /* Sizeof of ICB = VLYNQ_NUM_INT_BITS(for 32 bits in IntPending) +
2218 + * expansion slots for shared interrupts*/
2219 + VLYNQ_INTR_CNTRL_ICB pIntrCB[VLYNQ_NUM_INT_BITS + VLYNQ_IVR_CHAIN_SLOTS];
2220 + VLYNQ_INTR_CNTRL_ICB *freelist;
2221 +
2222 + /* table holding mapping between intVector and the bit position the interrupt
2223 + * is mapped to(mapVector)*/
2224 + char vector_map[32];
2225 +
2226 + /* user callback for vlynq events, NULL if unused */
2227 + VLYNQ_REPORT_CB report_cb;
2228 +
2229 + /* user callback for resetting/realeasing remote device */
2230 + VLYNQ_RESET_REMOTE reset_cb;
2231 +
2232 + /*** Handles provided for direct access to register set if need be
2233 + * Must be intialized to point to appropriate address during
2234 + * vlynq_init */
2235 + volatile VLYNQ_REG_SET * local;
2236 + volatile VLYNQ_REG_SET * remote;
2237 +
2238 + unsigned int intCount; /* number of interrupts generated so far */
2239 + unsigned int isrCount; /* number of ISR invocations so far */
2240 +}VLYNQ_DEV;
2241 +
2242 +
2243 +typedef struct VLYNQ_ISR_ARGS_t
2244 +{
2245 + int irq;
2246 + void * arg;
2247 + void * regset;
2248 +}VLYNQ_ISR_ARGS;
2249 +
2250 +
2251 +/****************************************
2252 + * Function Prototypes *
2253 + * API exported by generic vlynq driver *
2254 + ****************************************/
2255 +/* Initialization function */
2256 +int vlynq_init( VLYNQ_DEV *pdev, VLYNQ_INIT_OPTIONS options);
2257 +
2258 +/* Check vlynq link */
2259 +unsigned int vlynq_link_check( VLYNQ_DEV * pdev);
2260 +
2261 +/* Set interrupt vector in local or remote device */
2262 +int vlynq_interrupt_vector_set( VLYNQ_DEV *pdev,
2263 + unsigned int int_vector,
2264 + unsigned int map_vector,
2265 + VLYNQ_DEV_TYPE dev,
2266 + VLYNQ_INTR_POLARITY pol,
2267 + VLYNQ_INTR_TYPE type);
2268 +
2269 +
2270 +int vlynq_interrupt_vector_cntl( VLYNQ_DEV *pdev,
2271 + unsigned int int_vector,
2272 + VLYNQ_DEV_TYPE dev,
2273 + unsigned int enable);
2274 +
2275 +unsigned int vlynq_interrupt_get_count( VLYNQ_DEV *pdev,
2276 + unsigned int map_vector);
2277 +
2278 +int vlynq_install_isr( VLYNQ_DEV *pdev,
2279 + unsigned int map_vector,
2280 + VLYNQ_INTR_CNTRL_ISR isr,
2281 + void *arg1, void *arg2, void *arg3);
2282 +
2283 +int vlynq_uninstall_isr( VLYNQ_DEV *pdev,
2284 + unsigned int map_vector,
2285 + void *arg1, void *arg2, void *arg3);
2286 +
2287 +
2288 +void vlynq_root_isr(void *arg);
2289 +
2290 +void vlynq_delay(unsigned int clktime);
2291 +
2292 +/* The following functions, provide better granularity in setting
2293 + * interrupt parameters. (for better support of linux INT Controller)
2294 + * Note: The interrupt source is identified by "map_vector"- the bit
2295 + * position in interrupt status register*/
2296 +
2297 +int vlynq_interrupt_vector_map(VLYNQ_DEV * pdev,
2298 + VLYNQ_DEV_TYPE dev,
2299 + unsigned int int_vector,
2300 + unsigned int map_vector);
2301 +
2302 +int vlynq_interrupt_set_polarity(VLYNQ_DEV * pdev,
2303 + VLYNQ_DEV_TYPE dev,
2304 + unsigned int map_vector,
2305 + VLYNQ_INTR_POLARITY pol);
2306 +
2307 +int vlynq_interrupt_get_polarity( VLYNQ_DEV *pdev ,
2308 + VLYNQ_DEV_TYPE dev_type,
2309 + unsigned int map_vector);
2310 +
2311 +int vlynq_interrupt_set_type(VLYNQ_DEV * pdev,
2312 + VLYNQ_DEV_TYPE dev,
2313 + unsigned int map_vector,
2314 + VLYNQ_INTR_TYPE type);
2315 +
2316 +int vlynq_interrupt_get_type( VLYNQ_DEV *pdev,
2317 + VLYNQ_DEV_TYPE dev_type,
2318 + unsigned int map_vector);
2319 +
2320 +int vlynq_interrupt_enable(VLYNQ_DEV* pdev,
2321 + VLYNQ_DEV_TYPE dev,
2322 + unsigned int map_vector);
2323 +
2324 +int vlynq_interrupt_disable(VLYNQ_DEV * pdev,
2325 + VLYNQ_DEV_TYPE dev,
2326 + unsigned int map_vector);
2327 +
2328 +
2329 +
2330 +
2331 +
2332 +#endif /* _VLYNQ_HAL_H_ */