linux/drivers/pcmcia/sa1100_simpad.c
<<
>>
Prefs
   1/*
   2 * drivers/pcmcia/sa1100_simpad.c
   3 *
   4 * PCMCIA implementation routines for simpad
   5 *
   6 */
   7#include <linux/module.h>
   8#include <linux/kernel.h>
   9#include <linux/device.h>
  10#include <linux/init.h>
  11
  12#include <mach/hardware.h>
  13#include <asm/mach-types.h>
  14#include <asm/irq.h>
  15#include <mach/simpad.h>
  16#include "sa1100_generic.h"
  17 
  18static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  19{
  20
  21        simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
  22
  23        skt->stat[SOC_STAT_CD].gpio = GPIO_CF_CD;
  24        skt->stat[SOC_STAT_CD].name = "CF_CD";
  25        skt->stat[SOC_STAT_RDY].gpio = GPIO_CF_IRQ;
  26        skt->stat[SOC_STAT_RDY].name = "CF_RDY";
  27
  28        return 0;
  29}
  30
  31static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  32{
  33        /* Disable CF bus: */
  34        /*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
  35        simpad_clear_cs3_bit(PCMCIA_RESET);
  36}
  37
  38static void
  39simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  40                           struct pcmcia_state *state)
  41{
  42        long cs3reg = simpad_get_cs3_ro();
  43
  44        /* the detect signal is inverted - fix that up here */
  45        state->detect = !state->detect;
  46
  47        state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
  48        state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
  49
  50        if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
  51                        (PCMCIA_VS1|PCMCIA_VS2)) {
  52                state->vs_3v=0;
  53                state->vs_Xv=0;
  54        } else {
  55                state->vs_3v=1;
  56                state->vs_Xv=0;
  57        }
  58}
  59
  60static int
  61simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  62                               const socket_state_t *state)
  63{
  64        unsigned long flags;
  65
  66        local_irq_save(flags);
  67
  68        /* Murphy: see table of MIC2562a-1 */
  69        switch (state->Vcc) {
  70        case 0:
  71                simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
  72                break;
  73
  74        case 33:  
  75                simpad_clear_cs3_bit(VCC_3V_EN|EN1);
  76                simpad_set_cs3_bit(VCC_5V_EN|EN0);
  77                break;
  78
  79        case 50:
  80                simpad_clear_cs3_bit(VCC_5V_EN|EN1);
  81                simpad_set_cs3_bit(VCC_3V_EN|EN0);
  82                break;
  83
  84        default:
  85                printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
  86                        __func__, state->Vcc);
  87                simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
  88                local_irq_restore(flags);
  89                return -1;
  90        }
  91
  92
  93        local_irq_restore(flags);
  94
  95        return 0;
  96}
  97
  98static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
  99{
 100        simpad_set_cs3_bit(PCMCIA_RESET);
 101}
 102
 103static struct pcmcia_low_level simpad_pcmcia_ops = { 
 104        .owner                  = THIS_MODULE,
 105        .hw_init                = simpad_pcmcia_hw_init,
 106        .hw_shutdown            = simpad_pcmcia_hw_shutdown,
 107        .socket_state           = simpad_pcmcia_socket_state,
 108        .configure_socket       = simpad_pcmcia_configure_socket,
 109        .socket_suspend         = simpad_pcmcia_socket_suspend,
 110};
 111
 112int pcmcia_simpad_init(struct device *dev)
 113{
 114        int ret = -ENODEV;
 115
 116        if (machine_is_simpad())
 117                ret = sa11xx_drv_pcmcia_probe(dev, &simpad_pcmcia_ops, 1, 1);
 118
 119        return ret;
 120}
 121