~ubuntu-branches/ubuntu/karmic/linux-mvl-dove/karmic-proposed

« back to all changes in this revision

Viewing changes to arch/arm/plat-orion/mv_hal_drivers/mv_drivers_lsp/mv_phone/mp.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bader
  • Date: 2010-03-10 22:24:12 UTC
  • mto: (15.1.2 karmic-security)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20100310222412-k86m3r53jw0je7x1
Tags: upstream-2.6.31
Import upstream version 2.6.31

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*******************************************************************************
2
 
Copyright (C) Marvell International Ltd. and its affiliates
3
 
 
4
 
This software file (the "File") is owned and distributed by Marvell 
5
 
International Ltd. and/or its affiliates ("Marvell") under the following
6
 
alternative licensing terms.  Once you have made an election to distribute the
7
 
File under one of the following license alternatives, please (i) delete this
8
 
introductory statement regarding license alternatives, (ii) delete the two
9
 
license alternatives that you have not elected to use and (iii) preserve the
10
 
Marvell copyright notice above.
11
 
 
12
 
********************************************************************************
13
 
Marvell Commercial License Option
14
 
 
15
 
If you received this File from Marvell and you have entered into a commercial
16
 
license agreement (a "Commercial License") with Marvell, the File is licensed
17
 
to you under the terms of the applicable Commercial License.
18
 
 
19
 
********************************************************************************
20
 
Marvell GPL License Option
21
 
 
22
 
If you received this File from Marvell, you may opt to use, redistribute and/or 
23
 
modify this File in accordance with the terms and conditions of the General 
24
 
Public License Version 2, June 1991 (the "GPL License"), a copy of which is 
25
 
available along with the File in the license.txt file or by writing to the Free 
26
 
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or 
27
 
on the worldwide web at http://www.gnu.org/licenses/gpl.txt. 
28
 
 
29
 
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED 
30
 
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY 
31
 
DISCLAIMED.  The GPL License provides additional details about this warranty 
32
 
disclaimer.
33
 
********************************************************************************
34
 
Marvell BSD License Option
35
 
 
36
 
If you received this File from Marvell, you may opt to use, redistribute and/or 
37
 
modify this File under the following licensing terms. 
38
 
Redistribution and use in source and binary forms, with or without modification, 
39
 
are permitted provided that the following conditions are met:
40
 
 
41
 
    *   Redistributions of source code must retain the above copyright notice,
42
 
            this list of conditions and the following disclaimer. 
43
 
 
44
 
    *   Redistributions in binary form must reproduce the above copyright
45
 
        notice, this list of conditions and the following disclaimer in the
46
 
        documentation and/or other materials provided with the distribution. 
47
 
 
48
 
    *   Neither the name of Marvell nor the names of its contributors may be 
49
 
        used to endorse or promote products derived from this software without 
50
 
        specific prior written permission. 
51
 
    
52
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
53
 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
54
 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
55
 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
56
 
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
57
 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
58
 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
59
 
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
60
 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
61
 
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
 
 
63
 
******************************************************************************/
64
 
 
65
 
#include <linux/kernel.h>
66
 
#include <linux/module.h>
67
 
#include <linux/init.h>
68
 
#include <linux/sched.h>
69
 
#include <linux/telephony.h>
70
 
#include <linux/phonedev.h>
71
 
#include <linux/interrupt.h>
72
 
#include <linux/delay.h>
73
 
#include <linux/poll.h>
74
 
#include "gpp/mvGpp.h"
75
 
#include "mp.h"
76
 
 
77
 
extern MV_U8 currRxSampleGet(MV_U8 ch);
78
 
extern MV_U8 currTxSampleGet(MV_U8 ch);
79
 
extern u32 mvVoiceIfType;
80
 
 
81
 
 
82
 
#ifdef CONFIG_MV_GTW_QOS
83
 
extern int mv_gtw_qos_tos_enable(void);
84
 
extern int mv_gtw_qos_tos_disable(void);
85
 
#endif
86
 
 
87
 
 
88
 
/***********************
89
 
* PHONE DRIVER'S STUFF *
90
 
***********************/
91
 
typedef struct {
92
 
        struct phone_device p;
93
 
        unsigned int ch_info;
94
 
        unsigned int slic_dev;
95
 
        unsigned int daa_dev;
96
 
        unsigned char ch;
97
 
        unsigned int irq;
98
 
        unsigned char exception;
99
 
        int readers, writers;
100
 
        wait_queue_head_t poll_q;
101
 
        wait_queue_head_t read_q;
102
 
        wait_queue_head_t write_q;
103
 
        MV_VOICE_IF_TYPE chType;
104
 
        int cs;  /* for daisy chain */
105
 
        unsigned char rxActive, txActive, started;
106
 
} MV_PHONE;
107
 
 
108
 
static MV_PHONE mv_phone[MV_TDM_MAX_CHANNELS];
109
 
static char *cmdline = "dev0:fxs,dev1:fxs";
110
 
static int work_mode = DAISY_CHAIN_MODE;
111
 
static int interrupt_mode = INTERRUPT_TO_TDM;
112
 
static struct class *phone_class;
113
 
#define get_mp(ch) (&mv_phone[ch])
114
 
 
115
 
 
116
 
 
117
 
/* Forward declarations */
118
 
static int __init mp_init(void);
119
 
static void __exit mp_exit(void);
120
 
static int mp_open(struct phone_device *pdev, struct file *file_p);
121
 
static int mp_close(struct inode *inode, struct file *file_p);
122
 
static ssize_t mp_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos);
123
 
static ssize_t mp_write(struct file *file_p, const char __user *buf, size_t count, loff_t * ppos);
124
 
static unsigned int mp_poll(struct file *file_p, poll_table * wait);
125
 
static int mp_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg);
126
 
static irqreturn_t mp_int_handler(int irq, void *dev_id);
127
 
static void mp_spi_write(unsigned char addr, unsigned char data, MV_PHONE *mp);
128
 
static void mp_spi_read(unsigned char addr, unsigned char *data, MV_PHONE *mp);
129
 
static int slicRingBackTone(unsigned int slicDev);
130
 
static int slicEventGet(unsigned char *offhook, MV_PHONE *mp);
131
 
static int slicBusyTone(unsigned int slicDev);
132
 
static void slicSetLineFeedControl(unsigned char val, unsigned int slicDev);
133
 
static void slicReversDcPolarity(unsigned int slicDev);
134
 
static int slicSpiTest(unsigned int loop, MV_PHONE *mp);
135
 
static int fxdevInterruptBits(unsigned char ch, MV_PHONE *mp);
136
 
