vserver 1.9.3
[linux-2.6.git] / drivers / pcmcia / soc_common.c
index ff8b521..a45fee3 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>
 
 #include "soc_common.h"
 
+/* FIXME: platform dependent resource declaration has to move out of this file */
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #ifdef DEBUG
 
 static int pc_debug;
@@ -446,9 +453,7 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
        skt->ops->set_timing(skt);
 
-       map->sys_stop -= map->sys_start;
-       map->sys_stop += res->start + map->card_start;
-       map->sys_start = res->start + map->card_start;
+       map->static_start = res->start + map->card_start;
 
        return 0;
 }
@@ -614,9 +619,53 @@ 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;
+       struct soc_pcmcia_socket *skt;
        int ret, i;
 
        down(&soc_pcmcia_sockets_lock);
@@ -634,7 +683,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
         * Initialise the per-socket structure.
         */
        for (i = 0; i < nr; i++) {
-               struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+               skt = &sinfo->skt[i];
 
                skt->socket.ops = &soc_common_pcmcia_operations;
                skt->socket.owner = ops->owner;
@@ -692,6 +741,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);
 
                /*
@@ -729,7 +781,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
        goto out;
 
        do {
-               struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+               skt = &sinfo->skt[i];
 
                del_timer_sync(&skt->poll_timer);
                pcmcia_unregister_socket(&skt->socket);
@@ -789,6 +841,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);