patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / pcmcia / soc_common.c
index ff8b521..6d393e7 100644 (file)
@@ -31,6 +31,7 @@
 ======================================================================*/
 
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -39,6 +40,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -614,6 +616,49 @@ struct skt_dev_info {
 #define SKT_DEV_INFO_SIZE(n) \
        (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
 
+#ifdef CONFIG_CPU_FREQ
+static int
+soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+       struct soc_pcmcia_socket *skt;
+       struct cpufreq_freqs *freqs = data;
+       int ret = 0;
+
+       down(&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);
+       up(&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;
+}
+
+static void soc_pcmcia_cpufreq_unregister(void)
+{
+       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+#define soc_pcmcia_cpufreq_register()
+#define soc_pcmcia_cpufreq_unregister()
+#endif
+
 int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
 {
        struct skt_dev_info *sinfo;
@@ -692,6 +737,9 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
                        goto out_err_5;
                }
 
+               if ( list_empty(&soc_pcmcia_sockets) )
+                       soc_pcmcia_cpufreq_register();
+
                list_add(&skt->node, &soc_pcmcia_sockets);
 
                /*
@@ -789,6 +837,9 @@ int soc_common_drv_pcmcia_remove(struct device *dev)
                release_resource(&skt->res_io);
                release_resource(&skt->res_skt);
        }
+       if ( list_empty(&soc_pcmcia_sockets) )
+               soc_pcmcia_cpufreq_unregister();
+
        up(&soc_pcmcia_sockets_lock);
 
        kfree(sinfo);