static int mp_get_int(unsigned int* work_done);
137
 
static int mp_cmdline_config(char *s);
138
 
static int mp_parse_config(int ifNum);
139
 
static int mp_check_config(void);
140
 
 
141
 
 
142
 
 
143
 
 
144
 
 
145
 
 
146
 
/* Module stuff */
147
 
module_init(mp_init);
148
 
module_exit(mp_exit);
149
 
MODULE_DESCRIPTION("Marvell Telephony Device Driver - www.marvell.com");
150
 
MODULE_AUTHOR("Tzachi Perelstein <tzachi@marvell.com>");
151
 
MODULE_LICENSE("GPL");
152
 
 
153
 
/* Driver's operations */
154
 
static struct file_operations mp_fops =
155
 
{
156
 
        .owner          = THIS_MODULE,
157
 
        .read           = mp_read,
158
 
        .write          = mp_write,
159
 
        .poll           = mp_poll,
160
 
        .ioctl          = mp_ioctl,
161
 
        .release        = mp_close,
162
 
};
163
 
 
164
 
 
165
 
 
166
 
static int mp_parse_config(int ifNum)
167
 
{
168
 
        char type[4];
169
 
        int size = 3, i = 0, offset;
170
 
        offset = BASE_ENV_PARAM_OFF + (DEV_ENV_PARAM_OFF * ifNum); /* start of requested type in cmdline */
171
 
 
172
 
        if(ifNum < MV_TDM_MAX_CHANNELS)
173
 
        {
174
 
                while(i < size)
175
 
                        type[i++] = cmdline[offset++];
176
 
                type[i] = '\0';
177
 
                if(!strcmp(type,"fxs"))
178
 
                        return MV_FXS;
179
 
                else if(!strcmp(type,"fxo"))
180
 
                        return MV_FXO;
181
 
        }
182
 
 
183
 
        return MV_ERROR;                                                                                                                                                                                                                                  }
184
 
 
185
 
static int mp_cmdline_config(char *s)
186
 
{
187
 
        cmdline = s;
188
 
        return 1;
189
 
}
190
 
 
191
 
__setup("mv_phone_config=", mp_cmdline_config);
192
 
 
193
 
 
194
 
static int mp_check_config(void)
195
 
{
196
 
 
197
 
#if defined(CONFIG_ARCH_FEROCEON_ORION)
198
 
        int boardId;
199
 
 
200
 
        boardId = mvBoardIdGet();
201
 
 
202
 
         /* print board detection info */
203
 
           switch(boardId) {
204
 
                case RD_88F5181L_VOIP_GE:
205
 
                        printk("Detected RD_88F5181L_VOIP_GE\n");
206
 
                        work_mode = DAISY_CHAIN_MODE;
207
 
                        interrupt_mode = INTERRUPT_TO_TDM;
208
 
               
209
 
                        break;
210
 
                case RD_88F5181L_VOIP_FE:
211
 
                        printk("Detected RD_88F5181L_VOIP_FE\n");
212
 
                        work_mode = DAISY_CHAIN_MODE;
213
 
                        interrupt_mode = INTERRUPT_TO_TDM;
214
 
                        break;  
215
 
                case DB_88F5181L_DDR2_2XTDM:
216
 
                        printk("Detected DB_88F5181L_DDR2_2XTDM\n");
217
 
                        work_mode = DUAL_CHIP_SELECT_MODE;
218
 
                        interrupt_mode = INTERRUPT_TO_MPP;
219
 
               
220
 
                        break;
221
 
 
222
 
                case RD_88F5181L_VOIP_FXO_GE: 
223
 
                        printk("Detected RD_88F5181L_VOIP_FXO_GE\n");
224
 
                        work_mode = DUAL_CHIP_SELECT_MODE;
225
 
                        interrupt_mode = INTERRUPT_TO_TDM;
226
 
                                
227
 
               /* set life line control mpp */
228
 
                                /*mvGppValueSet(0, MV_GPP11, MV_GPP11);*/
229
 
                                        
230
 
                        break;
231
 
                default:
232
 
                        printk("Error, platform does not support telephony\n");
233
 
                        return MV_ERROR;
234
 
          }
235
 
#elif defined(CONFIG_ARCH_FEROCEON_KW)
236
 
                        work_mode = DUAL_CHIP_SELECT_MODE;
237
 
                        interrupt_mode = INTERRUPT_TO_TDM;
238
 
                        mvBoardTdmLifeLineSet();
239
 
#endif
240
 
                return MV_OK;
241
 
 
242
 
        
243
 
}
244
 
 
245
 
static int __init mp_init(void)
246
 
