[PATCH 1/2][RFC] ep93xx pcmcia support

Lennert Buytenhek buytenh at wantstofly.org
Sun Feb 4 19:05:07 EST 2007


Signed-off-by: Lennert Buytenhek <buytenh at wantstofly.org>

Index: linux-2.6.20/drivers/pcmcia/Kconfig
===================================================================
--- linux-2.6.20.orig/drivers/pcmcia/Kconfig
+++ linux-2.6.20/drivers/pcmcia/Kconfig
@@ -197,6 +197,12 @@ config PCMCIA_AU1X00
 	tristate "Au1x00 pcmcia support"
 	depends on SOC_AU1X00 && PCMCIA
 
+config PCMCIA_EP93XX
+	tristate "EP93xx support"
+	depends on ARM && ARCH_EP93XX && PCMCIA
+	help
+	  Say Y here to include support for the EP93xx PCMCIA controller
+
 config PCMCIA_SA1100
 	tristate "SA1100 support"
 	depends on ARM && ARCH_SA1100 && PCMCIA
Index: linux-2.6.20/drivers/pcmcia/Makefile
===================================================================
--- linux-2.6.20.orig/drivers/pcmcia/Makefile
+++ linux-2.6.20/drivers/pcmcia/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_I82092)				+= i82092.o
 obj-$(CONFIG_TCIC)				+= tcic.o
 obj-$(CONFIG_PCMCIA_M8XX)			+= m8xx_pcmcia.o
 obj-$(CONFIG_HD64465_PCMCIA)			+= hd64465_ss.o
+obj-$(CONFIG_PCMCIA_EP93XX)			+= ep93xx_core.o ep93xx_cs.o
 obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o
 obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o
 obj-$(CONFIG_PCMCIA_PXA2XX)                     += pxa2xx_core.o pxa2xx_cs.o
@@ -38,6 +39,7 @@ obj-$(CONFIG_PCMCIA_VRC4173)			+= vrc417
 obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
 obj-$(CONFIG_AT91_CF)				+= at91_cf.o
 
+ep93xx_core-y					+= soc_common.o ep93xx_base.o
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
 
