]> git.hungrycats.org Git - linux/commitdiff
[ARM] SA11x0 PCMCIA 1
authorRussell King <rmk@flint.arm.linux.org.uk>
Sun, 2 Mar 2003 19:32:19 +0000 (19:32 +0000)
committerRussell King <rmk@flint.arm.linux.org.uk>
Sun, 2 Mar 2003 19:32:19 +0000 (19:32 +0000)
Make SA11x0 generic pcmcia implementation fit better with Dominik's
work - pass around our socket structure rather than the socket number
itself.  Reference socket operations using the socket structure
rather than a static variable.

drivers/pcmcia/sa1100.h
drivers/pcmcia/sa1100_generic.c

index 53716e9dcf63577cf072c288fb6b241046dada2b..6bc54de53d2d3dd5bbc9812fc9f23495a5529d38 100644 (file)
@@ -150,6 +150,7 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
  */
 #define SA1100_PCMCIA_POLL_PERIOD    (2*HZ)
 
+struct pcmcia_low_level;
 
 /* This structure encapsulates per-socket state which we might need to
  * use when responding to a Card Services query of some kind.
@@ -158,6 +159,7 @@ struct sa1100_pcmcia_socket {
   /*
    * Core PCMCIA state
    */
+  int                  nr;
   socket_state_t        cs_state;
   pccard_io_map         io_map[MAX_IO_WIN];
   pccard_mem_map        pc_mem_map[MAX_WIN];
@@ -173,6 +175,7 @@ struct sa1100_pcmcia_socket {
    * Info from low level handler
    */
   unsigned int          irq;
+  struct pcmcia_low_level *ops;
 };
 
 
index e071bb184ced47f4dc6901c3bcf1d3de9dcfeaca..9fe899279d9608a89a5d59228543b69f39a3bcf1 100644 (file)
@@ -110,59 +110,76 @@ sa1100_pcmcia_default_mecr_timing(unsigned int sock, unsigned int cpu_speed,
  * Call board specific BS value calculation to allow boards
  * to tweak the BS values.
  */
-static int sa1100_pcmcia_set_mecr(int sock, unsigned int cpu_clock)
+static int
+sa1100_pcmcia_set_mecr(struct sa1100_pcmcia_socket *skt, unsigned int cpu_clock)
 {
-       struct sa1100_pcmcia_socket *skt;
        u32 mecr;
        unsigned long flags;
        unsigned int bs;
 
-       if (sock < 0 || sock > SA1100_PCMCIA_MAX_SOCK)
-               return -1;
-
-       skt = PCMCIA_SOCKET(sock);
-
        local_irq_save(flags);
 
-       bs = pcmcia_low_level->socket_get_timing(sock, cpu_clock, skt->speed_io);
+       bs = skt->ops->socket_get_timing(skt->nr, cpu_clock, skt->speed_io);
 
        mecr = MECR;
-       MECR_FAST_SET(mecr, sock, 0);
-       MECR_BSIO_SET(mecr, sock, bs );
-       MECR_BSA_SET(mecr, sock, bs );
-       MECR_BSM_SET(mecr, sock, bs );
+       MECR_FAST_SET(mecr, skt->nr, 0);
+       MECR_BSIO_SET(mecr, skt->nr, bs );
+       MECR_BSA_SET(mecr, skt->nr, bs );
+       MECR_BSM_SET(mecr, skt->nr, bs );
        MECR = mecr;
 
        local_irq_restore(flags);
 
-       DEBUG(4, "%s(): FAST%u %X  BSM%u %X  BSA%u %X  BSIO%u %X\n",
-             __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
-             MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
-             sock, MECR_BSIO_GET(mecr, sock));
+       DEBUG(4, "%s(): sock %u FAST %X  BSM %X  BSA %X  BSIO %X\n",
+             __FUNCTION__, skt->nr, MECR_FAST_GET(mecr, skt->nr),
+             MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr),
+             MECR_BSIO_GET(mecr, skt->nr));
 
        return 0;
 }
 
 /*
- * sa1100_pcmcia_state_to_config
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * sa1100_pcmcia_config_skt
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
  *
  * Convert PCMCIA socket state to our socket configure structure.
  */
-static struct pcmcia_configure
-sa1100_pcmcia_state_to_config(unsigned int sock, socket_state_t *state)
+static int
+sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state)
 {
-  struct pcmcia_configure conf;
+       struct pcmcia_configure conf;
+       int ret;
+
+       conf.sock    = skt->nr;
+       conf.vcc     = state->Vcc;
+       conf.vpp     = state->Vpp;
+       conf.output  = state->flags & SS_OUTPUT_ENA ? 1 : 0;
+       conf.speaker = state->flags & SS_SPKR_ENA ? 1 : 0;
+       conf.reset   = state->flags & SS_RESET ? 1 : 0;
+       conf.irq     = state->io_irq != 0;
+
+       ret = skt->ops->configure_socket(&conf);
+       if (ret == 0) {
+               /*
+                * This really needs a better solution.  The IRQ
+                * may or may not be claimed by the driver.
+                */
+               if (skt->irq_state != 1 && state->io_irq) {
+                       skt->irq_state = 1;
+                       set_irq_type(skt->irq, IRQT_FALLING);
+               } else if (skt->irq_state == 1 && state->io_irq == 0) {
+                       skt->irq_state = 0;
+                       set_irq_type(skt->irq, IRQT_NOEDGE);
+               }
+
+               skt->cs_state = *state;
+       }
 
-  conf.sock    = sock;
-  conf.vcc     = state->Vcc;
-  conf.vpp     = state->Vpp;
-  conf.output  = state->flags & SS_OUTPUT_ENA ? 1 : 0;
-  conf.speaker = state->flags & SS_SPKR_ENA ? 1 : 0;
-  conf.reset   = state->flags & SS_RESET ? 1 : 0;
-  conf.irq     = state->io_irq != 0;
+       if (ret < 0)
+               printk(KERN_ERR "sa1100_pcmcia: unable to configure "
+                      "socket %d\n", skt->nr);
 
-  return conf;
+       return ret;
 }
 
 /* sa1100_pcmcia_sock_init()
@@ -177,17 +194,12 @@ sa1100_pcmcia_state_to_config(unsigned int sock, socket_state_t *state)
 static int sa1100_pcmcia_sock_init(unsigned int sock)
 {
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
-  struct pcmcia_configure conf;
 
   DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
 
-  skt->cs_state = dead_socket;
+  sa1100_pcmcia_config_skt(skt, &dead_socket);
 
-  conf = sa1100_pcmcia_state_to_config(sock, &dead_socket);
-
-  pcmcia_low_level->configure_socket(&conf);
-
-  return pcmcia_low_level->socket_init(sock);
+  return skt->ops->socket_init(skt->nr);
 }
 
 
@@ -203,19 +215,14 @@ static int sa1100_pcmcia_sock_init(unsigned int sock)
 static int sa1100_pcmcia_suspend(unsigned int sock)
 {
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
-  struct pcmcia_configure conf;
   int ret;
 
-  DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
-
-  conf = sa1100_pcmcia_state_to_config(sock, &dead_socket);
+  DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, skt->nr);
 
-  ret = pcmcia_low_level->configure_socket(&conf);
+  ret = sa1100_pcmcia_config_skt(skt, &dead_socket);
 
-  if (ret == 0) {
-    skt->cs_state = dead_socket;
-    ret = pcmcia_low_level->socket_suspend(sock);
-  }
+  if (ret == 0)
+    ret = skt->ops->socket_suspend(skt->nr);
 
   return ret;
 }
@@ -427,7 +434,7 @@ sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
   int ret = -1;
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   if (sock < sa1100_pcmcia_socket_count) {
     cap->features  = SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
@@ -467,7 +474,7 @@ sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status)
   struct pcmcia_state_array state_array;
   unsigned int stat;
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   state_array.size = sa1100_pcmcia_socket_count;
   state_array.state = state;
@@ -530,7 +537,7 @@ sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
 {
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   *state = skt->cs_state;
 
@@ -551,9 +558,8 @@ static int
 sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
 {
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
-  struct pcmcia_configure conf;
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   DEBUG(3, "\tmask:  %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n",
        (state->csc_mask==0)?"<NONE>":"",
@@ -571,16 +577,7 @@ sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
   DEBUG(3, "\tVcc %d  Vpp %d  irq %d\n",
        state->Vcc, state->Vpp, state->io_irq);
 
-  conf = sa1100_pcmcia_state_to_config(sock, state);
-
-  if (pcmcia_low_level->configure_socket(&conf) < 0) {
-    printk(KERN_ERR "sa1100_pcmcia: unable to configure socket %d\n", sock);
-    return -1;
-  }
-
-  skt->cs_state = *state;
-  
-  return 0;
+  return sa1100_pcmcia_config_skt(skt, state);
 }  /* sa1100_pcmcia_set_socket() */
 
 
@@ -623,7 +620,7 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
 {
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   DEBUG(3, "\tmap %u  speed %u\n\tstart 0x%08x  stop 0x%08x\n",
        map->map, map->speed, map->start, map->stop);
@@ -647,7 +644,7 @@ sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
     if ( map->speed == 0)
        map->speed = SA1100_PCMCIA_IO_ACCESS;
 
-       sa1100_pcmcia_set_mecr(sock, cpufreq_get(0));
+       sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
   }
 
   if (map->stop == 1)
@@ -704,7 +701,7 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
   struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
   unsigned long start;
 
-  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
+  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, skt->nr);
 
   DEBUG(3, "\tmap %u speed %u sys_start %08lx sys_stop %08lx card_start %08x\n",
        map->map, map->speed, map->sys_start, map->sys_stop, map->card_start);
@@ -736,7 +733,7 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
                          map->speed = SA1100_PCMCIA_5V_MEM_ACCESS;
          }
 
-         sa1100_pcmcia_set_mecr(sock, cpufreq_get(0));
+         sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
 
   }
 
@@ -767,9 +764,8 @@ static int
 sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
                          int count, int *eof, void *data)
 {
-  unsigned int sock = (unsigned int)data;
+  struct sa1100_pcmcia_socket *skt = data;
   unsigned int clock = cpufreq_get(0);
-  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
   unsigned long mecr = MECR;
   char *p = buf;
 
@@ -815,13 +811,13 @@ sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
   p+=sprintf(p, "IRQ      : %d\n", skt->cs_state.io_irq);
 
   p+=sprintf(p, "I/O      : %u (%u)\n", skt->speed_io,
-            sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, sock)));
+            sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr)));
 
   p+=sprintf(p, "attribute: %u (%u)\n", skt->speed_attr,
-            sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, sock)));
+            sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr)));
 
   p+=sprintf(p, "common   : %u (%u)\n", skt->speed_mem,
-            sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, sock)));
+            sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr)));
 
   return p-buf;
 }
@@ -846,7 +842,7 @@ sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
   }
 
   entry->read_proc = sa1100_pcmcia_proc_status;
-  entry->data = (void *)sock;
+  entry->data = PCMCIA_SOCKET(sock);
 }
 
 #endif  /* defined(CONFIG_PROC_FS) */
@@ -881,8 +877,10 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock)
 {
        unsigned int sock;
 
-       for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock)
-               sa1100_pcmcia_set_mecr(sock, clock);
+       for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) {
+               struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+               sa1100_pcmcia_set_mecr(skt, clock);
+       }
 }
 
 /* sa1100_pcmcia_notifier()
@@ -956,8 +954,8 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
         * set default MECR calculation if the board specific
         * code did not specify one...
         */
-       if (!pcmcia_low_level->socket_get_timing)
-               pcmcia_low_level->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
+       if (!ops->socket_get_timing)
+               ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
 
        pcmcia_init.handler = sa1100_pcmcia_interrupt;
        ret = ops->init(&pcmcia_init);
@@ -1002,6 +1000,8 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
                if (ret < 0)
                        printk(KERN_ERR "Unable to get IRQ for socket %u (%d)\n", i, ret);
 
+               skt->nr         = i;
+               skt->ops        = ops;
                skt->irq        = irq_info.irq;
                skt->k_state    = state[i];
                skt->speed_io   = SA1100_PCMCIA_IO_ACCESS;
@@ -1016,7 +1016,7 @@ int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
                        goto out_err;
                }
 
-               sa1100_pcmcia_set_mecr(i, cpu_clock);
+               sa1100_pcmcia_set_mecr(skt, cpu_clock);
        }