{
247
 
        MV_PHONE *mp;
248
 
        int i, retval;
249
 
        u32 mpp0;
250
 
int err;
251
 
static int unit=0;
252
 
char dev_name[10];
253
 
 
254
 
        printk("Marvell Telephony Driver:\n");
255
 
 
256
 
        if (MV_FALSE == mvCtrlPwrClckGet(TDM_UNIT_ID, 0)) 
257
 
        {
258
 
                printk("\nWarning Tdm is Powered Off\n");
259
 
                return 0;
260
 
        }
261
 
 
262
 
        /* check system configuration */
263
 
        if(MV_ERROR == mp_check_config())
264
 
                return MV_ERROR; 
265
 
 
266
 
        TRC_INIT(currRxSampleGet, currTxSampleGet, 0, 0);
267
 
        TRC_REC("->%s\n",__FUNCTION__);
268
 
 
269
 
        /* General TDM and SLIC init */
270
 
        TRC_REC("tdm init\n");
271
 
        mvTdmInit(work_mode, interrupt_mode);
272
 
        mvTdmShowProperties();
273
 
        
274
 
    phone_class = class_create(THIS_MODULE, "telephony");
275
 
    if (IS_ERR(phone_class))
276
 
    {
277
 
        err = PTR_ERR(phone_class);
278
 
        return err;
279
 
    }
280
 
        
281
 
        /* per channel init */
282
 
        for(i=0; i<MV_TDM_MAX_CHANNELS; i++)
283
 
        {
284
 
                printk("Initializing channel %d\n",i);
285
 
                TRC_REC("ch%d init\n",i);
286
 
                mp = get_mp(i);
287
 
                mp->chType = mp_parse_config(i);
288
 
                if(mp->chType == MV_ERROR)
289
 
                {
290
 
                        printk("%s: error, unknown device type (check u-boot config)\n",__FUNCTION__);
291
 
                        return MV_ERROR;
292
 
                }
293
 
#ifdef CONFIG_ARCH_FEROCEON_ORION
294
 
                if((mvBoardIdGet() == RD_88F5181L_VOIP_FXO_GE) && (i != 0)) {
295
 
                        mpp0 = MV_REG_READ(MPP_CONTROL_REG0);
296
 
                                        
297
 
                        
298
 
                        if(mp->chType == MV_FXO)
299
 
                        { 
300
 
        
301
 
                                mvGppValueSet(0, MV_GPP3, MV_GPP3); /* reset daa */     
302
 
                                mvGppValueSet(0, MV_GPP3, 0);
303
 
 
304
 
                        }
305
 
                        else {
306
 
                                mvGppValueSet(0, MV_GPP3, 0); /* reset slic */
307
 
                                mvGppValueSet(0, MV_GPP3, MV_GPP3);
308
 
                        }
309
 
                }
310
 
#endif
311
 
                printk("Unit Type: %s\n",mp->chType == MV_FXO ? "FXO":"FXS");                
312
 
                mp->p.board = mp->ch = i;
313
 
                mp->p.f_op = &mp_fops;
314
 
                mp->p.open = mp_open;
315
 
        
316
 
 
317
 
                if(interrupt_mode == INTERRUPT_TO_MPP)
318
 
                {
319
 
                        mp->irq = mvBoardSlicGpioPinGet(i) + IRQ_GPP_START;     
320
 
                }
321
 
                else
322
 
                        mp->irq = MP_IRQ; 
323
 
 
324
 
                init_waitqueue_head(&mp->poll_q);
325
 
                init_waitqueue_head(&mp->read_q);
326
 
                init_waitqueue_head(&mp->write_q);
327
 
                   
328
 
                if(mvTdmChInit(&mp->p, i, &(mp->ch_info), mp->chType) == MV_OK)
329
 
                {
330
 
                 mp->rxActive = 0;
331
 
                 mp->txActive = 0;
332
 
                 mp->started =  0;
333
 
                }
334
 
                else
335
 
                {
336
 
                 printk("mvTdmChInit() failed !\n");
337
 
                 return -EIO;
338
 
                }
339
 
                        
340
 
                if(mp->chType == MV_FXS)
341
 
                        retval = initSlic(&(mp->slic_dev), mp->ch, work_mode, interrupt_mode);
342
 
                else
343
 
                        retval = initDaa(&(mp->daa_dev), mp->ch, work_mode, interrupt_mode);
344
 
                if(!retval)
345
 
                {
346
 
                        phone_register_device(&mp->p, PHONE_UNIT_ANY);
347
 
                        printk("phone%d registered\n",i);
348
 
                }
349
 
                else
350
 
                        printk("%s: Unable to initialize %s-%d\n",__FUNCTION__, mp->chType == 0 ? "FXO":"FXS", i);
351
 
 
352
 
        sprintf(dev_name, "phone%d", unit);
353
 
        device_create(phone_class, NULL, MKDEV(PHONE_MAJOR, unit), dev_name);
354
 
        unit++;
355
 
        }
356
 
 
357
 
        if (request_irq(MP_IRQ, mp_int_handler, IRQF_SHARED | IRQF_DISABLED, "mv-phone", &mv_phone[0])) {
358
 
                printk("Failed to connect IRQ %d\n", MP_IRQ);
359
 
                mp->irq = 0;
360
 
                return -EIO;
361
 
        }               
362
 
 
363
 
        if(interrupt_mode == INTERRUPT_TO_MPP)
364
 
        {
365
 
                mp = get_mp(0);
366
 
                if (request_irq(mp->irq, mp_int_handler,  IRQF_DISABLED, "mv-voice0", (&mv_phone[0])+1)) {
367
 
                        printk("Failed to connect IRQ %d\n", mp->irq);
368
 
                        mp->irq = 0;
369
 
                        return -EIO;
370
 
                }
371
 
                mp = get_mp(1);
372
 
                if (request_irq(mp->irq, mp_int_handler,  IRQF_DISABLED, "mv-voice1", (&mv_phone[0])+2)) {
373
 
                        printk("Failed to connect IRQ %d\n", mp->irq);
374
 
                        mp->irq = 0;
375
 
                        return -EIO;
376
 
                }       
377
 
 
378
 
        }               
379
 
 
380
 
        TRC_REC("<-%s\n",__FUNCTION__);
381
 
        return 0;
382
 
}
383
 
 
384
 
static void __exit mp_exit(void)
385
 
{
386
 
        MV_PHONE *mp;
387
 
        int i;
388
 
 
389
 
        TRC_REC("->%s\n",__FUNCTION__);
390
 
 
391
 
        free_irq(MP_IRQ, &mv_phone[0]);
392
 
        TRC_REC("free irq %d\n",MP_IRQ);
393
 
 
394
 
        for(i=0; i<MV_TDM_MAX_CHANNELS; i++) {
395
 
                TRC_REC("ch%d remove\n",i);
396
 
                mp = get_mp(i);
397
 
                mvTdmChRemove(mp->ch_info);
398
 
 
399
 
        if(interrupt_mode == INTERRUPT_TO_MPP) {
400
 
                free_irq(mp->irq, (&mv_phone[0]) + i + 1);
401
 
                TRC_REC("free irq %d\n",mp->irq);
402
 
 
403
 
        }
404
 
                if(mp->chType == MV_FXS)
405
 
                        slicFreeChannel(mp->slic_dev);
406
 
                else
407
 
                        daaFreeChannel(mp->daa_dev);
408
 
                mp->irq = 0;
409
 
                mp->p.f_op = NULL;
410
 
                mp->p.open = NULL;
411
 
                mp->p.board = 0;
412
 
                phone_unregister_device(&mp->p);
413
 
                printk("phone%d removed\n",i);
414
 
        }
415
 
 
416
 
        TRC_REC("<-%s\n",__FUNCTION__);
417
 
        TRC_OUTPUT();
418
 
        TRC_RELEASE();
419
 
}
420
 
 
421
 
static int mp_open(struct phone_device *p, struct file *file_p)
422
 
{
423
 
        
424
 
        MV_PHONE *mp = get_mp(p->board);
425
 
        int i, first = 1;
426
 
        file_p->private_data = mp;
427
 
                
428
 
        printk("Opening phone channel %d - \n",mp->ch);
429
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
430
 
 
431
 
        if (file_p->f_mode & FMODE_READ) {
432
 
                if(!mp->readers) {
433
 
                        mp->readers++;
434
 
                }
435
 
                else {
436
 
                        printk("device is busy (read)\n");
437
 
                        return -EBUSY;
438
 
                }
439
 
        }
440
 
 
441
 
        if (file_p->f_mode & FMODE_WRITE) {
442
 
                if(!mp->writers) {
443
 
                        mp->writers++;
444
 
                } 
445
 
                else {
446
 
                        if (file_p->f_mode & FMODE_READ) {
447
 
                                mp->readers--;
448
 
                        }
449
 
                        printk("device is busy (write)\n");
450
 
                        return -EBUSY;
451
 
                }
452
 
        }
453
 
        
454
 
        /* enable FXO/FXS interrupts */ 
455
 
        if(mp->chType == MV_FXS)
456
 
                enableSlicInterrupts(mp->slic_dev);
457
 
        else
458
 
                enableDaaInterrupts(mp->daa_dev);
459
 
 
460
 
        for (i = 0; i < MV_TDM_MAX_CHANNELS; i++)
461
 
        {
462
 
                if (mp->started)
463
 
                {
464
 
                        first = 0;
465
 
                        break;
466
 
                }
467
 
        }
468
 
        if (first)
469
 
        {
470
 
                MV_REG_WRITE(INT_STATUS_REG,0);         
471
 
                MV_REG_WRITE(INT_STATUS_MASK_REG,TDM_INT_SLIC); 
472
 
        }
473
 
 
474
 
        mp->started = 1;
475
 
 
476
 
        
477
 
        if(mvTdmChStart(mp->ch_info) == MV_OK)
478
 
          mp->rxActive = mp->txActive = 0;
479
 
        else
480
 
          printk("mvTdmChStart() failed !\n");
481
 
 
482
 
        TRC_REC("<-%s\n",__FUNCTION__);
483
 
        return 0;
484
 
}
485
 
 
486
 
static int mp_close(struct inode *inode, struct file *file_p)
487
 
{
488
 
        MV_PHONE *mp = file_p->private_data;
489
 
        int i, stillRunning = 0;
490
 
        
491
 
 
492
 
        printk("Closing Marvell phone%d device\n",mp->ch);
493
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
494
 
 
495
 
        /* Disable Rx/Tx */
496
 
        if(mp->rxActive)
497
 
                mp->rxActive = 0;
498
 
        
499
 
        if(mp->txActive)
500
 
                mp->txActive = 0;
501
 
        
502
 
        /* Clear cause and disable all interrupts */
503
 
        mp->started = 0;
504
 
        TRC_REC("disable all ch%d interrupts\n",mp->ch);
505
 
        for (i = 0; i < MV_TDM_MAX_CHANNELS; i++)
506
 
        {
507
 
                if (mp->started)        
508
 
                {
509
 
                        stillRunning = 1;
510
 
                        break;
511
 
                }
512
 
        }       
513
 
        if (!stillRunning)
514
 
        {                       
515
 
                MV_REG_WRITE(INT_STATUS_MASK_REG,0);
516
 
                MV_REG_WRITE(INT_STATUS_REG,0);
517
 
        }
518
 
        
519
 
 
520
 
        if(mvTdmChStop(mp->ch_info) == MV_OK)
521
 
          mp->rxActive = mp->txActive = 0;
522
 
        else
523
 
          printk("mvTdmChStop() failed !\n");
524
 
 
525
 
 
526
 
        /* disable FXO/FXS interrupts */        
527
 
        if(mp->chType == MV_FXS)
528
 
                disableSlicInterrupts(mp->slic_dev);
529
 
        else
530
 
                disableDaaInterrupts(mp->daa_dev);
531
 
 
532
 
 
533
 
        wake_up_interruptible(&mp->poll_q);
534
 
        wake_up_interruptible(&mp->read_q);
535
 
        wake_up_interruptible(&mp->write_q);
536
 
 
537
 
        if (file_p->f_mode & FMODE_READ)
538
 
                mp->readers--;
539
 
        if (file_p->f_mode & FMODE_WRITE)
540
 
                mp->writers--;
541
 
 
542
 
        file_p->private_data = NULL;
543
 
 
544
 
        TRC_REC("<-%s\n",__FUNCTION__);
545
 
        TRC_OUTPUT();
546
 
        return 0;
547
 
}
548
 
 
549
 
static ssize_t mp_read(struct file * file_p, char __user *buf, size_t length, loff_t * ppos)
550
 
{
551
 
        
552
 
        MV_STATUS status;
553
 
        unsigned long count = 0;
554
 
        unsigned int err = 0;
555
 
        MV_PHONE *mp = file_p->private_data;
556
 
 
557
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
558
 
 
559
 
 
560
 
        count = min(length, (size_t)MV_TDM_BUFF_SIZE);
561
 
        do
562
 
        {       
563
 
                if(mp->rxActive)
564
 
                   status = mvTdmChRx(mp->ch_info, buf, count);
565
 
                else
566
 
                {
567
 
                   TRC_REC("rx is not active!\n");
568
 
                   status = MV_NOT_READY;
569
 
                }
570
 
 
571
 
                if (status == MV_NOT_READY) 
572
 
                { 
573
 
                        if (file_p->f_flags & O_NONBLOCK) 
574
 
                        {               
575
 
                                TRC_REC("read not ready, try again\n");
576
 
                                err = -EAGAIN;
577
 
                                break;
578
 
                        }
579
 
                        else
580
 
                        {
581
 
                                
582
 
                                if(!mp->rxActive)
583
 
                                {
584
 
                                        mp->rxActive = 1;                       
585
 
                                        interruptible_sleep_on(&mp->read_q);
586
 
                                        if (signal_pending(current)) 
587
 
                                        {
588
 
                                                return -EINTR;
589
 
                                        }
590
 
                                 } 
591
 
                                 else
592
 
                                 {                              
593
 
                                        err = -EFAULT;
594
 
                                        break;
595
 
                                 }
596
 
                                
597
 
                        }
598
 
                }       
599
 
                else if(status == MV_FAIL) {
600
 
                        TRC_REC("copy to user failed\n");
601
 
                        printk("%s: copy to user failed\n", __FUNCTION__);
602
 
                        err = -EFAULT;                  
603
 
                }
604
 
                else {
605
 
                        TRC_REC("copy to user %dB ok\n",count);
606
 
                        err = 0;                        
607
 
                }
608
 
        } while (status == MV_NOT_READY);
609
 
 
610
 
        TRC_REC("<-%s\n",__FUNCTION__);
611
 
        return (err)?err:count;
612
 
}
613
 
 
614
 
static ssize_t mp_write(struct file *file_p, const char __user *buf, size_t length, loff_t * ppos)
615
 
{
616
 
        
617
 
        MV_STATUS status;
618
 
        unsigned long count = 0;
619
 
        int err = 0;
620
 
        MV_PHONE *mp = file_p->private_data;
621
 
 
622
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
623
 
        
624
 
 
625
 
        count = min(length, (size_t)MV_TDM_BUFF_SIZE);
626
 
        do
627
 
        {
628
 
                
629
 
                if(mp->txActive)
630
 
                        status = mvTdmChTx(mp->ch_info, (MV_U8 *)buf, count);
631
 
                else
632
 
                {
633
 
                        TRC_REC("tx is not active!\n");
634
 
                        status = MV_NOT_READY;
635
 
                }
636
 
 
637
 
                if (status == MV_NOT_READY) 
638
 
                { 
639
 
                        if (file_p->f_flags & O_NONBLOCK) 
640
 
                        {                               
641
 
                                TRC_REC("write not ready, try again\n");
642
 
                                err = -EAGAIN;
643
 
                                break;
644
 
                        }
645
 
                        else
646
 
                        {
647
 
                                if(!mp->txActive)
648
 
                                {
649
 
                                        mp->txActive = 1;                       
650
 
                                        interruptible_sleep_on(&mp->write_q);
651
 
                                        if (signal_pending(current)) 
652
 
                                        {
653
 
                                                return -EINTR;
654
 
                                        }
655
 
                                }
656
 
                                else
657
 
                                {                               
658
 
                                        err = -EFAULT;
659
 
                                        break;
660
 
                                }
661
 
                        }
662
 
                }               
663
 
                else if(status == MV_FAIL) {
664
 
                        TRC_REC("copy from user failed\n");
665
 
                        printk("%s: copy from user failed\n",__FUNCTION__);
666
 
                        err = -EFAULT;          
667
 
                }
668
 
                else {
669
 
                        TRC_REC("copy from user %dB ok\n",count);
670
 
                        err = 0;
671
 
                }
672
 
        } while (status == MV_NOT_READY);
673
 
        TRC_REC("<-%s\n",__FUNCTION__);
674
 
        return (err)?err:count;
675
 
}
676
 
 
677
 
static unsigned int mp_poll(struct file *file_p, poll_table * wait)
678
 
{
679
 
        
680
 
        unsigned int mask = 0;
681
 
        MV_PHONE *mp = file_p->private_data;
682
 
 
683
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
684
 
 
685
 
        poll_wait(file_p, &(mp->poll_q), wait);
686
 
        
687
 
        if(mp->rxActive)
688
 
        {
689
 
         if(mvTdmChRxReady(mp->ch_info)) {
690
 
                mask |= POLLIN | POLLRDNORM;    /* readable */
691
 
                TRC_REC("poll can read\n");
692
 
         }
693
 
        }
694
 
        if(mp->txActive)
695
 
        {
696
 
          if(mvTdmChTxReady(mp->ch_info)) {
697
 
                mask |= POLLOUT | POLLWRNORM;   /* writable */
698
 
                TRC_REC("poll can write\n");
699
 
          }
700
 
        }
701
 
          if(mp->exception == EXCEPTION_ON) {
702
 
                mask |= POLLPRI;                /* events */
703
 
                TRC_REC("poll can get event\n");
704
 
          }
705
 
 
706
 
 
707
 
 
708
 
        TRC_REC("<-%s\n",__FUNCTION__);
709
 
        return mask;
710
 
}
711
 
 
712
 
static int mp_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg)
713
 
