Merge branch android-common-3.10
[firefly-linux-kernel-4.4.55.git] / drivers / pcmcia / soc_common.c
index 6f1a86b43c606ac5e21b9353363da911cc53c314..a2bc6ee1702e14f2c722b510c304863c7b9d0060 100644 (file)
 ======================================================================*/
 
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
+#include <linux/cpufreq.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
 #include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
-#include <asm/system.h>
 
 #include "soc_common.h"
 
+static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev);
+
 #ifdef CONFIG_PCMCIA_DEBUG
 
 static int pc_debug;
@@ -57,18 +59,25 @@ module_param(pc_debug, int, 0644);
 void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
                      int lvl, const char *fmt, ...)
 {
+       struct va_format vaf;
        va_list args;
        if (pc_debug > lvl) {
-               printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func);
                va_start(args, fmt);
-               vprintk(fmt, args);
+
+               vaf.fmt = fmt;
+               vaf.va = &args;
+
+               printk(KERN_DEBUG "skt%u: %s: %pV", skt->nr, func, &vaf);
+
                va_end(args);
        }
 }
+EXPORT_SYMBOL(soc_pcmcia_debug);
 
 #endif
 
-#define to_soc_pcmcia_socket(x)        container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x)        \
+       container_of(x, struct soc_pcmcia_socket, socket)
 
 static unsigned short
 calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -85,14 +94,105 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt)
        return speed;
 }
 
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+       struct soc_pcmcia_timing *timing)
 {
-       timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
-       timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
-       timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+       timing->io =
+               calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+       timing->mem =
+               calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+       timing->attr =
+               calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
 }
 EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
 
+static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt,
+       unsigned int nr)
+{
+       unsigned int i;
+
+       for (i = 0; i < nr; i++) {
+               if (skt->stat[i].irq)
+                       free_irq(skt->stat[i].irq, skt);
+               if (gpio_is_valid(skt->stat[i].gpio))
+                       gpio_free(skt->stat[i].gpio);
+       }
+
+       if (skt->ops->hw_shutdown)
+               skt->ops->hw_shutdown(skt);
+}
+
+static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+       __soc_pcmcia_hw_shutdown(skt, ARRAY_SIZE(skt->stat));
+}
+
+static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+       int ret = 0, i;
+
+       if (skt->ops->hw_init) {
+               ret = skt->ops->hw_init(skt);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
+               if (gpio_is_valid(skt->stat[i].gpio)) {
+                       int irq;
+
+                       ret = gpio_request_one(skt->stat[i].gpio, GPIOF_IN,
+                                              skt->stat[i].name);
+                       if (ret) {
+                               __soc_pcmcia_hw_shutdown(skt, i);
+                               return ret;
+                       }
+
+                       irq = gpio_to_irq(skt->stat[i].gpio);
+
+                       if (i == SOC_STAT_RDY)
+                               skt->socket.pci_irq = irq;
+                       else
+                               skt->stat[i].irq = irq;
+               }
+
+               if (skt->stat[i].irq) {
+                       ret = request_irq(skt->stat[i].irq,
+                                         soc_common_pcmcia_interrupt,
+                                         IRQF_TRIGGER_NONE,
+                                         skt->stat[i].name, skt);
+                       if (ret) {
+                               if (gpio_is_valid(skt->stat[i].gpio))
+                                       gpio_free(skt->stat[i].gpio);
+                               __soc_pcmcia_hw_shutdown(skt, i);
+                               return ret;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+static void soc_pcmcia_hw_enable(struct soc_pcmcia_socket *skt)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
+               if (skt->stat[i].irq) {
+                       irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_RISING);
+                       irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_BOTH);
+               }
+}
+
+static void soc_pcmcia_hw_disable(struct soc_pcmcia_socket *skt)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
+               if (skt->stat[i].irq)
+                       irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_NONE);
+}
+
 static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
 {
        struct pcmcia_state state;
@@ -100,6 +200,22 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
 
        memset(&state, 0, sizeof(struct pcmcia_state));
 
+       /* Make battery voltage state report 'good' */
+       state.bvd1 = 1;
+       state.bvd2 = 1;
+
+       /* CD is active low by default */
+       if (gpio_is_valid(skt->stat[SOC_STAT_CD].gpio))
+               state.detect = !gpio_get_value(skt->stat[SOC_STAT_CD].gpio);
+
+       /* RDY and BVD are active high by default */
+       if (gpio_is_valid(skt->stat[SOC_STAT_RDY].gpio))
+               state.ready = !!gpio_get_value(skt->stat[SOC_STAT_RDY].gpio);
+       if (gpio_is_valid(skt->stat[SOC_STAT_BVD1].gpio))
+               state.bvd1 = !!gpio_get_value(skt->stat[SOC_STAT_BVD1].gpio);
+       if (gpio_is_valid(skt->stat[SOC_STAT_BVD2].gpio))
+               state.bvd2 = !!gpio_get_value(skt->stat[SOC_STAT_BVD2].gpio);
+
        skt->ops->socket_state(skt, &state);
 
        stat = state.detect  ? SS_DETECT : 0;
@@ -131,8 +247,8 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
  *
  * Convert PCMCIA socket state to our socket configure structure.
  */
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+       struct soc_pcmcia_socket *skt, socket_state_t *state)
 {
        int ret;
 
@@ -144,10 +260,11 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
                 */
                if (skt->irq_state != 1 && state->io_irq) {
                        skt->irq_state = 1;
-                       set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+                       irq_set_irq_type(skt->socket.pci_irq,
+                                        IRQ_TYPE_EDGE_FALLING);
                } else if (skt->irq_state == 1 && state->io_irq == 0) {
                        skt->irq_state = 0;
-                       set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
+                       irq_set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
                }
 
                skt->cs_state = *state;
@@ -174,8 +291,9 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
        debug(skt, 2, "initializing socket\n");
-
-       skt->ops->socket_init(skt);
+       if (skt->ops->socket_init)
+               skt->ops->socket_init(skt);
+       soc_pcmcia_hw_enable(skt);
        return 0;
 }
 
@@ -195,7 +313,9 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
 
        debug(skt, 2, "suspending socket\n");
 
-       skt->ops->socket_suspend(skt);
+       soc_pcmcia_hw_disable(skt);
+       if (skt->ops->socket_suspend)
+               skt->ops->socket_suspend(skt);
 
        return 0;
 }
@@ -298,24 +418,24 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
  * of power configuration, reset, &c. We also record the value of
  * `state' in order to regurgitate it to the PCMCIA core later.
  */
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+       struct pcmcia_socket *sock, socket_state_t *state)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
-       debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
-                       (state->csc_mask==0)?"<NONE> ":"",
-                       (state->csc_mask&SS_DETECT)?"DETECT ":"",
-                       (state->csc_mask&SS_READY)?"READY ":"",
-                       (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-                       (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-                       (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-                       (state->flags==0)?"<NONE> ":"",
-                       (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-                       (state->flags&SS_IOCARD)?"IOCARD ":"",
-                       (state->flags&SS_RESET)?"RESET ":"",
-                       (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-                       (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+       debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+                       (state->csc_mask == 0)          ? "<NONE> " :   "",
+                       (state->csc_mask & SS_DETECT)   ? "DETECT " :   "",
+                       (state->csc_mask & SS_READY)    ? "READY " :    "",
+                       (state->csc_mask & SS_BATDEAD)  ? "BATDEAD " :  "",
+                       (state->csc_mask & SS_BATWARN)  ? "BATWARN " :  "",
+                       (state->csc_mask & SS_STSCHG)   ? "STSCHG " :   "",
+                       (state->flags == 0)             ? "<NONE> " :   "",
+                       (state->flags & SS_PWR_AUTO)    ? "PWR_AUTO " : "",
+                       (state->flags & SS_IOCARD)      ? "IOCARD " :   "",
+                       (state->flags & SS_RESET)       ? "RESET " :    "",
+                       (state->flags & SS_SPKR_ENA)    ? "SPKR_ENA " : "",
+                       (state->flags & SS_OUTPUT_ENA)  ? "OUTPUT_ENA " : "",
                        state->Vcc, state->Vpp, state->io_irq);
 
        return soc_common_pcmcia_config_skt(skt, state);
@@ -330,8 +450,8 @@ soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
  *
  * Returns: 0 on success, -1 on error
  */
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+       struct pcmcia_socket *sock, struct pccard_io_map *map)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
        unsigned short speed = map->speed;
@@ -340,14 +460,14 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
                map->map, map->speed, (unsigned long long)map->start,
                (unsigned long long)map->stop);
        debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-               (map->flags==0)?"<NONE>":"",
-               (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-               (map->flags&MAP_16BIT)?"16BIT ":"",
-               (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-               (map->flags&MAP_0WS)?"0WS ":"",
-               (map->flags&MAP_WRPROT)?"WRPROT ":"",
-               (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-               (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+               (map->flags == 0)               ? "<NONE>"      : "",
+               (map->flags & MAP_ACTIVE)       ? "ACTIVE "     : "",
+               (map->flags & MAP_16BIT)        ? "16BIT "      : "",
+               (map->flags & MAP_AUTOSZ)       ? "AUTOSZ "     : "",
+               (map->flags & MAP_0WS)          ? "0WS "        : "",
+               (map->flags & MAP_WRPROT)       ? "WRPROT "     : "",
+               (map->flags & MAP_USE_WAIT)     ? "USE_WAIT "   : "",
+               (map->flags & MAP_PREFETCH)     ? "PREFETCH "   : "");
 
        if (map->map >= MAX_IO_WIN) {
                printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -384,8 +504,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
  *
  * Returns: 0 on success, -ERRNO on error
  */
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+       struct pcmcia_socket *sock, struct pccard_mem_map *map)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
        struct resource *res;
@@ -394,14 +514,14 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
        debug(skt, 2, "map %u speed %u card_start %08x\n",
                map->map, map->speed, map->card_start);
        debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-               (map->flags==0)?"<NONE>":"",
-               (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-               (map->flags&MAP_16BIT)?"16BIT ":"",
-               (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-               (map->flags&MAP_0WS)?"0WS ":"",
-               (map->flags&MAP_WRPROT)?"WRPROT ":"",
-               (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-               (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+               (map->flags == 0)               ? "<NONE>"      : "",
+               (map->flags & MAP_ACTIVE)       ? "ACTIVE "     : "",
+               (map->flags & MAP_16BIT)        ? "16BIT "      : "",
+               (map->flags & MAP_AUTOSZ)       ? "AUTOSZ "     : "",
+               (map->flags & MAP_0WS)          ? "0WS "        : "",
+               (map->flags & MAP_WRPROT)       ? "WRPROT "     : "",
+               (map->flags & MAP_ATTRIB)       ? "ATTRIB "     : "",
+               (map->flags & MAP_USE_WAIT)     ? "USE_WAIT "   : "");
 
        if (map->map >= MAX_WIN)
                return -EINVAL;
@@ -456,8 +576,8 @@ static struct bittbl conf_bits[] = {
        { SS_OUTPUT_ENA,        "SS_OUTPUT_ENA" },
 };
 
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+       unsigned int val, struct bittbl *bits, int sz)
 {
        char *b = *p;
        int i;
@@ -475,13 +595,14 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+       struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct soc_pcmcia_socket *skt =
                container_of(dev, struct soc_pcmcia_socket, socket.dev);
        char *p = buf;
 
-       p+=sprintf(p, "slot     : %d\n", skt->nr);
+       p += sprintf(p, "slot     : %d\n", skt->nr);
 
        dump_bits(&p, "status", skt->status,
                  status_bits, ARRAY_SIZE(status_bits));
@@ -490,12 +611,12 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch
        dump_bits(&p, "cs_flags", skt->cs_state.flags,
                  conf_bits, ARRAY_SIZE(conf_bits));
 
-       p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
-       p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
-       p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
+       p += sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
+       p += sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
+       p += sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
                skt->socket.pci_irq);
        if (skt->ops->show_timing)
-               p+=skt->ops->show_timing(skt, p);
+               p += skt->ops->show_timing(skt, p);
 
        return p-buf;
 }
@@ -512,69 +633,6 @@ static struct pccard_operations soc_common_pcmcia_operations = {
 };
 
 
-int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt,
-                           struct pcmcia_irqs *irqs, int nr)
-{
-       int i, res = 0;
-
-       for (i = 0; i < nr; i++) {
-               if (irqs[i].sock != skt->nr)
-                       continue;
-               res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt,
-                                 IRQF_DISABLED, irqs[i].str, skt);
-               if (res)
-                       break;
-               set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
-       }
-
-       if (res) {
-               printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n",
-                       irqs[i].irq, res);
-
-               while (i--)
-                       if (irqs[i].sock == skt->nr)
-                               free_irq(irqs[i].irq, skt);
-       }
-       return res;
-}
-EXPORT_SYMBOL(soc_pcmcia_request_irqs);
-
-void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt,
-                         struct pcmcia_irqs *irqs, int nr)
-{
-       int i;
-
-       for (i = 0; i < nr; i++)
-               if (irqs[i].sock == skt->nr)
-                       free_irq(irqs[i].irq, skt);
-}
-EXPORT_SYMBOL(soc_pcmcia_free_irqs);
-
-void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
-                            struct pcmcia_irqs *irqs, int nr)
-{
-       int i;
-
-       for (i = 0; i < nr; i++)
-               if (irqs[i].sock == skt->nr)
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
-}
-EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
-
-void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
-                           struct pcmcia_irqs *irqs, int nr)
-{
-       int i;
-
-       for (i = 0; i < nr; i++)
-               if (irqs[i].sock == skt->nr) {
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
-                       set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
-               }
-}
-EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
-
-
 static LIST_HEAD(soc_pcmcia_sockets);
 static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
 
@@ -588,7 +646,7 @@ soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
 
        mutex_lock(&soc_pcmcia_sockets_lock);
        list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-               if ( skt->ops->frequency_change )
+               if (skt->ops->frequency_change)
                        ret += skt->ops->frequency_change(skt, val, freqs);
        mutex_unlock(&soc_pcmcia_sockets_lock);
 
@@ -614,12 +672,28 @@ fs_initcall(soc_pcmcia_cpufreq_register);
 
 static void soc_pcmcia_cpufreq_unregister(void)
 {
-       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+               CPUFREQ_TRANSITION_NOTIFIER);
 }
 module_exit(soc_pcmcia_cpufreq_unregister);
 
 #endif
 
+void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt,
+       struct pcmcia_low_level *ops, struct device *dev)
+{
+       int i;
+
+       skt->ops = ops;
+       skt->socket.owner = ops->owner;
+       skt->socket.dev.parent = dev;
+       skt->socket.pci_irq = NO_IRQ;
+
+       for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
+               skt->stat[i].gpio = -EINVAL;
+}
+EXPORT_SYMBOL(soc_pcmcia_init_one);
+
 void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
 {
        mutex_lock(&soc_pcmcia_sockets_lock);
@@ -627,10 +701,9 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
 
        pcmcia_unregister_socket(&skt->socket);
 
-       flush_scheduled_work();
-
-       skt->ops->hw_shutdown(skt);
+       soc_pcmcia_hw_shutdown(skt);
 
+       /* should not be required; violates some lowlevel drivers */
        soc_common_pcmcia_config_skt(skt, &dead_socket);
 
        list_del(&skt->node);
@@ -687,7 +760,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
         */
        skt->ops->set_timing(skt);
 
-       ret = skt->ops->hw_init(skt);
+       ret = soc_pcmcia_hw_init(skt);
        if (ret)
                goto out_err_6;
 
@@ -720,9 +793,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
        pcmcia_unregister_socket(&skt->socket);
 
  out_err_7:
-       flush_scheduled_work();
-
-       skt->ops->hw_shutdown(skt);
+       soc_pcmcia_hw_shutdown(skt);
  out_err_6:
        list_del(&skt->node);
        mutex_unlock(&soc_pcmcia_sockets_lock);