Advertisement
goroh_kun

AE2用ドライバ(IS01 BB01.00.14)

Nov 13th, 2011
670
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 26.20 KB | None | 0 0
  1. /*
  2.  * Copyright (C) 2009 SHARP CORPORATION
  3.  * Copyright (C) 2009 Yamaha CORPORATION
  4.  *
  5.  * This software is licensed under the terms of the GNU General Public
  6.  * License version 2, as published by the Free Software Foundation, and
  7.  * may be copied, distributed, and modified under those terms.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  */
  15.  
  16. #include <linux/types.h>
  17. #include <linux/fs.h>
  18. #include <linux/module.h>
  19. #include <linux/kernel.h>
  20. #include <linux/sched.h>
  21. #include <linux/signal.h>
  22. #include <linux/init.h>
  23. #include <linux/cdev.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/irq.h>
  26. #include <linux/delay.h>
  27. #include <linux/device.h>
  28. #include <linux/err.h>
  29. #include <linux/list.h>
  30. #include <linux/errno.h>
  31. #include <linux/mutex.h>
  32. #include <linux/slab.h>
  33. #include <asm/io.h>
  34. #include <asm/uaccess.h>
  35. #if 0
  36. #include <asm/arch/mx31_pins.h>
  37. #include <asm/arch/gpio.h>
  38. #else
  39. #include <mach/gpio.h>
  40. #endif
  41.  
  42. #include "madrv.h"
  43.  
  44. //#define KDEBUG_FUNC() printk("%s()\n", __FUNCTION__)
  45. #define KDEBUG_FUNC()
  46.  
  47. //#define YAMAHA_DEBUG_LOG
  48.  
  49. #define MA_DEVICE_NODE_NAME         "ae2"
  50. #define MA_DEVICE_NAME              "ae2"
  51. #define MA_DEVICE_IRQ_NAME          "irq_ae2"
  52. #define MA_DEVICE_COUNT             (1)
  53. #define MA_CLASS_NAME               "cls_ae2"
  54.  
  55. extern void gpio_ext_bus_active(void);
  56.  
  57. struct MaDriverInfo
  58. {
  59.     void                *pMemory;
  60.     unsigned int        dIrq;
  61.     struct cdev         sCdev;
  62.     wait_queue_head_t   sQueue;
  63.     spinlock_t          sLock;
  64.     unsigned int        dIrqCount;
  65.     unsigned int        dMaskIrq;
  66.     unsigned int        dCanceled;
  67. };
  68.  
  69. static int ma_IoCtl( struct inode *psInode, struct file *psFile, unsigned int dCmd, unsigned long dArg );
  70. static int ma_Open( struct inode *psInode, struct file *psFile );
  71. static int ma_Close( struct inode *psInode, struct file *psFile );
  72.  
  73. static struct file_operations ma_FileOps =
  74. {
  75.     .owner = THIS_MODULE,
  76.     .ioctl = ma_IoCtl,
  77.     .open = ma_Open,
  78.     .release = ma_Close,
  79. };
  80. static struct MaDriverInfo *gpsDriver = NULL;
  81. static int gsMajor = -1;
  82. static dev_t gsDev;
  83.  
  84. static struct class *gpsClass = NULL;
  85.  
  86. /****************************************************************************
  87.  *  NanoWait
  88.  *
  89.  *  Description:
  90.  *  Arguments:
  91.  *  Return:
  92.  *
  93.  ****************************************************************************/
  94. static inline int
  95. NanoWait( unsigned int dPeriod )
  96. {
  97.     unsigned int ms = 0, us = 0, ns = 0;
  98.     ms = dPeriod / 1000000;
  99.     us = ( dPeriod - ( ms * 1000000 ) ) / 1000;
  100.     ns = dPeriod - ( ms * 1000000 ) - ( us * 1000 );
  101.     if ( ms > 0 )
  102.     {
  103.         mdelay( ms );
  104.     }
  105.     if ( us > 0 )
  106.     {
  107.         udelay( us );
  108.     }
  109.     if ( ns > 0 )
  110.     {
  111.         ndelay( ns );
  112.     }
  113.     return 0;
  114. }
  115.  
  116. /****************************************************************************
  117.  *  IoCtl_Wait
  118.  *
  119.  *  Description:
  120.  *          Processing that does weight every Nano second is done.
  121.  *  Arguments:
  122.  *          psInode inode info pointer
  123.  *          psFile  file info pointer
  124.  *          dArg    wait value(ns)
  125.  *  Return:
  126.  *          0       success
  127.  *          < 0     error code
  128.  *
  129.  ****************************************************************************/
  130. static inline int
  131. IoCtl_Wait( struct inode *psInode, struct file *psFile, unsigned long dArg )
  132. {
  133.     /*
  134.         Processing that does weight every Nano second is done.
  135.     */
  136.  
  137.     (void)psInode;
  138.     (void)psFile;
  139.  
  140.     return NanoWait( dArg );
  141. }
  142.  
  143. /****************************************************************************
  144.  *  MilliSleep
  145.  *
  146.  *  Description:
  147.  *  Arguments:
  148.  *  Return:
  149.  *
  150.  ****************************************************************************/
  151. #if (0)
  152. static inline int
  153. MilliSleep( unsigned int dPeriod )
  154. {
  155.     msleep( dPeriod );
  156.     return 0;
  157. }
  158.  
  159. #else
  160. static inline int
  161. MilliSleep( unsigned int dPeriod )
  162. {
  163.     struct timeval sStart, sCurrent;
  164.     unsigned long dDiff = 0;
  165.     if ( dPeriod == 0 )
  166.     {
  167.         schedule();
  168.         return 0;
  169.     }
  170.     if ( dPeriod > 4000000 )
  171.     {
  172.         return -EINVAL; /* Too big */
  173.     }
  174.     /* do_gettimeofday might provide more accuracy than jiffies */
  175.     do_gettimeofday( &sStart );
  176.     for ( ;; )
  177.     {
  178.         do_gettimeofday( &sCurrent );
  179.         dDiff = ( sCurrent.tv_sec - sStart.tv_sec ) * 1000000 + ( sCurrent.tv_usec - sStart.tv_usec );
  180.         if ( dDiff > dPeriod * 1000 )
  181.         {
  182.             break;
  183.         }
  184.         schedule();
  185.     }
  186.     return 0;
  187. }
  188. #endif
  189.  
  190. /****************************************************************************
  191.  *  IoCtl_Sleep
  192.  *
  193.  *  Description:
  194.  *          Processing that does the sleep in each millisecond is done.
  195.  *  Arguments:
  196.  *          psInode inode info pointer
  197.  *          psFile  file info pointer
  198.  *          dArg    sleep value(ms)
  199.  *  Return:
  200.  *          0       success
  201.  *          < 0     error code
  202.  *
  203.  ****************************************************************************/
  204. static inline int
  205. IoCtl_Sleep( struct inode *psInode, struct file *psFile, unsigned long dArg )
  206. {
  207.     /*
  208.         Processing that does the sleep in each millisecond is done.
  209.     */
  210.  
  211.     (void)psInode;
  212.     (void)psFile;
  213.     (void)dArg;
  214.  
  215.     return MilliSleep( dArg );
  216. }
  217.  
  218. /****************************************************************************
  219.  *  WriteRegWait
  220.  *
  221.  *  Description:
  222.  *  Arguments:
  223.  *  Return:
  224.  *
  225.  ****************************************************************************/
  226. static inline int
  227. WriteRegWait( unsigned long dAddress, void *pData, unsigned int dSize, unsigned int dWait )
  228. {
  229.     (void)dWait;
  230.  
  231.     if ( gpsDriver == NULL )
  232.     {
  233.         return -ENOTTY;
  234.     }
  235. #if 0
  236.     dAddress <<= 1;
  237. #endif
  238.     dAddress += (unsigned long) gpsDriver->pMemory;
  239. #if 1
  240.     NanoWait( dWait );
  241. #endif
  242.     switch ( dSize )
  243.     {
  244.     case sizeof( unsigned char ):
  245.         iowrite8( *(unsigned char *)pData, (void *)dAddress );
  246.         break;
  247.     case sizeof( unsigned short ):
  248.         iowrite16( *(unsigned short *)pData, (void *)dAddress );
  249.         break;
  250.     default:
  251.         return -EINVAL;
  252.     }
  253.     return 0;
  254. }
  255.  
  256. /****************************************************************************
  257.  *  IoCtl_WriteRegWait
  258.  *
  259.  *  Description:
  260.  *          The processing written in the interface register is done.
  261.  *  Arguments:
  262.  *          psInode inode info pointer
  263.  *          psFile  file info pointer
  264.  *          dArg    pointer to ma_IoCtlWriteRegWait structure
  265.  *  Return:
  266.  *          0       success
  267.  *          < 0     error code
  268.  *
  269.  ****************************************************************************/
  270. static inline int
  271. IoCtl_WriteRegWait( struct inode *psInode, struct file *psFile, unsigned long dArg )
  272. {
  273.     /*
  274.         Data is copied from the user space, and it writes it in the interface register.
  275.     */
  276.  
  277.     struct ma_IoCtlWriteRegWait sParam;
  278.     unsigned char bData = 0;
  279.     unsigned short wData = 0;
  280. #if 1
  281.     unsigned long dFlags = 0;
  282. #else
  283.     unsigned int dFlags = 0;
  284. #endif
  285.     unsigned int dCnt;
  286.     if ( gpsDriver == NULL )
  287.     {
  288.         return -ENOTTY;
  289.     }
  290.     if ( copy_from_user( &sParam, (void*)dArg, sizeof( sParam ) ) )
  291.     {
  292.         return -EFAULT;
  293.     }
  294.     switch ( sParam.dSize )
  295.     {
  296.     case sizeof( unsigned char ):
  297.         for(dCnt=0; dCnt<sParam.dDataLen; ++dCnt) {
  298.             get_user( bData, (((unsigned char*)sParam.pData) + dCnt) );
  299.             spin_lock_irqsave( &gpsDriver->sLock, dFlags);
  300.             WriteRegWait( sParam.dAddress, &bData, sizeof( bData ), sParam.dWait );
  301.             spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  302.         }
  303.         break;
  304.     case sizeof( unsigned short ):
  305.         for(dCnt=0; dCnt<sParam.dDataLen; ++dCnt) {
  306.             get_user( wData, (((unsigned short*)sParam.pData) + dCnt) );
  307.             spin_lock_irqsave( &gpsDriver->sLock, dFlags);
  308.             WriteRegWait( sParam.dAddress, &wData, sizeof( wData ), sParam.dWait );
  309.             spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  310.         }
  311.         break;
  312.     default:
  313.         return -EINVAL;
  314.     }
  315.     return 0;
  316. }
  317.  
  318. /****************************************************************************
  319.  *  ReadRegWait
  320.  *
  321.  *  Description:
  322.  *  Arguments:
  323.  *  Return:
  324.  *
  325.  ****************************************************************************/
  326. static inline int
  327. ReadRegWait( unsigned long dAddress, void *pData, unsigned int dSize, unsigned int dWait )
  328. {
  329.     /*
  330.         It reads it from the interface register.
  331.         The read value is copied onto the user space.
  332.     */
  333.  
  334.     if ( gpsDriver == NULL )
  335.     {
  336.         return -ENOTTY;
  337.     }
  338. #if 0
  339.     dAddress <<= 1;
  340. #endif
  341.     dAddress += (unsigned long) gpsDriver->pMemory;
  342.     NanoWait( dWait );
  343.     switch ( dSize ) {
  344.     case sizeof( unsigned char ):
  345.         *(unsigned char *)pData = ioread8( (void *)dAddress );
  346.         break;
  347.     case sizeof( unsigned short ):
  348.         *(unsigned short *)pData = ioread16( (void *)dAddress );
  349.         break;
  350.     default:
  351.         return -EINVAL;
  352.     }
  353.     return 0;
  354. }
  355.  
  356. /****************************************************************************
  357.  *  IoCtl_ReadRegWait
  358.  *
  359.  *  Description:
  360.  *          The processing read from the interface register is done.
  361.  *  Arguments:
  362.  *          psInode inode info pointer
  363.  *          psFile  file info pointer
  364.  *          dArg    pointer to ma_IoCtlReadRegWait structure
  365.  *  Return:
  366.  *          0       success
  367.  *          < 0     error code
  368.  *
  369.  ****************************************************************************/
  370. static inline int
  371. IoCtl_ReadRegWait( struct inode *psInode, struct file *psFile, unsigned long dArg )
  372. {
  373.     /*
  374.         It reads it from the interface register.
  375.         The read value is copied onto the user space.
  376.     */
  377.  
  378.     struct ma_IoCtlReadRegWait sParam;
  379.     unsigned char bData = 0;
  380.     unsigned short wData = 0;
  381. #if 1
  382.     unsigned long dFlags;
  383. #else
  384.     unsigned int dFlags;
  385. #endif
  386.     unsigned int dCnt;
  387.     if ( gpsDriver == NULL )
  388.     {
  389.         return -ENOTTY;
  390.     }
  391.     if ( copy_from_user( &sParam, (void*)dArg, sizeof( sParam ) ) )
  392.     {
  393.         return -EFAULT;
  394.     }
  395.     switch ( sParam.dSize ) {
  396.     case sizeof( unsigned char ):
  397.         for(dCnt=0; dCnt<sParam.dDataLen; ++dCnt) {
  398.             spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  399.             ReadRegWait( sParam.dAddress, &bData, sizeof( bData ), sParam.dWait );
  400.             spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  401.             put_user( bData, (((unsigned char*)sParam.pData) + dCnt) );
  402.         }
  403.         break;
  404.     case sizeof( unsigned short ):
  405.         for(dCnt=0; dCnt<sParam.dDataLen; ++dCnt) {
  406.             spin_lock_irqsave( &gpsDriver->sLock, dFlags);
  407.             ReadRegWait( sParam.dAddress, &wData, sizeof( wData ), sParam.dWait );
  408.             spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  409.             put_user( wData, (((unsigned short*)sParam.pData) + dCnt) );
  410.         }
  411.         break;
  412.     default:
  413.         return -EINVAL;
  414.     }
  415.     return 0;
  416. }
  417.  
  418. /****************************************************************************
  419.  *  DisableIrq
  420.  *
  421.  *  Description:
  422.  *  Arguments:
  423.  *  Return:
  424.  *
  425.  ****************************************************************************/
  426. static inline int
  427. DisableIrq( void )
  428. {
  429.     unsigned char bStatus = 0x00;
  430.     if ( gpsDriver == NULL )
  431.     {
  432.         return -ENOTTY;
  433.     }
  434.     if ( gpsDriver->dMaskIrq == 0 )
  435.     {
  436.         WriteRegWait( 0x00, &bStatus, sizeof( bStatus ), 135 );
  437.     }
  438.     gpsDriver->dMaskIrq++;
  439.     return 0;
  440. }
  441.  
  442. /****************************************************************************
  443.  *  IoCtl_DisableIrq
  444.  *
  445.  *  Description:
  446.  *          The interruption is prohibited.
  447.  *  Arguments:
  448.  *          psInode inode info pointer
  449.  *          psFile  file info pointer
  450.  *          dArg    no use
  451.  *  Return:
  452.  *          0       success
  453.  *          < 0     error code
  454.  *
  455.  ****************************************************************************/
  456. static inline int
  457. IoCtl_DisableIrq( struct inode *psInode, struct file *psFile, unsigned long dArg )
  458. {
  459.     /*
  460.         The interruption is prohibited.
  461.     */
  462.  
  463.     unsigned long dFlags;
  464.     int sdResult = 0;
  465.     if ( gpsDriver == NULL )
  466.     {
  467.         return -ENOTTY;
  468.     }
  469.     spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  470.     sdResult = DisableIrq();
  471.     spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  472.     return sdResult;
  473. }
  474.  
  475. /****************************************************************************
  476.  *  EnableIrq
  477.  *
  478.  *  Description:
  479.  *  Arguments:
  480.  *  Return:
  481.  *
  482.  ****************************************************************************/
  483. static inline int
  484. EnableIrq( void )
  485. {
  486.     unsigned char bStatus = 0x80;
  487.     if ( gpsDriver == NULL )
  488.     {
  489.         return -ENOTTY;
  490.     }
  491.     if ( gpsDriver->dMaskIrq > 0UL )
  492.     {
  493.         gpsDriver->dMaskIrq--;
  494.     }
  495.     if ( gpsDriver->dMaskIrq == 0UL )
  496.     {
  497.         WriteRegWait( 0x00, &bStatus, sizeof( bStatus ), 135 );
  498.     }
  499.     return 0;
  500. }
  501.  
  502. /****************************************************************************
  503.  *  IoCtl_EnableIrq
  504.  *
  505.  *  Description:
  506.  *          The interruption is permitted.
  507.  *  Arguments:
  508.  *          psInode inode info pointer
  509.  *          psFile  file info pointer
  510.  *          dArg    no use
  511.  *  Return:
  512.  *          0       success
  513.  *          < 0     error code
  514.  *
  515.  ****************************************************************************/
  516. static inline int
  517. IoCtl_EnableIrq( struct inode *psInode, struct file *psFile, unsigned long dArg )
  518. {
  519.     /*
  520.         The interruption is permitted.
  521.     */
  522.  
  523.     unsigned long dFlags;
  524.     int sdResult = 0;
  525.     if ( gpsDriver == NULL )
  526.     {
  527.         return -ENOTTY;
  528.     }
  529.     spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  530.     sdResult = EnableIrq();
  531.     spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  532.     return sdResult;
  533. }
  534.  
  535. /****************************************************************************
  536.  *  ResetIrqMaskCount
  537.  *
  538.  *  Description:
  539.  *  Arguments:
  540.  *  Return:
  541.  *
  542.  ****************************************************************************/
  543. static inline int
  544. ResetIrqMaskCount( void )
  545. {
  546.     if ( gpsDriver == NULL )
  547.     {
  548.         return -ENOTTY;
  549.     }
  550.  
  551.     gpsDriver->dMaskIrq = 0;
  552.     return 0;
  553. }
  554.  
  555. /****************************************************************************
  556.  *  IoCtl_ResetIrqMaskCount
  557.  *
  558.  *  Description:
  559.  *          The interruption mask counter is initialized.
  560.  *  Arguments:
  561.  *          psInode inode info pointer
  562.  *          psFile  file info pointer
  563.  *          dArg    no use
  564.  *  Return:
  565.  *          0       success
  566.  *          < 0     error code
  567.  *
  568.  ****************************************************************************/
  569. static inline int
  570. IoCtl_ResetIrqMaskCount( struct inode *psInode, struct file *psFile, unsigned long dArg )
  571. {
  572.     /*
  573.         The interruption mask counter is initialized.
  574.     */
  575.  
  576.     unsigned long dFlags = 0;
  577.     int sdResult = 0;
  578.  
  579.     (void)psInode;
  580.     (void)psFile;
  581.     (void)dArg;
  582.  
  583.     if ( gpsDriver == NULL )
  584.     {
  585.         return -ENOTTY;
  586.     }
  587.  
  588.     spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  589.     sdResult = ResetIrqMaskCount();
  590.     spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  591.  
  592.     return sdResult;
  593. }
  594.  
  595. /****************************************************************************
  596.  *  IoCtl_WaitIrq
  597.  *
  598.  *  Description:
  599.  *          The interruption is waited for.
  600.  *  Arguments:
  601.  *          psInode inode info pointer
  602.  *          psFile  file info pointer
  603.  *          dArg    Pointer to variable that stores interruption frequency
  604.  *  Return:
  605.  *          0       success
  606.  *          < 0     error code
  607.  *
  608.  ****************************************************************************/
  609. static inline int
  610. IoCtl_WaitIrq( struct inode *psInode, struct file *psFile, unsigned long dArg )
  611. {
  612.     /*
  613.         Sleep until interruption is notified, or waiting condition is released.
  614.         When getting up, store the counter of interruption reserved to dArg of user space,
  615.         and return it.
  616.         When the interruption has already reserved it, this API call is returned at once.
  617.     */
  618.  
  619.     unsigned long dFlags;
  620.     int sdResult = 0;
  621.     int dIrqCount = 0;
  622.  
  623.     KDEBUG_FUNC();
  624.  
  625.     (void)psInode;
  626.     (void)psFile;
  627.     (void)dArg;
  628.  
  629.     if ( gpsDriver == NULL )
  630.     {
  631.         return -ENOTTY;
  632.     }
  633.     spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  634.     if ( gpsDriver->dIrqCount != 0 )
  635.     {
  636.         dIrqCount = gpsDriver->dIrqCount;
  637.         gpsDriver->dIrqCount = 0;
  638.         spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  639.     }
  640.     else
  641.     {
  642.         spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  643.         for ( ;; )
  644.         {
  645.             DEFINE_WAIT( sWait );
  646.             prepare_to_wait( &gpsDriver->sQueue, &sWait, TASK_INTERRUPTIBLE );
  647.             spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  648.             if ( gpsDriver->dCanceled )
  649.             {
  650.                 dIrqCount = -1;
  651.                 gpsDriver->dCanceled = 0;
  652.                 spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  653.                 finish_wait( &gpsDriver->sQueue, &sWait );
  654.                 sdResult = -ERESTARTSYS;
  655.                 goto out;
  656.             }
  657.             if ( gpsDriver->dIrqCount != 0 )
  658.             {
  659.                 dIrqCount = gpsDriver->dIrqCount;
  660.                 gpsDriver->dIrqCount = 0;
  661.                 spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  662.                 finish_wait( &gpsDriver->sQueue, &sWait );
  663.                 sdResult = 0;
  664.                 goto out;
  665.             }
  666.             spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  667.             if ( signal_pending( current ) )
  668.             {
  669.                 dIrqCount = 0;
  670.                 finish_wait( &gpsDriver->sQueue, &sWait );
  671.                 sdResult = -ERESTARTSYS;
  672.                 goto out;
  673.             }
  674.             schedule();
  675.             finish_wait( &gpsDriver->sQueue, &sWait );
  676.         }
  677.     }
  678. out:
  679.     if ( dArg != 0 )
  680.     {
  681.         put_user( dIrqCount, (unsigned int*)dArg );
  682.     }
  683.     return sdResult;
  684. }
  685.  
  686.  
  687. /****************************************************************************
  688.  *  IoCtl_CancelWaitIrq
  689.  *
  690.  *  Description:
  691.  *          The interruption waiting state is released.
  692.  *  Arguments:
  693.  *          psInode inode info pointer
  694.  *          psFile  file info pointer
  695.  *          dArg    no use
  696.  *  Return:
  697.  *          0       success
  698.  *          < 0     error code
  699.  *
  700.  ****************************************************************************/
  701. static inline int
  702. IoCtl_CancelWaitIrq( struct inode *psInode, struct file *psFile, unsigned long dArg )
  703. {
  704.     /*
  705.         The interruption waiting state is released.
  706.     */
  707.     unsigned long dFlags = 0;
  708.  
  709.     KDEBUG_FUNC();
  710.  
  711.     (void)psInode;
  712.     (void)psFile;
  713.     (void)dArg;
  714.  
  715.     if ( gpsDriver == NULL )
  716.     {
  717.         return -ENOTTY;
  718.     }
  719.  
  720.     spin_lock_irqsave( &gpsDriver->sLock, dFlags );
  721.     gpsDriver->dCanceled = 1;
  722.     spin_unlock_irqrestore( &gpsDriver->sLock, dFlags );
  723.  
  724.     wake_up_interruptible( &gpsDriver->sQueue );
  725.     return 0;
  726. }
  727.  
  728. /****************************************************************************
  729.  *  IrqIsMine
  730.  *
  731.  *  Description:
  732.  *  Arguments:
  733.  *  Return:
  734.  *
  735.  ****************************************************************************/
  736. static inline int
  737. IrqIsMine( void )
  738. {
  739.     unsigned char bStatus = 0;
  740.     ReadRegWait( 0, &bStatus, sizeof( bStatus ), 150 );
  741.     if ( ( bStatus & 0x01 ) == 0 || ( bStatus & 0x80 ) == 0 )
  742.     {
  743.         return 0;
  744.     }
  745.     return 1;
  746. }
  747.  
  748. #if 1
  749. /****************************************************************************
  750.  *  IoCtl_SetGpio
  751.  *
  752.  *  Description:
  753.  *  Arguments:
  754.  *  Return:
  755.  *
  756.  ****************************************************************************/
  757. static inline int
  758. IoCtl_SetGpio( struct inode *psInode, struct file *psFile, unsigned long dArg )
  759. {
  760.     (void)psInode;
  761.     (void)psFile;
  762.  
  763.     if( dArg == 0 ){
  764.         /* OFF */
  765.         gpio_direction_output(121, 0);
  766.         gpio_direction_output(27, 0);
  767. #ifdef YAMAHA_DEBUG_LOG
  768.         printk("IoCtl_SetGpio GPIO OFF\n");
  769. #endif
  770.     }else{
  771.         /* ON */
  772.         gpio_direction_output(121, 1);
  773.         gpio_direction_output(27, 1);
  774. #ifdef YAMAHA_DEBUG_LOG
  775.         printk("IoCtl_SetGpio GPIO ON\n");
  776. #endif
  777.     }
  778.  
  779.     return 0;
  780. }
  781. #endif
  782.  
  783. /****************************************************************************
  784.  *  ma_IrqHandler
  785.  *
  786.  *  Description:
  787.  *          Interruption handler
  788.  *  Arguments:
  789.  *          sdIrq   interruption number
  790.  *          pDevId  pointer to device ID
  791.  *  Return:
  792.  *          0       success
  793.  *          < 0     error code
  794.  *
  795.  ****************************************************************************/
  796. static irqreturn_t
  797. ma_IrqHandler( int sdIrq, void *pDevId )
  798. {
  799.     /*
  800.         It is notified that the interruption entered the interrupt processing thread.
  801.     */
  802.  
  803.     KDEBUG_FUNC();
  804.     (void)sdIrq;
  805.  
  806.     if ( pDevId == NULL || gpsDriver == NULL )
  807.     {
  808.         return IRQ_NONE;
  809.     }
  810.     spin_lock( &gpsDriver->sLock ); /* for SMP */
  811.     if ( !IrqIsMine() )
  812.     {
  813.         spin_unlock( &gpsDriver->sLock );
  814.         return IRQ_NONE;
  815.     }
  816.     DisableIrq();
  817.     gpsDriver->dIrqCount++;
  818.     spin_unlock( &gpsDriver->sLock );
  819.     wake_up_interruptible( &gpsDriver->sQueue );
  820.     return IRQ_HANDLED;
  821. }
  822.  
  823. /****************************************************************************
  824.  *  ma_IoCtl
  825.  *
  826.  *  Description:
  827.  *          Character type driver IoCtl processing is executed.
  828.  *  Arguments:
  829.  *          psInode inode info pointer
  830.  *          psFile  file info pointer
  831.  *          dCmd    ioctl command number
  832.  *          dArg    ioctl command argument
  833.  *  Return:
  834.  *          0       success
  835.  *          < 0     error code
  836.  *
  837.  ****************************************************************************/
  838. static int
  839. ma_IoCtl( struct inode *psInode, struct file *psFile, unsigned int dCmd, unsigned long dArg )
  840. {
  841.     int sdResult = -EFAULT;
  842.  
  843.     if ( gpsDriver == NULL )
  844.     {
  845.         return -ENOTTY;
  846.     }
  847.  
  848.     switch ( dCmd ) {
  849.     case MA_IOCTL_WAIT:
  850.         sdResult = IoCtl_Wait( psInode, psFile, dArg );
  851.         break;
  852.     case MA_IOCTL_SLEEP:
  853.         sdResult = IoCtl_Sleep( psInode, psFile, dArg );
  854.         break;
  855.     case MA_IOCTL_WRITE_REG_WAIT:
  856.         sdResult = IoCtl_WriteRegWait( psInode, psFile, dArg );
  857.         break;
  858.     case MA_IOCTL_READ_REG_WAIT:
  859.         sdResult = IoCtl_ReadRegWait( psInode, psFile, dArg );
  860.         break;
  861.     case MA_IOCTL_DISABLE_IRQ:
  862.         sdResult = IoCtl_DisableIrq( psInode, psFile, dArg );
  863.         break;
  864.     case MA_IOCTL_ENABLE_IRQ:
  865.         sdResult = IoCtl_EnableIrq( psInode, psFile, dArg );
  866.         break;
  867.     case MA_IOCTL_RESET_IRQ_MASK_COUNT:
  868.         sdResult = IoCtl_ResetIrqMaskCount( psInode, psFile, dArg );
  869.         break;
  870.     case MA_IOCTL_WAIT_IRQ:
  871.         sdResult = IoCtl_WaitIrq( psInode, psFile, dArg );
  872.         break;
  873.     case MA_IOCTL_CANCEL_WAIT_IRQ:
  874.         sdResult = IoCtl_CancelWaitIrq( psInode, psFile, dArg );
  875.         break;
  876. #if 1
  877.     case MA_IOCTL_SET_GPIO:
  878.         sdResult = IoCtl_SetGpio( psInode, psFile, dArg );
  879.         break;
  880. #endif
  881.     default:
  882.         sdResult = -ENOTTY;
  883.         break;
  884.     }
  885.  
  886.     return sdResult;
  887. }
  888.  
  889. /****************************************************************************
  890.  *  ma_Open
  891.  *
  892.  *  Description:
  893.  *  Arguments:
  894.  *  Return:
  895.  *
  896.  ****************************************************************************/
  897. static int
  898. ma_Open( struct inode *psInode, struct file *psFile )
  899. {
  900.     /*
  901.         Character type driver Open processes it.
  902.     */
  903.     int sdResult = 0;
  904.  
  905.     KDEBUG_FUNC();
  906.  
  907.     if ( gpsDriver == NULL )
  908.     {
  909.         return -ENOTTY;
  910.     }
  911.  
  912. #if 1
  913.     gpio_tlmm_config(GPIO_CFG(27,  0, GPIO_OUTPUT, GPIO_NO_PULL,   GPIO_2MA), GPIO_ENABLE);
  914.     gpio_tlmm_config(GPIO_CFG(28,  0, GPIO_INPUT,  GPIO_PULL_DOWN, GPIO_2MA), GPIO_ENABLE);
  915.     gpio_tlmm_config(GPIO_CFG(102, 1, GPIO_OUTPUT, GPIO_NO_PULL,   GPIO_2MA), GPIO_ENABLE);
  916.     gpio_tlmm_config(GPIO_CFG(121, 0, GPIO_OUTPUT, GPIO_NO_PULL,   GPIO_2MA), GPIO_ENABLE);
  917.  
  918.     gpio_direction_output(121, 1);
  919.     gpio_direction_output(27, 1);
  920. #ifdef YAMAHA_DEBUG_LOG
  921.     printk("ma_Open GPIO ON\n");
  922. #endif
  923. #endif
  924.  
  925.     /* init */
  926.     init_waitqueue_head( &gpsDriver->sQueue );
  927.     spin_lock_init( &gpsDriver->sLock );
  928.     gpsDriver->dIrqCount = 0;
  929.     gpsDriver->dCanceled = 0;
  930.  
  931.     /* I/O port setting */
  932. #if 0
  933.     gpsDriver->pMemory = ioremap( ?, 64 );
  934. #else
  935.     gpsDriver->pMemory = ioremap( 0x90000000, 64 );
  936. #endif
  937.     if ( gpsDriver->pMemory == NULL )
  938.     {
  939.         goto err1;
  940.     }
  941.  
  942.     /* interrrupt setting */
  943.     ResetIrqMaskCount();
  944.  
  945. #if 0
  946.     gpsDriver->dIrq = ?;
  947.     sdResult = request_irq( gpsDriver->dIrq, ma_IrqHandler, IRQF_SHARED, MA_DEVICE_IRQ_NAME, gpsDriver );
  948.     if ( sdResult < 0 )
  949.     {
  950.         goto err2;
  951.     }
  952.     set_irq_type( gpsDriver->dIrq, IRQT_FALLING );
  953. #else
  954.     gpsDriver->dIrq = MSM_GPIO_TO_INT(28);
  955.     sdResult = request_irq( gpsDriver->dIrq, ma_IrqHandler, IRQF_TRIGGER_FALLING, MA_DEVICE_NAME, gpsDriver );
  956.     if ( sdResult < 0 )
  957.     {
  958.         goto err2;
  959.     }
  960. #endif
  961.  
  962.     return 0;
  963. err2:
  964.     iounmap( gpsDriver->pMemory );
  965.     gpsDriver->pMemory = NULL;
  966. err1:
  967. #if 1
  968.     gpio_direction_output(121, 0);
  969.     gpio_direction_output(27, 0);
  970. #ifdef YAMAHA_DEBUG_LOG
  971.     printk("ma_Open GPIO Err OFF\n");
  972. #endif
  973. #endif
  974.     return sdResult;
  975. }
  976.  
  977. /****************************************************************************
  978.  *  ma_Close
  979.  *
  980.  *  Description:
  981.  *          Character type driver Close processing is executed.
  982.  *  Arguments:
  983.  *          psInode inode info pointer
  984.  *          psFile  file info pointer
  985.  *  Return:
  986.  *          0       success
  987.  *          < 0     error code
  988.  *
  989.  ****************************************************************************/
  990. static int
  991. ma_Close( struct inode *psInode, struct file *psFile )
  992. {
  993.     /*
  994.         Character type driver Close processes it.
  995.     */
  996.     KDEBUG_FUNC();
  997.  
  998.     (void)psInode;
  999.     (void)psFile;
  1000.  
  1001.     if ( gpsDriver == NULL )
  1002.     {
  1003.         return -ENOTTY;
  1004.     }
  1005.     if ( gpsDriver->pMemory == NULL )
  1006.     {
  1007.         return -ENOTTY;
  1008.     }
  1009.  
  1010.     free_irq( gpsDriver->dIrq, gpsDriver );
  1011.     iounmap( gpsDriver->pMemory );
  1012.     gpsDriver->pMemory = NULL;
  1013.  
  1014. #if 1
  1015.     gpio_direction_output(27, 0);
  1016.     gpio_direction_output(121, 0);
  1017. #endif
  1018.  
  1019.     return 0;
  1020. }
  1021.  
  1022. /****************************************************************************
  1023.  *  ma_Init
  1024.  *
  1025.  *  Description:
  1026.  *          The driver is initialized.
  1027.  *  Arguments:
  1028.  *          none
  1029.  *  Return:
  1030.  *          0       success
  1031.  *          < 0     error code
  1032.  *
  1033.  ****************************************************************************/
  1034. static int __init
  1035. ma_Init( void )
  1036. {
  1037.     /*
  1038.         Processing that registers the character type driver is done.
  1039.     */
  1040.  
  1041.     int sdResult;
  1042.     struct device *dev;
  1043.  
  1044.     KDEBUG_FUNC();
  1045.  
  1046.     sdResult = alloc_chrdev_region( &gsDev, 0, MA_DEVICE_COUNT, MA_DEVICE_NAME );
  1047.     if ( sdResult < 0 )
  1048.     {
  1049.         goto err1;
  1050.     }
  1051.     gsMajor = sdResult;
  1052.  
  1053.     gpsDriver = kzalloc( sizeof( struct MaDriverInfo ), GFP_KERNEL );
  1054.     if ( gpsDriver == NULL )
  1055.     {
  1056.         sdResult = -ENOMEM;
  1057.         goto err2;
  1058.     }
  1059.  
  1060.     cdev_init( &gpsDriver->sCdev, &ma_FileOps );
  1061.     gpsDriver->sCdev.owner = THIS_MODULE;
  1062.     gpsDriver->sCdev.ops = &ma_FileOps;
  1063.     sdResult = cdev_add( &gpsDriver->sCdev, gsDev, MA_DEVICE_COUNT );
  1064.     if ( sdResult < 0 )
  1065.     {
  1066.         goto err3;
  1067.     }
  1068.  
  1069.     gpsClass = class_create( THIS_MODULE, MA_CLASS_NAME );
  1070.     if ( IS_ERR(gpsClass) )
  1071.     {
  1072.         sdResult = PTR_ERR( gpsClass );
  1073.         goto err4;
  1074.     }
  1075.  
  1076. #if 1
  1077.     dev = device_create( gpsClass, NULL, gsDev, NULL, MA_DEVICE_NODE_NAME );
  1078. #else
  1079.     dev = device_create( gpsClass, NULL, gsDev, MA_DEVICE_NODE_NAME );
  1080. #endif
  1081.     sdResult = IS_ERR(dev) ? PTR_ERR(dev) : 0;
  1082.     if ( sdResult < 0 )
  1083.     {
  1084.         goto err5;
  1085.     }
  1086.  
  1087.     return 0;
  1088.  
  1089. err5:
  1090.     class_destroy( gpsClass );
  1091.     gpsClass = NULL;
  1092. err4:
  1093.     cdev_del( &gpsDriver->sCdev );
  1094. err3:
  1095.     kfree( gpsDriver );
  1096.     gpsDriver = NULL;
  1097. err2:
  1098.     unregister_chrdev_region( gsDev, MA_DEVICE_COUNT );
  1099.     gsMajor = -1;
  1100. err1:
  1101.     return sdResult;
  1102. }
  1103.  
  1104. /****************************************************************************
  1105.  *  ma_Term
  1106.  *
  1107.  *  Description:
  1108.  *          The driver is ended.
  1109.  *  Arguments:
  1110.  *          none
  1111.  *  Return:
  1112.  *          0       success
  1113.  *          < 0     error code
  1114.  *
  1115.  ****************************************************************************/
  1116. static void __exit
  1117. ma_Term( void )
  1118. {
  1119.     /*
  1120.         Processing that deletes the character type driver is done.
  1121.     */
  1122.  
  1123.     KDEBUG_FUNC();
  1124.  
  1125.     if ( gsMajor < 0 )
  1126.     {
  1127.         return;
  1128.     }
  1129.  
  1130.     device_destroy( gpsClass, gsDev );
  1131.  
  1132.     class_destroy( gpsClass );
  1133.     gpsClass = NULL;
  1134.  
  1135.     cdev_del( &gpsDriver->sCdev );
  1136.     kfree( gpsDriver );
  1137.     gpsDriver = NULL;
  1138.  
  1139.     unregister_chrdev_region( gsDev, MA_DEVICE_COUNT );
  1140.     gsMajor = -1;
  1141.  
  1142.     return;
  1143. }
  1144.  
  1145. module_init( ma_Init );
  1146. module_exit( ma_Term );
  1147.  
  1148. MODULE_DESCRIPTION("ae2 driver");
  1149. MODULE_LICENSE("GPL");
  1150.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement