lubbock.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/pcmcia/pxa/lubbock.c
  3.  *
  4.  * Author: George Davis
  5.  * Created: Jan 10, 2002
  6.  * Copyright: MontaVista Software Inc.
  7.  * 
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License version 2 as
  10.  * published by the Free Software Foundation.
  11.  *
  12.  * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
  13.  *
  14.  * Lubbock PCMCIA specific routines.
  15.  *
  16.  */
  17. #include <linux/kernel.h>
  18. #include <linux/sched.h>
  19. #include <asm/delay.h>
  20. #include <asm/hardware.h>
  21. #include <asm/irq.h>
  22. #include <asm/arch/pcmcia.h>
  23. #include <asm/hardware/sa1111.h>
  24. /*
  25.  * I'd really like to move the INTPOL stuff to arch/arm/mach-sa1100/sa1111.c
  26.  * ... and maybe even arch/arm/mach-pxa/sa1111.c now too!  : )
  27.  */
  28. #define SA1111_IRQMASK_LO(x) (1 << (x - IRQ_SA1111_START))
  29. #define SA1111_IRQMASK_HI(x) (1 << (x - IRQ_SA1111_START - 32))
  30. static int lubbock_pcmcia_init(struct pcmcia_init *init){
  31.   int return_val=0;
  32.   /* Set PCMCIA Socket 0 power to standby mode.
  33.    */
  34.   PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
  35.   /* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller.
  36.    * Note that this is done only after first initializing GPIO_A<3:0>
  37.    * output state above to be certain that we drive signals to the same
  38.    * state as the pull-downs connected to these lines. The pull-downs are
  39.    * req'd to make sure PCMCIA power is OFF until we can get around to
  40.    * setting up the GPIO_A<3:0> state and direction.
  41.    */
  42.   PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
  43.   /* Set CF Socket 1 power to standby mode. */
  44.   LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
  45.   INTPOL1 |= SA1111_IRQMASK_HI(S0_READY_NINT) |
  46.      SA1111_IRQMASK_HI(S1_READY_NINT) |
  47.      SA1111_IRQMASK_HI(S0_CD_VALID) |
  48.      SA1111_IRQMASK_HI(S1_CD_VALID) |
  49.      SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
  50.      SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
  51. #warning what if a request_irq fails?
  52.   return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
  53.   "Lubbock PCMCIA (0) CD", NULL);
  54.   return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
  55.   "Lubbock CF (1) CD", NULL);
  56.   return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
  57.   "Lubbock PCMCIA (0) BVD1", NULL);
  58.   return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
  59.   "Lubbock CF (1) BVD1", NULL);
  60.   return (return_val<0) ? -1 : 2;
  61. }
  62. static int lubbock_pcmcia_shutdown(void){
  63.   free_irq(S0_CD_VALID, NULL);
  64.   free_irq(S1_CD_VALID, NULL);
  65.   free_irq(S0_BVD1_STSCHG, NULL);
  66.   free_irq(S1_BVD1_STSCHG, NULL);
  67.   INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) |
  68.        SA1111_IRQMASK_HI(S1_CD_VALID) |
  69.        SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
  70.        SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
  71.   return 0;
  72. }
  73. static int lubbock_pcmcia_socket_state(struct pcmcia_state_array
  74. *state_array){
  75.   unsigned long status;
  76.   int return_val=1;
  77.   if(state_array->size<2) return -1;
  78.   memset(state_array->state, 0, 
  79.  (state_array->size)*sizeof(struct pcmcia_state));
  80.   status=PCSR;
  81.   state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
  82.   state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
  83.   state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
  84.   state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
  85.   state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
  86.   state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
  87.   state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
  88.   state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
  89.   state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
  90.   state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
  91.   state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
  92.   state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
  93.   state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
  94.   state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
  95.   return return_val;
  96. }
  97. static int lubbock_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
  98.   switch(info->sock){
  99.   case 0:
  100.     info->irq=S0_READY_NINT;
  101.     break;
  102.   case 1:
  103.     info->irq=S1_READY_NINT;
  104.     break;
  105.   default:
  106.     return -1;
  107.   }
  108.   return 0;
  109. }
  110. static int lubbock_pcmcia_configure_socket(const struct pcmcia_configure
  111.     *configure){
  112.   unsigned long pccr=PCCR, gpio=PA_DWR, misc_wr = LUB_MISC_WR;
  113.   /* Lubbock uses the Maxim MAX1602, with the following connections:
  114.    *
  115.    * Socket 0 (PCMCIA):
  116.    * MAX1602 Lubbock Register
  117.    * Pin Signal
  118.    * ----- ------- ----------------------
  119.    * A0VPP S0_PWR0 SA-1111 GPIO A<0>
  120.    * A1VPP S0_PWR1 SA-1111 GPIO A<1>
  121.    * A0VCC S0_PWR2 SA-1111 GPIO A<2>
  122.    * A1VCC S0_PWR3 SA-1111 GPIO A<3>
  123.    * VX VCC
  124.    * VY +3.3V
  125.    * 12IN +12V
  126.    * CODE +3.3V Cirrus  Code, CODE = High (VY)
  127.    *
  128.    * Socket 1 (CF):
  129.    * MAX1602 Lubbock Register
  130.    * Pin Signal
  131.    * ----- ------- ----------------------
  132.    * A0VPP GND VPP is not connected
  133.    * A1VPP GND VPP is not connected
  134.    * A0VCC S1_PWR0 MISC_WR<14>
  135.    * A1VCC S1_PWR0 MISC_WR<15>
  136.    * VX VCC
  137.    * VY +3.3V
  138.    * 12IN GND VPP is not connected
  139.    * CODE +3.3V Cirrus  Code, CODE = High (VY)
  140.    *
  141.    */
  142.   switch(configure->sock){
  143.   case 0:
  144.     switch(configure->vcc){
  145.     case 0:
  146.       pccr = (pccr & ~PCCR_S0_FLT);
  147.       gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
  148.       break;
  149.     case 33:
  150.       pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
  151.       gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
  152.       break;
  153.     case 50:
  154.       pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
  155.       gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
  156.       break;
  157.     default:
  158.       printk(KERN_ERR "%s(): unrecognized Vcc %un", __FUNCTION__,
  159.      configure->vcc);
  160.       return -1;
  161.     }
  162.     switch(configure->vpp){
  163.     case 0:
  164.       gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
  165.       break;
  166.     case 120:
  167.       gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
  168.       break;
  169.     default:
  170.       /* REVISIT: I'm not sure about this? Is this correct?
  171.          Is it always safe or do we have potential problems
  172.          with bogus combinations of Vcc and Vpp settings? */
  173.       if(configure->vpp == configure->vcc)
  174.         gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
  175.       else {
  176. printk(KERN_ERR "%s(): unrecognized Vpp %un", __FUNCTION__,
  177.        configure->vpp);
  178. return -1;
  179.       }
  180.     }
  181.     pccr = (configure->reset) ? (pccr | PCCR_S0_RST) : (pccr & ~PCCR_S0_RST);
  182.     break;
  183.   case 1:
  184.     switch(configure->vcc){
  185.     case 0:
  186.       pccr = (pccr & ~PCCR_S1_FLT);
  187.       misc_wr &= ~(GPIO_bit(15) | GPIO_bit(14));
  188.       break;
  189.     case 33:
  190.       pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
  191.       misc_wr = (misc_wr & ~(GPIO_bit(15) | GPIO_bit(14))) |  GPIO_bit(15);
  192.       gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
  193.       break;
  194.     case 50:
  195.       pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
  196.       misc_wr = (misc_wr & ~(GPIO_bit(15) | GPIO_bit(14))) |  GPIO_bit(14);
  197.       break;
  198.     default:
  199.       printk(KERN_ERR "%s(): unrecognized Vcc %un", __FUNCTION__,
  200.      configure->vcc);
  201.       return -1;
  202.     }
  203.     if(configure->vpp!=configure->vcc && configure->vpp!=0){
  204.       printk(KERN_ERR "%s(): CF slot cannot support Vpp %un", __FUNCTION__,
  205.      configure->vpp);
  206.       return -1;
  207.     }
  208.     pccr = (configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
  209.     break;
  210.   default:
  211.     return -1;
  212.   }
  213.   PCCR = pccr;
  214.   LUB_MISC_WR = misc_wr;
  215.   PA_DWR = gpio;
  216.   return 0;
  217. }
  218. struct pcmcia_low_level lubbock_pcmcia_ops = { 
  219.   lubbock_pcmcia_init,
  220.   lubbock_pcmcia_shutdown,
  221.   lubbock_pcmcia_socket_state,
  222.   lubbock_pcmcia_get_irq_info,
  223.   lubbock_pcmcia_configure_socket
  224. };