X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpcmcia%2Fsoc_common.c;fp=drivers%2Fpcmcia%2Fsa11xx_core.c;h=ff8b52124f66f8fb9b05ab5f2f9cdc6da0f1e2e4;hb=86090fcac5e27b630656fe3d963a6b80e26dac44;hp=d7249c033ec8329861ec7c7d9356de0310bc51a3;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/soc_common.c similarity index 56% rename from drivers/pcmcia/sa11xx_core.c rename to drivers/pcmcia/soc_common.c index d7249c033..ff8b52124 100644 --- a/drivers/pcmcia/sa11xx_core.c +++ b/drivers/pcmcia/soc_common.c @@ -1,7 +1,7 @@ /*====================================================================== - Device driver for the PCMCIA control functionality of StrongARM - SA-1100 microprocessors. + Common support code for the PCMCIA control functionality of + integrated SOCs like the SA-11x0 and PXA2xx microprocessors. The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -27,23 +27,16 @@ and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - + ======================================================================*/ -/* - * Please see linux/Documentation/arm/SA1100/PCMCIA for more information - * on the low-level kernel interface. - */ + #include #include #include -#include -#include -#include #include #include #include -#include #include #include @@ -52,46 +45,28 @@ #include #include -#include "sa11xx_core.h" -#include "sa1100.h" +#include "soc_common.h" #ifdef DEBUG -static int pc_debug; +static int pc_debug; module_param(pc_debug, int, 0644); -#define debug(skt, lvl, fmt, arg...) do { \ - if (pc_debug > (lvl)) \ - printk(KERN_DEBUG "skt%u: %s: " fmt, \ - (skt)->nr, __func__ , ## arg); \ -} while (0) +void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, + int lvl, const char *fmt, ...) +{ + va_list args; + if (pc_debug > lvl) { + printk(KERN_DEBUG "skt%u: %s: ", skt->nr, func); + va_start(args, fmt); + printk(fmt, args); + va_end(args); + } +} -#else -#define debug(skt, lvl, fmt, arg...) do { } while (0) #endif -#define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket) - -/* - * sa1100_pcmcia_default_mecr_timing - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * Calculate MECR clock wait states for given CPU clock - * speed and command wait state. This function can be over- - * written by a board specific version. - * - * The default is to simply calculate the BS values as specified in - * the INTEL SA1100 development manual - * "Expansion Memory (PCMCIA) Configuration Register (MECR)" - * that's section 10.2.5 in _my_ version of the manual ;) - */ -static unsigned int -sa1100_pcmcia_default_mecr_timing(struct sa1100_pcmcia_socket *skt, - unsigned int cpu_speed, - unsigned int cmd_time) -{ - return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed); -} +#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) @@ -108,52 +83,15 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt) return speed; } -/* sa1100_pcmcia_set_mecr() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * - * set MECR value for socket based on this sockets - * io, mem and attribute space access speed. - * Call board specific BS value calculation to allow boards - * to tweak the BS values. - */ -static int -sa1100_pcmcia_set_mecr(struct sa1100_pcmcia_socket *skt, unsigned int cpu_clock) +void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing) { - u32 mecr, old_mecr; - unsigned long flags; - unsigned short speed; - unsigned int bs_io, bs_mem, bs_attr; - - speed = calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS); - bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed); - - speed = calc_speed(skt->spd_mem, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS); - bs_mem = skt->ops->socket_get_timing(skt, cpu_clock, speed); - - speed = calc_speed(skt->spd_attr, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS); - bs_attr = skt->ops->socket_get_timing(skt, cpu_clock, speed); - - local_irq_save(flags); - - old_mecr = mecr = MECR; - MECR_FAST_SET(mecr, skt->nr, 0); - MECR_BSIO_SET(mecr, skt->nr, bs_io); - MECR_BSA_SET(mecr, skt->nr, bs_attr); - MECR_BSM_SET(mecr, skt->nr, bs_mem); - if (old_mecr != mecr) - MECR = mecr; - - local_irq_restore(flags); - - debug(skt, 2, "FAST %X BSM %X BSA %X BSIO %X\n", - MECR_FAST_GET(mecr, skt->nr), - MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr), - MECR_BSIO_GET(mecr, skt->nr)); - - return 0; + 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 unsigned int sa1100_pcmcia_skt_state(struct sa1100_pcmcia_socket *skt) +static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) { struct pcmcia_state state; unsigned int stat; @@ -186,13 +124,13 @@ static unsigned int sa1100_pcmcia_skt_state(struct sa1100_pcmcia_socket *skt) } /* - * sa1100_pcmcia_config_skt - * ^^^^^^^^^^^^^^^^^^^^^^^^ + * soc_common_pcmcia_config_skt + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * Convert PCMCIA socket state to our socket configure structure. */ static int -sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state) +soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state) { int ret; @@ -214,14 +152,14 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state } if (ret < 0) - printk(KERN_ERR "sa1100_pcmcia: unable to configure " + printk(KERN_ERR "soc_common_pcmcia: unable to configure " "socket %d\n", skt->nr); return ret; } -/* sa1100_pcmcia_sock_init() - * ^^^^^^^^^^^^^^^^^^^^^^^^^ +/* soc_common_pcmcia_sock_init() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * (Re-)Initialise the socket, turning on status interrupts * and PCMCIA bus. This must wait for power to stabilise @@ -229,9 +167,9 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state * * Returns: 0 */ -static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock) +static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); debug(skt, 2, "initializing socket\n"); @@ -241,22 +179,22 @@ static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock) /* - * sa1100_pcmcia_suspend() - * ^^^^^^^^^^^^^^^^^^^^^^^ + * soc_common_pcmcia_suspend() + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * Remove power on the socket, disable IRQs from the card. * Turn off status interrupts, and disable the PCMCIA bus. * * Returns: 0 */ -static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock) +static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); int ret; debug(skt, 2, "suspending socket\n"); - ret = sa1100_pcmcia_config_skt(skt, &dead_socket); + ret = soc_common_pcmcia_config_skt(skt, &dead_socket); if (ret == 0) skt->ops->socket_suspend(skt); @@ -265,10 +203,7 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock) static spinlock_t status_lock = SPIN_LOCK_UNLOCKED; -/* sa1100_check_status() - * ^^^^^^^^^^^^^^^^^^^^^ - */ -static void sa1100_check_status(struct sa1100_pcmcia_socket *skt) +static void soc_common_check_status(struct soc_pcmcia_socket *skt) { unsigned int events; @@ -278,7 +213,7 @@ static void sa1100_check_status(struct sa1100_pcmcia_socket *skt) unsigned int status; unsigned long flags; - status = sa1100_pcmcia_skt_state(skt); + status = soc_common_pcmcia_skt_state(skt); spin_lock_irqsave(&status_lock, flags); events = (status ^ skt->status) & skt->cs_state.csc_mask; @@ -298,45 +233,40 @@ static void sa1100_check_status(struct sa1100_pcmcia_socket *skt) } while (events); } -/* sa1100_pcmcia_poll_event() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Let's poll for events in addition to IRQs since IRQ only is unreliable... - */ -static void sa1100_pcmcia_poll_event(unsigned long dummy) +/* Let's poll for events in addition to IRQs since IRQ only is unreliable... */ +static void soc_common_pcmcia_poll_event(unsigned long dummy) { - struct sa1100_pcmcia_socket *skt = (struct sa1100_pcmcia_socket *)dummy; + struct soc_pcmcia_socket *skt = (struct soc_pcmcia_socket *)dummy; debug(skt, 4, "polling for events\n"); - mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD); + mod_timer(&skt->poll_timer, jiffies + SOC_PCMCIA_POLL_PERIOD); - sa1100_check_status(skt); + soc_common_check_status(skt); } -/* sa1100_pcmcia_interrupt() - * ^^^^^^^^^^^^^^^^^^^^^^^^^ +/* * Service routine for socket driver interrupts (requested by the - * low-level PCMCIA init() operation via sa1100_pcmcia_thread()). + * low-level PCMCIA init() operation via soc_common_pcmcia_thread()). * The actual interrupt-servicing work is performed by - * sa1100_pcmcia_thread(), largely because the Card Services event- + * soc_common_pcmcia_thread(), largely because the Card Services event- * handling code performs scheduling operations which cannot be * executed from within an interrupt context. */ -static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) { - struct sa1100_pcmcia_socket *skt = dev; + struct soc_pcmcia_socket *skt = dev; debug(skt, 3, "servicing IRQ %d\n", irq); - sa1100_check_status(skt); + soc_common_check_status(skt); return IRQ_HANDLED; } -/* sa1100_pcmcia_get_status() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the get_status() operation for the in-kernel PCMCIA +/* + * Implements the get_status() operation for the in-kernel PCMCIA * service (formerly SS_GetStatus in Card Services). Essentially just * fills in bits in `status' according to internal driver state or * the value of the voltage detect chipselect register. @@ -351,39 +281,37 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r * Returns: 0 */ static int -sa1100_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) +soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - skt->status = sa1100_pcmcia_skt_state(skt); + skt->status = soc_common_pcmcia_skt_state(skt); *status = skt->status; return 0; } -/* sa1100_pcmcia_get_socket() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ +/* * Implements the get_socket() operation for the in-kernel PCMCIA - * service (formerly SS_GetSocket in Card Services). Not a very + * service (formerly SS_GetSocket in Card Services). Not a very * exciting routine. * * Returns: 0 */ static int -sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) +soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); - debug(skt, 2, "\n"); + debug(skt, 2, "\n"); - *state = skt->cs_state; + *state = skt->cs_state; - return 0; + return 0; } -/* sa1100_pcmcia_set_socket() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ +/* * 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 @@ -393,31 +321,30 @@ sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state) * Returns: 0 */ static int -sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) +soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) { - struct sa1100_pcmcia_socket *skt = to_sa1100_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)?" ":"", - (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)?" ":"", - (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 sa1100_pcmcia_config_skt(skt, state); -} /* sa1100_pcmcia_set_socket() */ - - -/* sa1100_pcmcia_set_io_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^ + 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)?" ":"", + (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)?" ":"", + (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); +} + + +/* * Implements the set_io_map() operation for the in-kernel PCMCIA * service (formerly SS_SetIOMap in Card Services). We configure * the map speed as requested, but override the address ranges @@ -426,9 +353,9 @@ sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state) * Returns: 0 on success, -1 on error */ static int -sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) +soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); unsigned short speed = map->speed; debug(skt, 2, "map %u speed %u start 0x%08x stop 0x%08x\n", @@ -451,13 +378,13 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) if (map->flags & MAP_ACTIVE) { if (speed == 0) - speed = SA1100_PCMCIA_IO_ACCESS; + speed = SOC_PCMCIA_IO_ACCESS; } else { speed = 0; } skt->spd_io[map->map] = speed; - sa1100_pcmcia_set_mecr(skt, cpufreq_get(0)); + skt->ops->set_timing(skt); if (map->stop == 1) map->stop = PAGE_SIZE-1; @@ -467,11 +394,10 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) map->start = (unsigned long)skt->virt_io; return 0; -} /* sa1100_pcmcia_set_io_map() */ +} -/* sa1100_pcmcia_set_mem_map() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/* * Implements the set_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_SetMemMap in Card Services). We configure * the map speed as requested, but override the address ranges @@ -480,9 +406,9 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map) * Returns: 0 on success, -1 on error */ static int -sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) +soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map) { - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); struct resource *res; unsigned short speed = map->speed; @@ -518,7 +444,7 @@ sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map skt->spd_mem[map->map] = speed; } - sa1100_pcmcia_set_mecr(skt, cpufreq_get(0)); + skt->ops->set_timing(skt); map->sys_stop -= map->sys_start; map->sys_stop += res->start + map->card_start; @@ -567,18 +493,15 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i *p = b; } -/* show_status() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/* * Implements the /sys/class/pcmcia_socket/??/status file. * * Returns: the number of characters added to the buffer */ static ssize_t show_status(struct class_device *class_dev, char *buf) { - struct sa1100_pcmcia_socket *skt = container_of(class_dev, - struct sa1100_pcmcia_socket, socket.dev); - unsigned int clock = cpufreq_get(0); - unsigned long mecr = MECR; + struct soc_pcmcia_socket *skt = + container_of(class_dev, struct soc_pcmcia_socket, socket.dev); char *p = buf; p+=sprintf(p, "slot : %d\n", skt->nr); @@ -593,42 +516,34 @@ static ssize_t show_status(struct class_device *class_dev, char *buf) 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->irq); - - p+=sprintf(p, "I/O : %u (%u)\n", - calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS), - sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr))); - - p+=sprintf(p, "attribute: %u (%u)\n", - calc_speed(skt->spd_attr, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS), - sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr))); - - p+=sprintf(p, "common : %u (%u)\n", - calc_speed(skt->spd_mem, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS), - sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr))); + if (skt->ops->show_timing) + p+=skt->ops->show_timing(skt, p); return p-buf; } static CLASS_DEVICE_ATTR(status, S_IRUGO, show_status, NULL); -static struct pccard_operations sa11xx_pcmcia_operations = { - .init = sa1100_pcmcia_sock_init, - .suspend = sa1100_pcmcia_suspend, - .get_status = sa1100_pcmcia_get_status, - .get_socket = sa1100_pcmcia_get_socket, - .set_socket = sa1100_pcmcia_set_socket, - .set_io_map = sa1100_pcmcia_set_io_map, - .set_mem_map = sa1100_pcmcia_set_mem_map, +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, }; -int sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr) + +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, sa1100_pcmcia_interrupt, + res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt, SA_INTERRUPT, irqs[i].str, skt); if (res) break; @@ -645,9 +560,10 @@ int sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir } return res; } -EXPORT_SYMBOL(sa11xx_request_irqs); +EXPORT_SYMBOL(soc_pcmcia_request_irqs); -void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr) +void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, + struct pcmcia_irqs *irqs, int nr) { int i; @@ -655,9 +571,10 @@ void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs if (irqs[i].sock == skt->nr) free_irq(irqs[i].irq, skt); } -EXPORT_SYMBOL(sa11xx_free_irqs); +EXPORT_SYMBOL(soc_pcmcia_free_irqs); -void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr) +void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, + struct pcmcia_irqs *irqs, int nr) { int i; @@ -665,9 +582,10 @@ void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *i if (irqs[i].sock == skt->nr) set_irq_type(irqs[i].irq, IRQT_NOEDGE); } -EXPORT_SYMBOL(sa11xx_disable_irqs); +EXPORT_SYMBOL(soc_pcmcia_disable_irqs); -void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr) +void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, + struct pcmcia_irqs *irqs, int nr) { int i; @@ -677,10 +595,11 @@ void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir set_irq_type(irqs[i].irq, IRQT_BOTHEDGE); } } -EXPORT_SYMBOL(sa11xx_enable_irqs); +EXPORT_SYMBOL(soc_pcmcia_enable_irqs); + -static LIST_HEAD(sa1100_sockets); -static DECLARE_MUTEX(sa1100_sockets_lock); +LIST_HEAD(soc_pcmcia_sockets); +DECLARE_MUTEX(soc_pcmcia_sockets_lock); static const char *skt_names[] = { "PCMCIA socket 0", @@ -689,26 +608,18 @@ static const char *skt_names[] = { struct skt_dev_info { int nskt; - struct sa1100_pcmcia_socket skt[0]; + struct soc_pcmcia_socket skt[0]; }; #define SKT_DEV_INFO_SIZE(n) \ - (sizeof(struct skt_dev_info) + (n)*sizeof(struct sa1100_pcmcia_socket)) + (sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) -int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) +int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { struct skt_dev_info *sinfo; - unsigned int cpu_clock; int ret, i; - /* - * set default MECR calculation if the board specific - * code did not specify one... - */ - if (!ops->socket_get_timing) - ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing; - - down(&sa1100_sockets_lock); + down(&soc_pcmcia_sockets_lock); sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); if (!sinfo) { @@ -719,22 +630,20 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr)); sinfo->nskt = nr; - cpu_clock = cpufreq_get(0); - /* * Initialise the per-socket structure. */ for (i = 0; i < nr; i++) { - struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; + struct soc_pcmcia_socket *skt = &sinfo->skt[i]; - skt->socket.ops = &sa11xx_pcmcia_operations; + skt->socket.ops = &soc_common_pcmcia_operations; skt->socket.owner = ops->owner; skt->socket.dev.dev = dev; init_timer(&skt->poll_timer); - skt->poll_timer.function = sa1100_pcmcia_poll_event; + skt->poll_timer.function = soc_common_pcmcia_poll_event; skt->poll_timer.data = (unsigned long)skt; - skt->poll_timer.expires = jiffies + SA1100_PCMCIA_POLL_PERIOD; + skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; skt->nr = first + i; skt->irq = NO_IRQ; @@ -772,7 +681,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; skt->res_attr.name = "attribute"; skt->res_attr.flags = IORESOURCE_MEM; - + ret = request_resource(&skt->res_skt, &skt->res_attr); if (ret) goto out_err_4; @@ -783,14 +692,14 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in goto out_err_5; } - list_add(&skt->node, &sa1100_sockets); + list_add(&skt->node, &soc_pcmcia_sockets); /* - * We initialize the MECR to default values here, because + * We initialize default socket timing here, because * we are not guaranteed to see a SetIOMap operation at * runtime. */ - sa1100_pcmcia_set_mecr(skt, cpu_clock); + ops->set_timing(skt); ret = ops->hw_init(skt); if (ret) @@ -802,7 +711,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in skt->socket.pci_irq = skt->irq; skt->socket.io_offset = (unsigned long)skt->virt_io; - skt->status = sa1100_pcmcia_skt_state(skt); + skt->status = soc_common_pcmcia_skt_state(skt); ret = pcmcia_register_socket(&skt->socket); if (ret) @@ -820,7 +729,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in goto out; do { - struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; + struct soc_pcmcia_socket *skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); @@ -847,21 +756,20 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in kfree(sinfo); out: - up(&sa1100_sockets_lock); + up(&soc_pcmcia_sockets_lock); return ret; } -EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); -int sa11xx_drv_pcmcia_remove(struct device *dev) +int soc_common_drv_pcmcia_remove(struct device *dev) { struct skt_dev_info *sinfo = dev_get_drvdata(dev); int i; dev_set_drvdata(dev, NULL); - down(&sa1100_sockets_lock); + down(&soc_pcmcia_sockets_lock); for (i = 0; i < sinfo->nskt; i++) { - struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; + struct soc_pcmcia_socket *skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); @@ -871,7 +779,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) skt->ops->hw_shutdown(skt); - sa1100_pcmcia_config_skt(skt, &dead_socket); + soc_common_pcmcia_config_skt(skt, &dead_socket); list_del(&skt->node); iounmap(skt->virt_io); @@ -881,91 +789,9 @@ int sa11xx_drv_pcmcia_remove(struct device *dev) release_resource(&skt->res_io); release_resource(&skt->res_skt); } - up(&sa1100_sockets_lock); + up(&soc_pcmcia_sockets_lock); kfree(sinfo); return 0; } -EXPORT_SYMBOL(sa11xx_drv_pcmcia_remove); - -#ifdef CONFIG_CPU_FREQ - -/* sa1100_pcmcia_update_mecr() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * When sa1100_pcmcia_notifier() decides that a MECR adjustment (due - * to a core clock frequency change) is needed, this routine establishes - * new BS_xx values consistent with the clock speed `clock'. - */ -static void sa1100_pcmcia_update_mecr(unsigned int clock) -{ - struct sa1100_pcmcia_socket *skt; - - down(&sa1100_sockets_lock); - list_for_each_entry(skt, &sa1100_sockets, node) - sa1100_pcmcia_set_mecr(skt, clock); - up(&sa1100_sockets_lock); -} - -/* sa1100_pcmcia_notifier() - * ^^^^^^^^^^^^^^^^^^^^^^^^ - * When changing the processor core clock frequency, it is necessary - * to adjust the MECR timings accordingly. We've recorded the timings - * requested by Card Services, so this is just a matter of finding - * out what our current speed is, and then recomputing the new MECR - * values. - * - * Returns: 0 on success, -1 on error - */ -static int -sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - struct cpufreq_freqs *freqs = data; - - switch (val) { - case CPUFREQ_PRECHANGE: - if (freqs->new > freqs->old) - sa1100_pcmcia_update_mecr(freqs->new); - break; - - case CPUFREQ_POSTCHANGE: - if (freqs->new < freqs->old) - sa1100_pcmcia_update_mecr(freqs->new); - break; - } - - return 0; -} - -static struct notifier_block sa1100_pcmcia_notifier_block = { - .notifier_call = sa1100_pcmcia_notifier -}; - -static int __init sa11xx_pcmcia_init(void) -{ - int ret; - - printk(KERN_INFO "SA11xx PCMCIA\n"); - - ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - if (ret < 0) - printk(KERN_ERR "Unable to register CPU frequency change " - "notifier (%d)\n", ret); - - return ret; -} -module_init(sa11xx_pcmcia_init); - -static void __exit sa11xx_pcmcia_exit(void) -{ - cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); -} - -module_exit(sa11xx_pcmcia_exit); -#endif - -MODULE_AUTHOR("John Dorsey "); -MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver"); -MODULE_LICENSE("Dual MPL/GPL");