{
714
 
        
715
 
        int retval = 0;
716
 
        MV_PHONE *mp = get_mp(iminor(inode) & 0xf);
717
 
 
718
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
719
 
 
720
 
        /* check ioctls only root can use */
721
 
        if (!capable(CAP_SYS_ADMIN)) {
722
 
                return -EPERM;
723
 
        }
724
 
 
725
 
        disable_irq(MP_IRQ);
726
 
 
727
 
        if(interrupt_mode == INTERRUPT_TO_MPP) 
728
 
                disable_irq(mp->irq);
729
 
 
730
 
 
731
 
 
732
 
#ifdef CONFIG_MV_GTW_QOS
733
 
        if(cmd == PHONE_REC_START || cmd == PHONE_PLAY_START) {
734
 
                mv_gtw_qos_tos_enable();
735
 
        }
736
 
        if(cmd == PHONE_REC_STOP || cmd == PHONE_PLAY_STOP) {
737
 
                mv_gtw_qos_tos_disable();
738
 
        }
739
 
#endif
740
 
 
741
 
        switch (cmd) {
742
 
                case PHONE_REC_START:
743
 
                        TRC_REC("PHONE_REC_START\n");
744
 
                        if(!mp->rxActive)
745
 
                        {
746
 
                           if(mvTdmChRxEnable(mp->ch_info) ==MV_OK)
747
 
                                mp->rxActive = 1;
748
 
                           else TRC_REC("failed\n");
749
 
                        }
750
 
                        TRC_REC("rec already active\n");
751
 
                        break;
752
 
                case PHONE_REC_STOP:
753
 
                        TRC_REC("PHONE_REC_STOP\n");                    
754
 
                        if(mp->rxActive)
755
 
                                mp->rxActive = 0;
756
 
                        wake_up_interruptible(&mp->read_q);
757
 
                        break;
758
 
                case PHONE_PLAY_START:
759
 
                        TRC_REC("PHONE_PLAY_START\n");
760
 
                        if(!mp->txActive)
761
 
                        {
762
 
                                if(mvTdmChTxEnable(mp->ch_info) == MV_OK)
763
 
                                        mp->txActive = 1;
764
 
                                else TRC_REC("failed\n");
765
 
                        }
766
 
                        TRC_REC("play already active\n");
767
 
                        break;
768
 
                case PHONE_PLAY_STOP:
769
 
                        TRC_REC("PHONE_PLAY_STOP\n");
770
 
                        if(mp->txActive)
771
 
                                mp->txActive = 0;
772
 
                        wake_up_interruptible(&mp->write_q);
773
 
                        break;
774
 
                case PHONE_EXCEPTION:
775
 
                {
776
 
                        union telephony_exception ex;
777
 
                        TRC_REC("PHONE_EXCEPTION\n");
778
 
                        ex.bytes = 0;
779
 
                        if(mp->chType == MV_FXS)
780
 
                        {
781
 
                                MV_U8 offhook;
782
 
                                slicEventGet(&offhook, mp);
783
 
                                if(offhook) {
784
 
                                        TRC_REC("off hook\n");                          
785
 
                                        ex.bits.hookstate = 1;
786
 
                                }
787
 
                                else 
788
 
                                        TRC_REC("on hook\n");                           
789
 
                        }
790
 
                        else
791
 
                        {
792
 
                                MV_U8 eventType;
793
 
                                daaEventTypeGet(&eventType, mp->daa_dev);
794
 
                                mp->exception = EXCEPTION_OFF;
795
 
                                if(eventType & 0x80)
796
 
                                {
797
 
                                        TRC_REC("Ring Detected\n");                             
798
 
                                        ex.bits.pstn_ring = 1;
799
 
                                }
800
 
                                if(eventType & 0x1)
801
 
                                {
802
 
                                        TRC_REC("Reverse Polarity Detected\n");                         
803
 
                                        ex.bits.reverse_polarity = 1;
804
 
 
805
 
                                }
806
 
                                if(eventType & 0x8)
807
 
                                {
808
 
                                        TRC_REC("Drop Out Detected\n");                         
809
 
                                        ex.bits.drop_out = 1;
810
 
 
811
 
                                }
812
 
        
813
 
                        }
814
 
                        retval = ex.bytes;
815
 
                }
816
 
                        break;
817
 
                case PHONE_PSTN_SET_STATE:
818
 
                        TRC_REC("PHONE_PSTN_SET_STATE\n");
819
 
                        setPstnState(arg, mp->daa_dev);
820
 
                        break;
821
 
                case PHONE_SET_CID_STATE:
822
 
                        TRC_REC("PHONE_SET_CID_STATE\n");
823
 
                        setDaaCidState(arg, mp->daa_dev);
824
 
                        break;
825
 
                case PHONE_SET_REVERSE_POLARITY:
826
 
                        TRC_REC("PHONE_SET_REVERSE_POLARITY\n");
827
 
                        enableDaaReveresePolarity(arg, mp->daa_dev);
828
 
                        break;
829
 
                case PHONE_SET_DIGITAL_HYBRID:
830
 
                        TRC_REC("PHONE_SET_DIGITAL_HYBRID\n");
831
 
                        setDaaDigitalHybrid((unsigned int)arg, mp->daa_dev);
832
 
                        break;
833
 
                case PHONE_GET_LINE_VOLTAGE:
834
 
                        TRC_REC("PHONE_GET_LINE_VOLTAGE\n");
835
 
                        retval = daaGetLineVoltage(mp->daa_dev);
836
 
                        break;
837
 
                case PHONE_DIALTONE:
838
 
                        TRC_REC("PHONE_DIALTONE\n");
839
 
                        dialTone(mp->slic_dev);
840
 
                        break;
841
 
                case PHONE_BUSY:
842
 
                        TRC_REC("PHONE_BUSY\n");
843
 
                        slicBusyTone(mp->slic_dev);
844
 
                        break;
845
 
                case PHONE_CPT_STOP:
846
 
                        TRC_REC("PHONE_CPT_STOP\n");
847
 
                        stopTone(mp->slic_dev);
848
 
                        break;
849
 
                case PHONE_RING_START:
850
 
                        TRC_REC("PHONE_RING_START\n");
851
 
                        activateRinging(mp->slic_dev);
852
 
                        break;
853
 
                case PHONE_RING_STOP:
854
 
                        TRC_REC("PHONE_RING_STOP\n");
855
 
                        stopRinging(mp->slic_dev);
856
 
                        break;
857
 
                case PHONE_RING_CADENCE:
858
 
                        TRC_REC("PHONE_RING_CADENCE\n");
859
 
                        slicRingCadence(arg, mp->slic_dev);
860
 
                        break;                  
861
 
                case PHONE_RINGBACK:
862
 
                        TRC_REC("PHONE_RINGBACK\n");
863
 
                        slicRingBackTone(mp->slic_dev);
864
 
                        break;
865
 
                case PHONE_PSTN_REVERSE_POLARITY:       /* Timor */
866
 
                        TRC_REC("PHONE_PSTN_REVERSE_POLARITY\n");
867
 
                        slicReversDcPolarity(mp->slic_dev);
868
 
                        break;
869
 
                case PHONE_PSTN_SEND_NTT_CRA:           /* Timor */
870
 
                        TRC_REC("PHONE_PSTN_SEND_NTT_CRA\n");
871
 
                        slicSendNTTCRATone(mp->slic_dev);
872
 
                        break;
873
 
 
874
 
                case PHONE_SET_LINE_FEED_CONTROL:               /* Timor */
875
 
                        TRC_REC("PHONE_SET_LINE_FEED_CONTROL\n");
876
 
                        slicSetLineFeedControl((unsigned char)arg, mp->slic_dev);
877
 
                        break;
878
 
 
879
 
                case PHONE_MV_READ_SLIC_REG:
880
 
#ifdef MV_IOCTL
881
 
        
882
 
                        mp_spi_read(arg, (MV_U8*)&retval, mp);
883
 
#else
884
 
                        printk("Driver is not configured to support this IOCTL\n");
885
 
                        retval = -1;
886
 
#endif
887
 
                        break;
888
 
                case PHONE_MV_WRITE_SLIC_REG:
889
 
#ifdef MV_IOCTL
890
 
                        
891
 
                        mp_spi_write((arg>>16)&0xff,arg&0xff, mp);
892
 
#else
893
 
                        printk("Driver is not configured to support this IOCTL\n");
894
 
                        retval = -1;
895
 
#endif
896
 
                        break;
897
 
                case PHONE_MV_READ_REG:
898
 
#ifdef MV_IOCTL
899
 
                        retval = *((unsigned int*)(0xf1000000|arg));
900
 
#else
901
 
                        printk("Driver is not configured to support this IOCTL\n");
902
 
                        retval = -1;
903
 
#endif
904
 
                        break;
905
 
                case PHONE_MV_WRITE_REG:
906
 
#ifdef MV_IOCTL
907
 
                        printk("not implemented yet\n");
908
 
#else
909
 
                        printk("Driver is not configured to support this IOCTL\n");
910
 
                        retval = -1;
911
 
#endif
912
 
                        break;
913
 
                case PHONE_MV_SPI_TEST:
914
 
#ifdef MV_IOCTL
915
 
                        slicSpiTest(10000, mp);
916
 
#else
917
 
                        printk("Driver is not configured to support this IOCTL\n");
918
 
                        retval = -1;
919
 
#endif
920
 
                        break;
921
 
                default:
922
 
                        printk("mv_phone %s: unsupported IOCTL\n",__FUNCTION__);
923
 
        }
924
 
 
925
 
        TRC_REC("<-%s\n",__FUNCTION__);
926
 
        enable_irq(MP_IRQ);
927
 
 
928
 
        if(interrupt_mode == INTERRUPT_TO_MPP)
929
 
                enable_irq(mp->irq);
930
 
 
931
 
 
932
 
        return retval;
933
 
}
934
 
 
935
 
 
936
 
