Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszer...
[cascardo/linux.git] / drivers / pcmcia / soc_common.c
index d5ca760..153f312 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/cpufreq.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -42,6 +43,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 
@@ -79,6 +81,41 @@ EXPORT_SYMBOL(soc_pcmcia_debug);
 #define to_soc_pcmcia_socket(x)        \
        container_of(x, struct soc_pcmcia_socket, socket)
 
+int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt,
+       struct soc_pcmcia_regulator *r, int v)
+{
+       bool on;
+       int ret;
+
+       if (!r->reg)
+               return 0;
+
+       on = v != 0;
+       if (r->on == on)
+               return 0;
+
+       if (on) {
+               ret = regulator_set_voltage(r->reg, v * 100000, v * 100000);
+               if (ret) {
+                       int vout = regulator_get_voltage(r->reg) / 100000;
+
+                       dev_warn(&skt->socket.dev,
+                                "CS requested %s=%u.%uV, applying %u.%uV\n",
+                                r == &skt->vcc ? "Vcc" : "Vpp",
+                                v / 10, v % 10, vout / 10, vout % 10);
+               }
+
+               ret = regulator_enable(r->reg);
+       } else {
+               regulator_disable(r->reg);
+       }
+       if (ret == 0)
+               r->on = on;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(soc_pcmcia_regulator_set);
+
 static unsigned short
 calc_speed(unsigned short *spds, int num, unsigned short dflt)
 {
@@ -111,12 +148,9 @@ static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt,
 {
        unsigned int i;
 
-       for (i = 0; i < nr; 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);
@@ -129,6 +163,30 @@ static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
        __soc_pcmcia_hw_shutdown(skt, ARRAY_SIZE(skt->stat));
 }
 
+int soc_pcmcia_request_gpiods(struct soc_pcmcia_socket *skt)
+{
+       struct device *dev = skt->socket.dev.parent;
+       struct gpio_desc *desc;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
+               if (!skt->stat[i].name)
+                       continue;
+
+               desc = devm_gpiod_get(dev, skt->stat[i].name, GPIOD_IN);
+               if (IS_ERR(desc)) {
+                       dev_err(dev, "Failed to get GPIO for %s: %ld\n",
+                               skt->stat[i].name, PTR_ERR(desc));
+                       return PTR_ERR(desc);
+               }
+
+               skt->stat[i].desc = desc;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(soc_pcmcia_request_gpiods);
+
 static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
        int ret = 0, i;
@@ -143,21 +201,32 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 
        for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
                if (gpio_is_valid(skt->stat[i].gpio)) {
-                       int irq;
+                       unsigned long flags = GPIOF_IN;
 
-                       ret = gpio_request_one(skt->stat[i].gpio, GPIOF_IN,
-                                              skt->stat[i].name);
+                       /* CD is active low by default */
+                       if (i == SOC_STAT_CD)
+                               flags |= GPIOF_ACTIVE_LOW;
+
+                       ret = devm_gpio_request_one(skt->socket.dev.parent,
+                                                   skt->stat[i].gpio, flags,
+                                                   skt->stat[i].name);
                        if (ret) {
                                __soc_pcmcia_hw_shutdown(skt, i);
                                return ret;
                        }
 
-                       irq = gpio_to_irq(skt->stat[i].gpio);
+                       skt->stat[i].desc = gpio_to_desc(skt->stat[i].gpio);
+               }
+
+               if (i < SOC_STAT_VS1 && skt->stat[i].desc) {
+                       int irq = gpiod_to_irq(skt->stat[i].desc);
 
-                       if (i == SOC_STAT_RDY)
-                               skt->socket.pci_irq = irq;
-                       else
-                               skt->stat[i].irq = irq;
+                       if (irq > 0) {
+                               if (i == SOC_STAT_RDY)
+                                       skt->socket.pci_irq = irq;
+                               else
+                                       skt->stat[i].irq = irq;
+                       }
                }
 
                if (skt->stat[i].irq) {
@@ -166,8 +235,6 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
                                          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;
                        }
@@ -197,6 +264,18 @@ static void soc_pcmcia_hw_disable(struct soc_pcmcia_socket *skt)
                        irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_NONE);
 }
 
+/*
+ * The CF 3.0 specification says that cards tie VS1 to ground and leave
+ * VS2 open.  Many implementations do not wire up the VS signals, so we
+ * provide hard-coded values as per the CF 3.0 spec.
+ */
+void soc_common_cf_socket_state(struct soc_pcmcia_socket *skt,
+       struct pcmcia_state *state)
+{
+       state->vs_3v = 1;
+}
+EXPORT_SYMBOL_GPL(soc_common_cf_socket_state);
+
 static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
 {
        struct pcmcia_state state;
@@ -208,17 +287,18 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
        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);
+       if (skt->stat[SOC_STAT_CD].desc)
+               state.detect = !!gpiod_get_value(skt->stat[SOC_STAT_CD].desc);
+       if (skt->stat[SOC_STAT_RDY].desc)
+               state.ready = !!gpiod_get_value(skt->stat[SOC_STAT_RDY].desc);
+       if (skt->stat[SOC_STAT_BVD1].desc)
+               state.bvd1 = !!gpiod_get_value(skt->stat[SOC_STAT_BVD1].desc);
+       if (skt->stat[SOC_STAT_BVD2].desc)
+               state.bvd2 = !!gpiod_get_value(skt->stat[SOC_STAT_BVD2].desc);
+       if (skt->stat[SOC_STAT_VS1].desc)
+               state.vs_3v = !!gpiod_get_value(skt->stat[SOC_STAT_VS1].desc);
+       if (skt->stat[SOC_STAT_VS2].desc)
+               state.vs_Xv = !!gpiod_get_value(skt->stat[SOC_STAT_VS2].desc);
 
        skt->ops->socket_state(skt, &state);
 
@@ -257,7 +337,30 @@ static int soc_common_pcmcia_config_skt(
        int ret;
 
        ret = skt->ops->configure_socket(skt, state);
+       if (ret < 0) {
+               pr_err("soc_common_pcmcia: unable to configure socket %d\n",
+                      skt->nr);
+               /* restore the previous state */
+               WARN_ON(skt->ops->configure_socket(skt, &skt->cs_state));
+               return ret;
+       }
+
        if (ret == 0) {
+               struct gpio_desc *descs[2];
+               int values[2], n = 0;
+
+               if (skt->gpio_reset) {
+                       descs[n] = skt->gpio_reset;
+                       values[n++] = !!(state->flags & SS_RESET);
+               }
+               if (skt->gpio_bus_enable) {
+                       descs[n] = skt->gpio_bus_enable;
+                       values[n++] = !!(state->flags & SS_OUTPUT_ENA);
+               }
+
+               if (n)
+                       gpiod_set_array_value_cansleep(n, descs, values);
+
                /*
                 * This really needs a better solution.  The IRQ
                 * may or may not be claimed by the driver.
@@ -274,10 +377,6 @@ static int soc_common_pcmcia_config_skt(
                skt->cs_state = *state;
        }
 
-       if (ret < 0)
-               printk(KERN_ERR "soc_common_pcmcia: unable to configure "
-                      "socket %d\n", skt->nr);
-
        return ret;
 }
 
@@ -637,54 +736,19 @@ static struct pccard_operations soc_common_pcmcia_operations = {
 };
 
 
-static LIST_HEAD(soc_pcmcia_sockets);
-static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
-
 #ifdef CONFIG_CPU_FREQ
-static int
-soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
+static int soc_common_pcmcia_cpufreq_nb(struct notifier_block *nb,
+       unsigned long val, void *data)
 {
-       struct soc_pcmcia_socket *skt;
+       struct soc_pcmcia_socket *skt = container_of(nb, struct soc_pcmcia_socket, cpufreq_nb);
        struct cpufreq_freqs *freqs = data;
-       int ret = 0;
-
-       mutex_lock(&soc_pcmcia_sockets_lock);
-       list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-               if (skt->ops->frequency_change)
-                       ret += skt->ops->frequency_change(skt, val, freqs);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
-       return ret;
-}
-
-static struct notifier_block soc_pcmcia_notifier_block = {
-       .notifier_call  = soc_pcmcia_notifier
-};
-
-static int soc_pcmcia_cpufreq_register(void)
-{
-       int ret;
 
-       ret = cpufreq_register_notifier(&soc_pcmcia_notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
-       if (ret < 0)
-               printk(KERN_ERR "Unable to register CPU frequency change "
-                               "notifier for PCMCIA (%d)\n", ret);
-       return ret;
+       return skt->ops->frequency_change(skt, val, freqs);
 }
-fs_initcall(soc_pcmcia_cpufreq_register);
-
-static void soc_pcmcia_cpufreq_unregister(void)
-{
-       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)
+       const struct pcmcia_low_level *ops, struct device *dev)
 {
        int i;
 
@@ -700,19 +764,21 @@ EXPORT_SYMBOL(soc_pcmcia_init_one);
 
 void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
 {
-       mutex_lock(&soc_pcmcia_sockets_lock);
        del_timer_sync(&skt->poll_timer);
 
        pcmcia_unregister_socket(&skt->socket);
 
+#ifdef CONFIG_CPU_FREQ
+       if (skt->ops->frequency_change)
+               cpufreq_unregister_notifier(&skt->cpufreq_nb,
+                                           CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
        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);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
        iounmap(skt->virt_io);
        skt->virt_io = NULL;
        release_resource(&skt->res_attr);
@@ -726,6 +792,8 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 {
        int ret;
 
+       skt->cs_state = dead_socket;
+
        setup_timer(&skt->poll_timer, soc_common_pcmcia_poll_event,
                    (unsigned long)skt);
        skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
@@ -752,10 +820,6 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
                goto out_err_5;
        }
 
-       mutex_lock(&soc_pcmcia_sockets_lock);
-
-       list_add(&skt->node, &soc_pcmcia_sockets);
-
        /*
         * We initialize default socket timing here, because
         * we are not guaranteed to see a SetIOMap operation at
@@ -776,14 +840,23 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 
        skt->status = soc_common_pcmcia_skt_state(skt);
 
+#ifdef CONFIG_CPU_FREQ
+       if (skt->ops->frequency_change) {
+               skt->cpufreq_nb.notifier_call = soc_common_pcmcia_cpufreq_nb;
+
+               ret = cpufreq_register_notifier(&skt->cpufreq_nb,
+                                               CPUFREQ_TRANSITION_NOTIFIER);
+               if (ret < 0)
+                       dev_err(skt->socket.dev.parent,
+                               "unable to register CPU frequency change notifier for PCMCIA (%d)\n",
+                               ret);
+       }
+#endif
+
        ret = pcmcia_register_socket(&skt->socket);
        if (ret)
                goto out_err_7;
 
-       add_timer(&skt->poll_timer);
-
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
        ret = device_create_file(&skt->socket.dev, &dev_attr_status);
        if (ret)
                goto out_err_8;
@@ -791,15 +864,12 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
        return ret;
 
  out_err_8:
-       mutex_lock(&soc_pcmcia_sockets_lock);
        del_timer_sync(&skt->poll_timer);
        pcmcia_unregister_socket(&skt->socket);
 
  out_err_7:
        soc_pcmcia_hw_shutdown(skt);
  out_err_6:
-       list_del(&skt->node);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
        iounmap(skt->virt_io);
  out_err_5:
        release_resource(&skt->res_attr);