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;