/* 
937
 
** Two types of interrupts exists: 
938
 
** (1) FXS/FXO async event (e.g. on/off-hook). 
939
 
** (2) TDM sync 10ms event (data is ready for read+write)
940
 
*/
941
 
static irqreturn_t mp_int_handler(int irq, void *dev_id)
942
 
{       
943
 
        MV_U32 work_done = 0;
944
 
        MV_U8 i;
945
 
        MV_U8 wake_up_poll_q;
946
 
 
947
 
        TRC_REC("->->->%s\n",__FUNCTION__);
948
 
        if (!mp_get_int(&work_done)) 
949
 
        {               
950
 
                for (i = 0; i < MV_TDM_MAX_CHANNELS; i++)
951
 
                {                                                               
952
 
                        wake_up_poll_q = 0;
953
 
                        if (work_done & (MV_TDM_SLIC_INTR << MV_CHANNEL_INTR(i)))
954
 
                        {
955
 
                                TRC_REC("wake up for ex\n");
956
 
                                wake_up_poll_q = 1;
957
 
                        }
958
 
                        if (work_done & (MV_TDM_READ_INTR << MV_CHANNEL_INTR(i)))
959
 
                        {
960
 
                                wake_up_poll_q = 1;
961
 
                                TRC_REC("wake up for rd\n");
962
 
                                wake_up_interruptible(&mv_phone[i].read_q);
963
 
                        }
964
 
                        if (work_done & (MV_TDM_WRITE_INTR << MV_CHANNEL_INTR(i)))
965
 
                        {               
966
 
                                wake_up_poll_q = 1;
967
 
                                TRC_REC("wake up for wr\n");
968
 
                                wake_up_interruptible(&mv_phone[i].write_q);
969
 
                        }
970
 
                        if (wake_up_poll_q) {
971
 
                                TRC_REC("wake up poll\n");
972
 
                                wake_up_interruptible(&mv_phone[i].poll_q);     
973
 
                        }
974
 
                }
975
 
        }
976
 
        TRC_REC("<-%s\n",__FUNCTION__);
977
 
        return IRQ_HANDLED;
978
 
}
979
 
 
980
 
static void mp_spi_write(unsigned char addr, unsigned char data, MV_PHONE *mp)
981
 
{
982
 
        if(mp->chType == MV_FXS)
983
 
                writeDirectReg(mp->slic_dev, addr, data);
984
 
        else
985
 
                writeDaaDirectReg(mp->daa_dev, addr, data);
986
 
 
987
 
 
988
 
}
989
 
 
990
 
static void mp_spi_read(unsigned char addr, unsigned char *data, MV_PHONE *mp)
991
 
{
992
 
        if(mp->chType == MV_FXS)
993
 
                *data = readDirectReg(mp->slic_dev, addr);
994
 
        else    
995
 
                *data = readDaaDirectReg(mp->daa_dev, addr);
996
 
 
997
 
 
998
 
}
999
 
 
1000
 
static int slicEventGet(unsigned char *offhook, MV_PHONE *mp)
1001
 
{
1002
 
        
1003
 
        MV_U8 tmp;
1004
 
 
1005
 
        TRC_REC("->%s ch%d\n",__FUNCTION__,mp->ch);
1006
 
 
1007
 
  
1008
 
        mp_spi_read(68, &tmp, mp);
1009
 
 
1010
 
        /* hook state (0-on, 1-off) */
1011
 
        *offhook = !(tmp & 4);
1012
 
 
1013
 
        if(*offhook)
1014
 
                TRC_REC("off-hook\n");          
1015
 
        else            
1016
 
                TRC_REC("on-hook\n");   
1017
 
        mp->exception = EXCEPTION_OFF;
1018
 
        TRC_REC("<-%s\n",__FUNCTION__);
1019
 
        return 0;
1020
 
}
1021
 
 
1022
 
static int slicBusyTone(unsigned int slicDev)
1023
 
{
1024
 
   
1025
 
#if 1
1026
 
        busyTone(slicDev);
1027
 
#else
1028
 
        busyJapanTone(slicDev);
1029
 
#endif
1030
 
        return 0;
1031
 
}
1032
 
 
1033
 
 
1034
 
static int slicRingBackTone(unsigned int slicDev)
1035
 
{
1036
 
#if 1
1037
 
        ringBackTone(slicDev);
1038
 
#else
1039
 
        ringBackJapanTone(slicDev);
1040
 
#endif
1041
 
        return 0;
1042
 
}
1043
 
 
1044
 
static void slicSetLineFeedControl(unsigned char val, unsigned int slicDev)    /* Timor */
1045
 
{
1046
 
    writeDirectReg(slicDev, LINE_STATE, val);
1047
 
        return ;
1048
 
}
1049
 
 
1050
 
static void slicReversDcPolarity(unsigned int slicDev)         /* Timor */
1051
 
1052
 
    MV_U8 data;
1053
 
    /* read value of On-Hook Line Voltage register */
1054
 
    data = readDirectReg(slicDev, OFF_HOOK_V);
1055
 
    /* toggle the VSGN bit - VTIP–VRING polarity */
1056
 
    writeDirectReg(slicDev, OFF_HOOK_V, data^0x40);
1057
 
    
1058
 
    return;
1059
 
}
1060
 
 
1061
 
static int slicSpiTest(unsigned int loop, MV_PHONE *mp)
1062
 
{
1063
 
        
1064
 
        unsigned char  w,r;
1065
 
        int i,ch;
1066
 
 
1067
 
        for(ch=0; ch<MV_TDM_MAX_CHANNELS; ch++)
1068
 
        {
1069
 
 
1070
 
            /*mvTdmSetCurrentUnit(mp->cs);*/
1071
 
                printk("SPI channel %d Write/Read test %d loops... ",mp->ch,loop);
1072
 
 
1073
 
                for(i=0;i<loop;i++) 
1074
 
                {
1075
 
                        w = (i & 0x7f);
1076
 
                        r = 0;
1077
 
                        mp_spi_write(2, w, mp);
1078
 
                        mp_spi_read(2, &r, mp);
1079
 
                        if(r!=w) 
1080
 
                        {
1081
 
                                printk("SPI: Wrote %x, Read = %x ",w,r);
1082
 
                                break;
1083
 
                        }
1084
 
                }
1085
 
 
1086
 
                if(i != loop)
1087
 
                {
1088
 
                        printk("failed\n");
1089
 
                        return 1;
1090
 
                }
1091
 
 
1092
 
                printk("ok\n");
1093
 
        }
1094
 
        return 0;
1095
 
}
1096
 
 
1097
 
 
1098
 
