X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpcmcia%2Fsoc_common.c;h=ea7d9ca160b2810ccfe7da19a494f99521cfda4f;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=ff8b52124f66f8fb9b05ab5f2f9cdc6da0f1e2e4;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index ff8b52124..ea7d9ca16 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -31,6 +31,7 @@ ======================================================================*/ +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -47,6 +49,11 @@ #include "soc_common.h" +/* FIXME: platform dependent resource declaration has to move out of this file */ +#ifdef CONFIG_ARCH_PXA +#include +#endif + #ifdef DEBUG static int pc_debug; @@ -59,7 +66,7 @@ void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, if (pc_debug > lvl) { printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func); va_start(args, fmt); - printk(fmt, args); + vprintk(fmt, args); va_end(args); } } @@ -190,18 +197,15 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock) static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock) { struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - int ret; debug(skt, 2, "suspending socket\n"); - ret = soc_common_pcmcia_config_skt(skt, &dead_socket); - if (ret == 0) - skt->ops->socket_suspend(skt); + skt->ops->socket_suspend(skt); - return ret; + return 0; } -static spinlock_t status_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(status_lock); static void soc_common_check_status(struct soc_pcmcia_socket *skt) { @@ -292,33 +296,12 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) } -/* - * Implements the get_socket() operation for the in-kernel PCMCIA - * service (formerly SS_GetSocket in Card Services). Not a very - * exciting routine. - * - * Returns: 0 - */ -static int -soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) -{ - struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - - debug(skt, 2, "\n"); - - *state = skt->cs_state; - - return 0; -} - /* * Implements the set_socket() operation for the in-kernel PCMCIA * service (formerly SS_SetSocket in Card Services). We more or * less punt all of this work and let the kernel handle the details * of power configuration, reset, &c. We also record the value of * `state' in order to regurgitate it to the PCMCIA core later. - * - * Returns: 0 */ static int soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) @@ -390,8 +373,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m map->stop = PAGE_SIZE-1; map->stop -= map->start; - map->stop += (unsigned long)skt->virt_io; - map->start = (unsigned long)skt->virt_io; + map->stop += skt->socket.io_offset; + map->start = skt->socket.io_offset; return 0; } @@ -403,7 +386,7 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m * the map speed as requested, but override the address ranges * supplied by Card Services. * - * Returns: 0 on success, -1 on error + * Returns: 0 on success, -ERRNO on error */ static int soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) @@ -446,9 +429,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; } @@ -528,7 +509,6 @@ static struct pccard_operations soc_common_pcmcia_operations = { .init = soc_common_pcmcia_sock_init, .suspend = soc_common_pcmcia_suspend, .get_status = soc_common_pcmcia_get_status, - .get_socket = soc_common_pcmcia_get_socket, .set_socket = soc_common_pcmcia_set_socket, .set_io_map = soc_common_pcmcia_set_io_map, .set_mem_map = soc_common_pcmcia_set_mem_map, @@ -614,27 +594,70 @@ 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 +static int soc_pcmcia_cpufreq_register(void) { return 0; } +static void soc_pcmcia_cpufreq_unregister(void) {} +#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); - sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); + sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); if (!sinfo) { ret = -ENOMEM; goto out; } - memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr)); sinfo->nskt = nr; /* * 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 +715,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); /* @@ -706,6 +732,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops goto out_err_6; skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; + skt->socket.resource_ops = &pccard_static_ops; skt->socket.irq_mask = 0; skt->socket.map_size = PAGE_SIZE; skt->socket.pci_irq = skt->irq; @@ -729,7 +756,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 +816,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);