bk://bk.arm.linux.org.uk/linux-2.6-pcmcia rmk@flint.arm.linux.org.uk|ChangeSet|20040531101546|30722 rmk # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/05/31 11:15:46+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Fix up SOC PCMCIA socket timing calculations # # The timing calculations used by the PXA platforms did not always take # account of the timings handed to us by PCMCIA, and where it did, it # assumed IO timings for memory windows. # # We fix this, and provide a generic function which calculates the # required timings (in nanoseconds) for IO, memory and attribute # windows. The SOC drivers only have to convert this information to # whatever format the hardware requires to achieve at least these # timing parameters. # # drivers/pcmcia/soc_common.h # 2004/05/31 11:13:14+01:00 rmk@flint.arm.linux.org.uk +7 -0 # Add soc_pcmcia_timing structure and prototype for # soc_common_pcmcia_get_timing() # # drivers/pcmcia/soc_common.c # 2004/05/31 11:13:13+01:00 rmk@flint.arm.linux.org.uk +23 -0 # Add calc_speed() and soc_common_pcmcia_get_timing() # # drivers/pcmcia/sa11xx_base.c # 2004/05/31 11:13:13+01:00 rmk@flint.arm.linux.org.uk +11 -29 # Move calc_speed() into soc_common.c. Use # soc_common_pcmcia_get_timing() to obtain socket timing. # # drivers/pcmcia/pxa2xx_base.c # 2004/05/31 11:13:13+01:00 rmk@flint.arm.linux.org.uk +7 -9 # Use soc_common_pcmcia_get_timing() to obtain timing parameters for # socket. Consolidate pxa2xx_pcmcia_set_mc* calls in # pxa2xx_pcmcia_update_mcxx(). # diff -Nru a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c --- a/drivers/pcmcia/pxa2xx_base.c 2004-05-31 16:24:35 -07:00 +++ b/drivers/pcmcia/pxa2xx_base.c 2004-05-31 16:24:35 -07:00 @@ -115,11 +115,14 @@ static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int lclk) { + struct soc_pcmcia_timing timing; int sock = skt->nr; - pxa2xx_pcmcia_set_mcmem( sock, SOC_PCMCIA_5V_MEM_ACCESS, lclk ); - pxa2xx_pcmcia_set_mcatt( sock, SOC_PCMCIA_ATTR_MEM_ACCESS, lclk ); - pxa2xx_pcmcia_set_mcio( sock, SOC_PCMCIA_IO_ACCESS, lclk ); + soc_common_pcmcia_get_timing(skt, &timing); + + pxa2xx_pcmcia_set_mcmem(sock, timing.mem, lclk); + pxa2xx_pcmcia_set_mcatt(sock, timing.attr, lclk); + pxa2xx_pcmcia_set_mcio(sock, timing.io, lclk); return 0; } @@ -237,12 +240,7 @@ down(&soc_sockets_lock); list_for_each_entry(skt, &soc_sockets, node) { - pxa2xx_pcmcia_set_mcio(skt->nr, calc_speed(skt->spd_io, - MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS), clock); - pxa2xx_pcmcia_set_mcmem(skt->nr, calc_speed(skt->spd_io, - MAX_IO_WIN, SOC_PCMCIA_3V_MEM_ACCESS), clock ); - pxa2xx_pcmcia_set_mcatt(skt->nr, calc_speed(skt->spd_io, - MAX_IO_WIN, SOC_PCMCIA_3V_MEM_ACCESS), clock ); + pxa2xx_pcmcia_set_mcxx(skt, clock); } up(&soc_sockets_lock); } diff -Nru a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c --- a/drivers/pcmcia/sa11xx_base.c 2004-05-31 16:24:35 -07:00 +++ b/drivers/pcmcia/sa11xx_base.c 2004-05-31 16:24:35 -07:00 @@ -69,21 +69,6 @@ return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed); } -static unsigned short -calc_speed(unsigned short *spds, int num, unsigned short dflt) -{ - unsigned short speed = 0; - int i; - - for (i = 0; i < num; i++) - if (speed < spds[i]) - speed = spds[i]; - if (speed == 0) - speed = dflt; - - return speed; -} - /* sa1100_pcmcia_set_mecr() * ^^^^^^^^^^^^^^^^^^^^^^^^ * @@ -95,19 +80,16 @@ static int sa1100_pcmcia_set_mecr(struct soc_pcmcia_socket *skt, unsigned int cpu_clock) { + 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, SOC_PCMCIA_IO_ACCESS); - bs_io = skt->ops->get_timing(skt, cpu_clock, speed); - - speed = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); - bs_mem = skt->ops->get_timing(skt, cpu_clock, speed); + soc_common_pcmcia_get_timing(skt, &timing); - speed = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS); - bs_attr = skt->ops->get_timing(skt, cpu_clock, speed); + bs_io = skt->ops->get_timing(skt, cpu_clock, timing.io); + bs_mem = skt->ops->get_timing(skt, cpu_clock, timing.mem); + bs_attr = skt->ops->get_timing(skt, cpu_clock, timing.attr); local_irq_save(flags); @@ -138,20 +120,20 @@ static int sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf) { + struct soc_pcmcia_timing timing; unsigned int clock = cpufreq_get(0); unsigned long mecr = MECR; char *p = buf; - p+=sprintf(p, "I/O : %u (%u)\n", - calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS), + soc_common_pcmcia_get_timing(skt, &timing); + + p+=sprintf(p, "I/O : %u (%u)\n", timing.io, 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, SOC_PCMCIA_3V_MEM_ACCESS), + p+=sprintf(p, "attribute: %u (%u)\n", timing.attr, 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, SOC_PCMCIA_3V_MEM_ACCESS), + p+=sprintf(p, "common : %u (%u)\n", timing.mem, sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr))); return p - buf; diff -Nru a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c --- a/drivers/pcmcia/soc_common.c 2004-05-31 16:24:35 -07:00 +++ b/drivers/pcmcia/soc_common.c 2004-05-31 16:24:35 -07:00 @@ -68,6 +68,29 @@ #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) +{ + unsigned short speed = 0; + int i; + + for (i = 0; i < num; i++) + if (speed < spds[i]) + speed = spds[i]; + if (speed == 0) + speed = dflt; + + return speed; +} + +void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing) +{ + 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 soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) { struct pcmcia_state state; diff -Nru a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h --- a/drivers/pcmcia/soc_common.h 2004-05-31 16:24:35 -07:00 +++ b/drivers/pcmcia/soc_common.h 2004-05-31 16:24:35 -07:00 @@ -112,10 +112,17 @@ const char *str; }; +struct soc_pcmcia_timing { + unsigned short io; + unsigned short mem; + unsigned short attr; +}; + extern int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); extern void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); extern void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); extern void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr); +extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *); extern struct list_head soc_pcmcia_sockets;