static int mp_get_int(unsigned int *work_done)
1099
 
{
1100
 
        MV_PHONE *mp;   
1101
 
        unsigned int cause, gppDataIn = 0, isFxInterrupt = 0;
1102
 
        unsigned char ch;
1103
 
        
1104
 
        /* Read and clear cause */
1105
 
        cause = MV_REG_READ(INT_STATUS_REG);
1106
 
        MV_REG_WRITE(INT_STATUS_REG, ~cause);
1107
 
 
1108
 
        if(interrupt_mode == INTERRUPT_TO_MPP) {
1109
 
                gppDataIn = MV_REG_READ(GPP_DATA_IN_REG(0));
1110
 
                TRC_REC("->%s gppcause=0x%x\n",__FUNCTION__, gppDataIn);
1111
 
        }
1112
 
        else
1113
 
                TRC_REC("->%s tdmcause=0x%x mask=0x%x\n",__FUNCTION__, cause, MV_REG_READ(INT_STATUS_MASK_REG));
1114
 
 
1115
 
 
1116
 
 
1117
 
        /* Refer only to unmasked bits */
1118
 
        cause &= (MV_REG_READ(INT_STATUS_MASK_REG));
1119
 
        isFxInterrupt = ((interrupt_mode == INTERRUPT_TO_MPP) ?  (gppDataIn & (BIT8 | BIT9)) : (cause & SLIC_INT_BIT)) ;
1120
 
 
1121
 
        if(isFxInterrupt)       
1122
 
        {
1123
 
                for (ch=0; ch<MV_TDM_MAX_CHANNELS; ch++)
1124
 
                {
1125
 
                        mp = get_mp(ch);
1126
 
                        
1127
 
                        if (fxdevInterruptBits(ch, mp)) { 
1128
 
                                mp->exception = EXCEPTION_ON;                           
1129
 
                                TRC_REC("ch%d voice unit interrupt\n",ch);                              
1130
 
                                *work_done |= MV_TDM_SLIC_INTR << MV_CHANNEL_INTR(ch);                  
1131
 
                        }                       
1132
 
                }               
1133
 
        }
1134
 
 
1135
 
        if(cause & DMA_ABORT_BIT)
1136
 
        {
1137
 
                mvOsPrintf("%s: DMA data abort. Address: 0x%08x, Info: 0x%08x\n",
1138
 
                __FUNCTION__, MV_REG_READ(DMA_ABORT_ADDR_REG), MV_REG_READ(DMA_ABORT_INFO_REG));
1139
 
                *work_done |= MV_TDM_DMA_ABORT_INTR;
1140
 
        }
1141
 
 
1142
 
        for(ch=0; ch<MV_TDM_MAX_CHANNELS; ch++)
1143
 
        {
1144
 
                
1145
 
                mp = get_mp(ch);
1146
 
        
1147
 
                if (cause & TDM_INT_RX(ch))
1148
 
                {
1149
 
                        if (cause & RX_BIT(ch)) 
1150
 
                        {
1151
 
                                /* Give next buff to TDM and set curr buff as full */                           
1152
 
                        
1153
 
                                if (mp->rxActive)
1154
 
                                        mvTdmChRxLow(mp->ch_info);      
1155
 
                                                
1156
 
                        }
1157
 
                        if (cause & RX_OVERFLOW_BIT(ch))
1158
 
                        {
1159
 
                                /*Channel Rx goes to idle*/     
1160
 
                                if (likely(!mp->rxActive))
1161
 
                                {
1162
 
                                        MV_REG_WRITE(INT_STATUS_MASK_REG, MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_RX(mp->ch)))); 
1163
 
                                        TRC_REC("ch %d: Rx stopped.\n",mp->ch);
1164
 
                                }
1165
 
                                else
1166
 
                                {
1167
 
                                        mvOsPrintf("ch %d: Rx overflow.\n",mp->ch);
1168
 
                                }
1169
 
                        }
1170
 
                        *work_done |= MV_TDM_READ_INTR << MV_CHANNEL_INTR(ch);                  
1171
 
                }
1172
 
 
1173
 
                if (cause & TDM_INT_TX(ch))
1174
 
                {
1175
 
                        /* Give next buff to TDM and set curr buff as empty */
1176
 
                        if (cause & TX_BIT(ch))
1177
 
                        {
1178
 
                             if (mp->txActive)                  
1179
 
                                mvTdmChTxLow(mp->ch_info); 
1180
 
                                                                        
1181
 
                        }
1182
 
                        if(cause & TX_UNDERFLOW_BIT(ch))
1183
 
                        {
1184
 
                                /*Channel Tx goes to idle*/     
1185
 
                                if (likely(!mp->txActive))
1186
 
                                {
1187
 
                                        MV_REG_WRITE(INT_STATUS_MASK_REG, MV_REG_READ(INT_STATUS_MASK_REG) & (~(TDM_INT_TX(mp->ch)))); 
1188
 
                                        TRC_REC("ch %d: Tx stopped.\n",mp->ch);
1189
 
                                }
1190
 
                                else
1191
 
                                {
1192
 
                                        mvOsPrintf("ch %d: Tx underflow.\n",mp->ch);
1193
 
                                }
1194
 
                        }
1195
 
                        *work_done |= MV_TDM_WRITE_INTR << MV_CHANNEL_INTR(ch);                 
1196
 
                }
1197
 
        }
1198
 
        TRC_REC("<-%s\n",__FUNCTION__);
1199
 
        return( (*work_done) ? 0 : 1 );
1200
 
}
1201
 
 
1202
 
 
1203
 
static int fxdevInterruptBits(unsigned char ch, MV_PHONE *mp)
1204
 
{
1205
 
        MV_BOOL retVal; 
1206
 
        TRC_REC("<-%s: %s\n",__FUNCTION__, mp->chType == MV_FXS ? "FXS":"FXO");
1207
 
 
1208
 
        if(mp->chType == MV_FXS)
1209
 
                retVal = checkSlicInterrupts(mp->slic_dev);  
1210
 
        else
1211
 
                retVal = checkDaaInterrupts(mp->daa_dev);
1212
 
     
1213
 
     
1214
 
    return retVal;
1215
 
 
1216
 
}
1217
 
 
1218