Index: linux-2.6.20/drivers/pcmcia/ep93xx_base.c
===================================================================
--- /dev/null
+++ linux-2.6.20/drivers/pcmcia/ep93xx_base.c
@@ -0,0 +1,194 @@
+/*======================================================================
+
+  Device driver for the PCMCIA control functionality of EP93xx
+  microprocessors.  Derived from pxa2xx_base.c
+
+    The contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL")
+
+    (c) Ian Molton (spyro at f2s.com) 2003
+    (c) Stefan Eletzhofer (stefan.eletzhofer at inquant.de) 2003,4
+    (c) Robert Whaley (rwhaley at applieddata.net) 2005
+
+    derived from sa11xx_base.c
+
+     Portions created by John G. Dorsey are
+     Copyright (C) 1999 John G. Dorsey.
+
+  ======================================================================*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+#include "soc_common.h"
+
+#define PC1ATTRIB		(EP93XX_PCMCIA_CONTROLLER_BASE + 0x20)
+#define PC1COMMON		(EP93XX_PCMCIA_CONTROLLER_BASE + 0x24)
+#define PC1IO			(EP93XX_PCMCIA_CONTROLLER_BASE + 0x28)
+#define PC16BITSWIDE		0x80000000
+
+#define MIN(a,b)		((a) > (b) ? (b) : (a))
+
+#define MCXX_SETUP_MAX		0xff
+#define MCXX_ASST_MAX		0xff
+#define MCXX_HOLD_MAX		0x0f
+
+#define MCXX_SETUP_SHIFT	0
+#define MCXX_ASST_SHIFT		16
+#define MCXX_HOLD_SHIFT		8
+
+
+static inline u_int ep93xx_mcxx_hold(u_int pcmcia_cycle_ns,
+				     u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static inline u_int ep93xx_mcxx_asst(u_int pcmcia_cycle_ns,
+				     u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static inline u_int ep93xx_mcxx_setup(u_int pcmcia_cycle_ns,
+				      u_int hclk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * hclk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+static int ep93xx_pcmcia_set_mcmem( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1COMMON);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcio( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1IO);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcatt( int sock, int speed, int clock )
+{
+        writel(PC16BITSWIDE
+	     | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
+	     | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
+	     | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
+	     PC1ATTRIB);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk)
+{
+	struct soc_pcmcia_timing timing;
+	int sock = skt->nr;
+
+	soc_common_pcmcia_get_timing(skt, &timing);
+
+	ep93xx_pcmcia_set_mcmem(sock, timing.mem, clk);
+	ep93xx_pcmcia_set_mcatt(sock, timing.attr, clk);
+	ep93xx_pcmcia_set_mcio(sock, timing.io, clk);
+
+	return 0;
+}
+
+static int ep93xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
+{
+	unsigned int hclk;
+
+	/* for now just hard code hclk to 100Mhz (in 10khz units)*/
+	hclk = 10000;
+
+	return ep93xx_pcmcia_set_mcxx(skt, hclk);
+}
+
+
+static int ep93xx_drv_pcmcia_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct pcmcia_low_level *ops;
+	int first, nr;
+
+	if (pdev->dev.platform_data == NULL)
+		return -ENODEV;
+
+	ops = (struct pcmcia_low_level *)pdev->dev.platform_data;
+	first = ops->first;
+	nr = ops->nr;
+
+	/* Provide our EP93xx specific timing routines. */
+	ops->set_timing  = ep93xx_pcmcia_set_timing;
+
+	ret = soc_common_drv_pcmcia_probe(&pdev->dev, ops, first, nr);
+
+	return ret;
+}
+
+static int ep93xx_drv_pcmcia_remove(struct platform_device *pdev)
+{
+	return soc_common_drv_pcmcia_remove(&pdev->dev);
+}
+
+static int ep93xx_drv_pcmcia_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	return pcmcia_socket_dev_suspend(&pdev->dev, state);
+}
+
+static int ep93xx_drv_pcmcia_resume(struct platform_device *pdev)
+{
+	return pcmcia_socket_dev_resume(&pdev->dev);
+}
+
+static struct platform_driver ep93xx_pcmcia_driver = {
+	.probe		= ep93xx_drv_pcmcia_probe,
+	.remove		= ep93xx_drv_pcmcia_remove,
+	.suspend 	= ep93xx_drv_pcmcia_suspend,
+	.resume 	= ep93xx_drv_pcmcia_resume,
+	.driver		= {
+		.name	= "ep93xx-pcmcia",
+	},
+};
+
+static int __init ep93xx_pcmcia_init(void)
+{
+	return platform_driver_register(&ep93xx_pcmcia_driver);
+}
+
+static void __exit ep93xx_pcmcia_exit(void)
+{
+	platform_driver_unregister(&ep93xx_pcmcia_driver);
+}
+
+fs_initcall(ep93xx_pcmcia_init);
+module_exit(ep93xx_pcmcia_exit);
+
+MODULE_AUTHOR("Robert Whaley <rwhaley at applieddata.net>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: EP93xx core socket driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.20/drivers/pcmcia/soc_common.c
===================================================================
--- linux-2.6.20.orig/drivers/pcmcia/soc_common.c
+++ linux-2.6.20/drivers/pcmcia/soc_common.c
@@ -49,6 +49,9 @@
 #include "soc_common.h"
 
 /* FIXME: platform dependent resource declaration has to move out of this file */
+#ifdef CONFIG_ARCH_EP93XX
+#include <asm/arch/pcmcia.h>
+#endif
 #ifdef CONFIG_ARCH_PXA
 #include <asm/arch/pxa-regs.h>
 #endif
Index: linux-2.6.20/include/asm-arm/arch-ep93xx/pcmcia.h
===================================================================
--- /dev/null
+++ linux-2.6.20/include/asm-arm/arch-ep93xx/pcmcia.h
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-ep93xx/pcmcia.h
+ */
+
+#ifndef __ASM_ARCH_PCMCIA_H
+#define __ASM_ARCH_PCMCIA_H
+
+#define _PCMCIA(slt)		(0x40000000 + ((slt) ? 0x10000000 : 0))
+#define _PCMCIAIO(slt)		_PCMCIA(slt)
+#define _PCMCIAAttr(slt)	(_PCMCIA(slt) + 0x08000000)
+#define _PCMCIAMem(slt)		(_PCMCIA(slt) + 0x0c000000)
+
+#define PCMCIASp		0x10000000
+#define PCMCIAIOSp		0x04000000
+#define PCMCIAAttrSp		0x04000000
+#define PCMCIAMemSp		0x04000000
+
+
+#endif



More information about the linux-pcmcia mailing list