---

 /dev/null                                      |  659 ---------------------
 25-akpm/drivers/pcmcia/Kconfig                 |    7 
 25-akpm/drivers/pcmcia/Makefile                |    7 
 25-akpm/drivers/pcmcia/pxa2xx_base.c           |  335 ++++++++++
 25-akpm/drivers/pcmcia/pxa2xx_base.h           |    3 
 25-akpm/drivers/pcmcia/pxa2xx_lubbock.c        |  221 +++++++
 25-akpm/drivers/pcmcia/sa1100_adsbitsy.c       |    4 
 25-akpm/drivers/pcmcia/sa1100_assabet.c        |   20 
 25-akpm/drivers/pcmcia/sa1100_badge4.c         |    2 
 25-akpm/drivers/pcmcia/sa1100_cerf.c           |   20 
 25-akpm/drivers/pcmcia/sa1100_flexanet.c       |   20 
 25-akpm/drivers/pcmcia/sa1100_freebird.c       |   20 
 25-akpm/drivers/pcmcia/sa1100_generic.c        |    4 
 25-akpm/drivers/pcmcia/sa1100_generic.h        |    3 
 25-akpm/drivers/pcmcia/sa1100_graphicsclient.c |   14 
 25-akpm/drivers/pcmcia/sa1100_graphicsmaster.c |    4 
 25-akpm/drivers/pcmcia/sa1100_h3600.c          |   20 
 25-akpm/drivers/pcmcia/sa1100_jornada720.c     |    4 
 25-akpm/drivers/pcmcia/sa1100_neponset.c       |    4 
 25-akpm/drivers/pcmcia/sa1100_pangolin.c       |   20 
 25-akpm/drivers/pcmcia/sa1100_pfs168.c         |    4 
 25-akpm/drivers/pcmcia/sa1100_shannon.c        |   20 
 25-akpm/drivers/pcmcia/sa1100_simpad.c         |   20 
 25-akpm/drivers/pcmcia/sa1100_stork.c          |   20 
 25-akpm/drivers/pcmcia/sa1100_system3.c        |    6 
 25-akpm/drivers/pcmcia/sa1100_trizeps.c        |   20 
 25-akpm/drivers/pcmcia/sa1100_xp860.c          |    4 
 25-akpm/drivers/pcmcia/sa1100_yopy.c           |   20 
 25-akpm/drivers/pcmcia/sa1111_generic.c        |   25 
 25-akpm/drivers/pcmcia/sa1111_generic.h        |   16 
 25-akpm/drivers/pcmcia/sa11xx_base.c           |  257 ++++++++
 25-akpm/drivers/pcmcia/sa11xx_base.h           |  123 +++
 25-akpm/drivers/pcmcia/soc_common.c            |  774 +++++++++++++++++++++++++
 25-akpm/drivers/pcmcia/soc_common.h            |  179 +++++
 25-akpm/include/asm-arm/arch-pxa/pxa-regs.h    |   13 
 drivers/pcmcia/sa11xx_core.c                   |    0 
 36 files changed, 2079 insertions(+), 813 deletions(-)

diff -L Documentation/arm/SA1100/PCMCIA -puN Documentation/arm/SA1100/PCMCIA~bk-pcmcia /dev/null
--- 25/Documentation/arm/SA1100/PCMCIA
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,374 +0,0 @@
-Kernel Low-Level PCMCIA Interface Documentation
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-John G Dorsey <john+@cs.cmu.edu>
-Updated: 30 June, 2000
-
-
-Note: this interface has not been finalized!
-See also: http://www.cs.cmu.edu/~wearable/software/pcmcia-arm.html
-
-
-Introduction
-
-Early versions of PCMCIA Card Services for StrongARM were designed to
-permit a single socket driver to run on a variety of SA-1100 boards by
-using a userland configuration process. During the conversion to the 2.3
-kernel series, all of the configuration has moved into sub-drivers in the
-kernel proper (see linux/drivers/pcmcia/sa1100*). This document describes
-the low-level interface between those sub-drivers and the sa1100 socket
-driver module.
-
-Presently, there are six operations which must be provided by the
-board-specific code. Only functions whose implementation is likely to
-differ across board designs are required at this level. Some examples
-include:
-
-  - configuring card detect lines to generate interrupts
-  - sensing the legal voltage levels for inserted cards
-  - asserting the reset signal for a card
-
-Functions which are assumed to be the same across all designs are
-performed within the generic socket driver itself. Some examples of these
-kinds of operations include:
-
-  - configuring memory access times based on the core clock frequency
-  - reads/writes on memory, byte swizzling, ...
-
-The current implementation allows the specific per-board set of low-level
-operations to be determined at run time. For each specific board, the
-following structure should be filled in:
-
-  struct pcmcia_low_level {
-    int (*init)(struct pcmcia_init *);
-    int (*shutdown)(void);
-    int (*socket_state)(struct pcmcia_state_array *);
-    int (*get_irq_info)(struct pcmcia_irq_info *);
-    int (*configure_socket)(const struct pcmcia_configure *);
-  };
-
-The component functions are described in detail below. Using the
-machine_is_*() tests, the pointer `pcmcia_low_level' should be assigned to
-the location of the table for your board.
-
-
-0. init(struct pcmcia_init *init)
-
-This operation has three responsibilities:
-
-  - perform any board-specific initialization tasks
-  - associate the given handler with any interrupt-generating signals
-    such as card detection, or battery voltage detection
-  - set up any necessary edge detection for card ready signals
-
-Argument passing for this operation is implemented by the following
-structure:
-
-  struct pcmcia_init {
-    void (*handler)(int irq, void *dev, struct pt_regs *regs);
-    struct pcmcia_maps *maps;
-  };
-
-Here, `handler' is provided by the socket driver, and `maps' must be
-modified if the default mapping isn't appropriate. This operation should
-return one of two values:
-
-  - the highest-numbered socket available, plus one
-  - a negative number, indicating an error in configuration
-
-Note that the former case is _not_ the same as "the number of sockets
-available." In particular, if your design uses SA-1100 slot "one" but
-not slot "zero," you MUST report "2" to the socket driver.
-
-
-1. shutdown(void)
-
-This operation takes no arguments, and will be called during cleanup for
-the socket driver module. Any state associated with the socket controller,
-including allocated data structures, reserved IRQs, etc. should be
-released in this routine.
-
-The return value for this operation is not examined.
-
-
-2. socket_state(struct pcmcia_state_array *state_array)
-
-This operation will be invoked from the interrupt handler which was set up
-in the earlier call to init(). Note, however, that it should not include
-any side effects which would be inappropriate if the operation were to
-occur when no interrupt is pending. (An extra invocation of this operation
-currently takes place to initialize state in the socket driver.)
-
-Argument passing for this operation is handled by a structure which
-contains an array of the following type:
-
-  struct pcmcia_state {
-    unsigned detect: 1,
-              ready: 1,
-               bvd1: 1,
-               bvd2: 1,
-             wrprot: 1,
-              vs_3v: 1,
-              vs_Xv: 1;
-  };
-
-Upon return from the operation, a struct pcmcia_state should be filled in
-for each socket available in the hardware. For every array element (up to
-`size' in the struct pcmcia_state_saarray) which does not correspond to an
-available socket, zero the element bits. (This includes element [0] if
-socket zero is not used.)
-
-Regardless of how the various signals are routed to the SA-1100, the bits
-in struct pcmcia_state always have the following semantics:
-
-  detect - 1 if a card is fully inserted, 0 otherwise
-  ready  - 1 if the card ready signal is asserted, 0 otherwise
-  bvd1   - the value of the Battery Voltage Detect 1 signal
-  bvd2   - the value of the Battery Voltage Detect 2 signal
-  wrprot - 1 if the card is write-protected, 0 otherwise
-  vs_3v  - 1 if the card must be operated at 3.3V, 0 otherwise
-  vs_Xv  - 1 if the card must be operated at X.XV, 0 otherwise
-
-A note about the BVD signals: if your board does not make both lines
-directly observable to the processor, just return reasonable values. The
-standard interpretation of the BVD signals is:
-
-  BVD1  BVD2
-
-   0     x    battery is dead
-   1     0    battery warning
-   1     1    battery ok
-
-Regarding the voltage sense flags (vs_3v, vs_Xv), these bits should be set
-based on a sampling of the Voltage Sense pins, if available. The standard
-interpretation of the VS signals (for a "low-voltage" socket) is:
-
-  VS1   VS2
-
-   0     0    X.XV, else 3.3V, else none
-   0     1    3.3V, else none
-   1     0    X.XV, else none
-   1     1    5V, else none
-
-More information about the BVD and VS conventions is available in chapter
-5 of "PCMCIA System Architecture," 2nd ed., by Don Anderson.
-
-This operation should return 1 if an IRQ is actually pending for the
-socket controller, 0 if no IRQ is pending (but no error condition exists,
-such as an undersized state array), or -1 on any error.
-
-
-3. get_irq_info(struct pcmcia_irq_info *info)
-
-This operation obtains the IRQ assignment which is legal for the given
-socket. An argument of the following type is passed:
-
-  struct pcmcia_irq_info {
-    unsigned int sock;
-    unsigned int irq ;
-  };
-
-The `sock' field contains the socket index being queried. The `irq' field
-should contain the IRQ number corresponding to the card ready signal from
-the device.
-
-This operation should return 0 on success, or -1 on any error.
-
-
-4. configure_socket(const struct pcmcia_configure *configure)
-
-This operation allows the caller to apply power to the socket, issue a
-reset, or enable various outputs. The argument is of the following type:
-
-  struct pcmcia_configure {
-    unsigned sock: 8,
-              vcc: 8,
-              vpp: 8,
-           output: 1,
-          speaker: 1,
-            reset: 1;
-  };
-
-The `sock' field contains the index of the socket to be configured. The
-`vcc' and `vpp' fields contain the voltages to be applied for Vcc and Vpp,
-respectively, in units of 0.1V. (Note that vpp==120 indicates that
-programming voltage should be applied.)
-
-The two output enables, `output' and `speaker', refer to the card data
-signal enable and the card speaker enable, respectively. The `reset' bit,
-when set, indicates that the card reset should be asserted.
-
-This operation should return 0 on success, or -1 on any error.
-
-
-Board-Specific Notes
-
-The following information is known about various SA-11x0 board designs
-which may be used as reference while adding support to the kernel.
-
-
-Carnegie Mellon Itsy/Cue (http://www.cs.cmu.edu/~wearable/itsy/)
-
-  Itsy Chip Select 3 (CS3) Interface
-  ("ITSY MEMORY/PCMCIA ADD-ON BOARD with BATTERY and CHARGER CIRCUITRY,"
-   memo dated 5-20-99, from Tim Manns to Richard Martin, et. al)
-
-  Read:
-    ABVD2    (SS)D0          A slot, Battery Voltage Detect
-    ABVD1    (SS)D1
-    AVSS2    (SS)D2          A slot, Voltage Sense
-    AVSS1    (SS)D3
-    GND      (SS)D4
-    GND      (SS)D5
-    GND      (SS)D6
-    GND      (SS)D7
-  
-    BBVD2    (SS)D8          B slot, Battery Voltage Detect
-    BBVD1    (SS)D9
-    BVSS2    (SS)D10         B slot, Voltage Sense
-    BVSS1    (SS)D11
-    GND      (SS)D12
-    GND      (SS)D13
-    GND      (SS)D14
-    GND      (SS)D15
-  
-  Write:
-    (SS)D0   A_VPP_VCC       LTC1472 VPPEN1
-    (SS)D1   A_VPP_PGM       LTC1472 VPPEN0
-    (SS)D2   A_VCC_3         LTC1472 VCCEN0
-    (SS)D3   A_VCC_5         LTC1472 VCCEN1
-    (SS)D4   RESET (A SLOT)
-    (SS)D5   GND
-    (SS)D6   GND
-    (SS)D7   GND
- 
-    (SS)D8   B_VPP_VCC       LTC1472 VPPEN1
-    (SS)D9   B_VPP_PGM       LTC1472 VPPEN0
-    (SS)D10  B_VCC_3         LTC1472 VCCEN0
-    (SS)D11  B_VCC_5         LTC1472 VCCEN1
-    (SS)D12  RESET (B SLOT)
-    (SS)D13  GND
-    (SS)D14  GND
-    (SS)D15  GND
- 
-  GPIO pin assignments are as follows: (from schematics)
- 
-    GPIO 10                  Slot 0 Card Detect
-    GPIO 11                  Slot 1 Card Detect
-    GPIO 12                  Slot 0 Ready/Interrupt
-    GPIO 13                  Slot 1 Ready/Interrupt
-
-
-
-Intel SA-1100 Multimedia Board (http://developer.intel.com/design/strong/)
-
-  CPLD Registers
-  SA-1100 Multimedia Development Board with Companion SA-1101 Development
-    Board User's Guide, p.4-42
-
-  This SA-1100/1101 development package uses only one GPIO pin (24) to
-  signal changes in card status, and requires software to inspect a
-  PCMCIA status register to determine the source.
-
-  Read: (PCMCIA Power Sense Register - 0x19400000)
-    S0VS1           0        Slot 0 voltage sense
-    S0VS2           1
-    S0BVD1          2        Slot 0 battery voltage sense
-    S0BVD2          3
-    S1VS1           4        Slot 1 voltage sense
-    S1VS2           5
-    S1BVD1          6        Slot 1 battery voltage sense
-    S1BVD2          7
-
-  Read/Write: (PCMCIA Power Control Register - 0x19400002)
-    S0VPP0          0        Slot 0 Vpp
-    S0VPP1          1
-    S0VCC0          2        Slot 0 Vcc
-    S0VCC1          3
-    S1VPP0          4        Slot 1 Vpp
-    S1VPP1          5
-    S1VCC0          6        Slot 1 Vcc
-    S1VCC1          7
-
-  Read: (PCMCIA Status Register - 0x19400004)
-    S0CD1           0        Slot 0 Card Detect 1
-    S0RDY           1        Slot 0 Ready/Interrupt
-    S0STSCHG        2        Slot 0 Status Change
-    S0Reset         3        Slot 0 Reset (RW)
-    S1CD1           4        Slot 1 Card Detect 1
-    S1RDY           5        Slot 1 Ready/Interrupt
-    S1STSCHG        6        Slot 1 Status Change
-    S1Reset         7        Slot 1 Reset (RW)
-
-
-
-Intel SA-1100 Evaluation Platform (http://developer.intel.com/design/strong/)
-
-  Brutus I/O Pins and Chipselect Register
-  pcmcia-brutus.c, by Ivo Clarysse
-  (What's the official reference for this info?)
-
-  This SA-1100 development board uses more GPIO pins than say, the Itsy
-  or the SA-1100/1101 multimedia package. The pin assignments are as
-  follows:
-
-    GPIO 2                   Slot 0 Battery Voltage Detect 1
-    GPIO 3                   Slot 0 Ready/Interrupt
-    GPIO 4                   Slot 0 Card Detect
-    GPIO 5                   Slot 1 Battery Voltage Detect 1
-    GPIO 6                   Slot 1 Ready/Interrupt
-    GPIO 7                   Slot 1 Card Detect
-
-  Like the Itsy, Brutus uses a chipselect register in static memory
-  bank 3 for the other signals, such as voltage sense or reset:
-
-  Read:
-    P0_VS1          8        Slot 0 Voltage Sense
-    P0_VS2          9
-    P0_STSCHG      10        Slot 0 Status Change
-    P1_VS1         12        Slot 1 Voltage Sense
-    P1_VS2         13
-    P1_STSCHG      14        Slot 1 Status Change
-
-  Read/Write:
-    P0_            16        Slot 0 MAX1600EAI control line
-    P0_            17        Slot 0 MAX1600EAI control line
-    P0_            18        Slot 0 MAX1600EAI control line
-    P0_            19        Slot 0 MAX1600EAI control line
-    P0_            20        Slot 0 12V
-    P0_            21        Slot 0 Vpp to Vcc (CONFIRM?)
-    P0_            22        Slot 0 enable fan-out drivers & xcvrs
-    P0_SW_RST      23        Slot 0 Reset
-    P1_            24        Slot 1 MAX1600EAI control line
-    P1_            25        Slot 1 MAX1600EAI control line
-    P1_            26        Slot 1 MAX1600EAI control line
-    P1_            27        Slot 1 MAX1600EAI control line
-    P1_            28        Slot 1 12V
-    P1_            29        Slot 1 Vpp to Vcc (CONFIRM?)
-    P1_            30        Slot 1 enable fan-out drivers & xcvrs
-    P1_SW_RST      31        Slot 1 Reset
-
-  For each slot, the bits labelled "MAX1600EAI" should (apparently)
-  be written with the value 0101 for Vcc 3.3V, and 1001 for Vcc 5V.
-
-
-
-Intel SA-1110 Development Platform (http://developer.intel.com/design/strong/)
-
-  GPIO Pin Descriptions and Board Control Register
-  SA-1110 Microprocessor Development Board User's Guide, p.4-7, 4-10
-
-  The Assabet board contains only a single Compact Flash slot,
-  attached to slot 1 on the SA-1110. Card detect, ready, and BVD
-  signals are routed through GPIO, with power and reset placed in a
-  control register. Note that the CF bus must be enabled before use.
-
-    GPIO 21                  Slot 1 Compact Flash interrupt
-    GPIO 22                  Slot 1 card detect (CD1 NOR CD2)
-    GPIO 24                  Slot 1 Battery Voltage Detect 2
-    GPIO 25                  Slot 1 Battery Voltage Detect 1
-
-  Write-only: (Board Control Register - 0x12000000)
-    CF_PWR          0        CF bus power (3.3V)
-    CF_RST          1        CF reset
-    CF_Bus_On       7        CF bus enable
-
diff -puN drivers/pcmcia/Kconfig~bk-pcmcia drivers/pcmcia/Kconfig
--- 25/drivers/pcmcia/Kconfig~bk-pcmcia	2004-05-12 21:00:07.594634120 -0700
+++ 25-akpm/drivers/pcmcia/Kconfig	2004-05-12 21:00:07.639627280 -0700
@@ -120,6 +120,13 @@ config PCMCIA_SA1111
 
 	  This driver is also available as a module called sa1111_cs.
 
+config PCMCIA_PXA2XX
+	tristate "PXA2xx support"
+	depends on ARM && ARCH_PXA && PCMCIA
+	help
+	  Say Y here to include support for the PXA2xx PCMCIA controller
+
+
 config PCMCIA_PROBE
 	bool
 	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
diff -puN drivers/pcmcia/Makefile~bk-pcmcia drivers/pcmcia/Makefile
--- 25/drivers/pcmcia/Makefile~bk-pcmcia	2004-05-12 21:00:07.596633816 -0700
+++ 25-akpm/drivers/pcmcia/Makefile	2004-05-12 21:00:07.639627280 -0700
@@ -15,10 +15,14 @@ obj-$(CONFIG_TCIC)				+= tcic.o
 obj-$(CONFIG_HD64465_PCMCIA)			+= hd64465_ss.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
 
 pcmcia_core-y					+= cistpl.o rsrc_mgr.o bulkmem.o cs.o
 pcmcia_core-$(CONFIG_CARDBUS)			+= cardbus.o
 
+sa11xx_core-y					+= soc_common.o sa11xx_base.o
+pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
+
 sa1111_cs-y					+= sa1111_generic.o
 sa1111_cs-$(CONFIG_SA1100_ADSBITSY)		+= sa1100_adsbitsy.o
 sa1111_cs-$(CONFIG_ASSABET_NEPONSET)		+= sa1100_neponset.o
@@ -42,3 +46,6 @@ sa1100_cs-$(CONFIG_SA1100_SIMPAD)		+= sa
 sa1100_cs-$(CONFIG_SA1100_STORK)		+= sa1100_stork.o
 sa1100_cs-$(CONFIG_SA1100_TRIZEPS) 		+= sa1100_trizeps.o
 sa1100_cs-$(CONFIG_SA1100_YOPY)			+= sa1100_yopy.o
+
+pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK)		+= pxa2xx_lubbock.o sa1111_generic.o
+
diff -puN /dev/null drivers/pcmcia/pxa2xx_base.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/pxa2xx_base.c	2004-05-12 21:00:07.641626976 -0700
@@ -0,0 +1,335 @@
+/*======================================================================
+
+  Device driver for the PCMCIA control functionality of PXA2xx
+  microprocessors.
+
+    The contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL")
+
+    (c) Ian Molton (spyro@f2s.com) 2003
+    (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
+
+    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/config.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.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"
+#include "pxa2xx_base.h"
+
+
+#define MCXX_SETUP_MASK     (0x7f)
+#define MCXX_ASST_MASK      (0x1f)
+#define MCXX_HOLD_MASK      (0x3f)
+#define MCXX_SETUP_SHIFT    (0)
+#define MCXX_ASST_SHIFT     (7)
+#define MCXX_HOLD_SHIFT     (14)
+
+static inline u_int pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns,
+				     u_int mem_clk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+	return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
+}
+
+static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,
+				     u_int mem_clk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+	return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
+}
+
+static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,
+				      u_int mem_clk_10khz)
+{
+	u_int code = pcmcia_cycle_ns * mem_clk_10khz;
+	return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
+}
+
+/* This function returns the (approximate) command assertion period, in
+ * nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
+ */
+static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
+					   u_int pcmcia_mcxx_asst)
+{
+	return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
+}
+
+static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
+{
+	MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+		| ((pxa2xx_mcxx_asst(speed, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+		| ((pxa2xx_mcxx_hold(speed, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+
+	return 0;
+}
+
+static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
+{
+	MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+		| ((pxa2xx_mcxx_asst(speed, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+		| ((pxa2xx_mcxx_hold(speed, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+
+	return 0;
+}
+
+static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
+{
+	MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
+		& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
+		| ((pxa2xx_mcxx_asst(speed, clock)
+		& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
+		| ((pxa2xx_mcxx_hold(speed, clock)
+		& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
+
+	return 0;
+}
+
+static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int lclk)
+{
+	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 );
+
+	return 0;
+}
+
+static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
+{
+	unsigned int lclk = get_lclk_frequency_10khz();
+	return pxa2xx_pcmcia_set_mcxx(skt, lclk);
+}
+
+int pxa2xx_drv_pcmcia_probe(struct device *dev)
+{
+	int ret;
+	struct pcmcia_low_level *ops;
+	int first, nr;
+
+	if (!dev || !dev->platform_data)
+		return -ENODEV;
+
+	ops = (struct pcmcia_low_level *)dev->platform_data;
+	first = ops->first;
+	nr = ops->nr;
+
+	/* Setup GPIOs for PCMCIA/CF alternate function mode.
+	 *
+	 * It would be nice if set_GPIO_mode included support
+	 * for driving GPIO outputs to default high/low state
+	 * before programming GPIOs as outputs. Setting GPIO
+	 * outputs to default high/low state via GPSR/GPCR
+	 * before defining them as outputs should reduce
+	 * the possibility of glitching outputs during GPIO
+	 * setup. This of course assumes external terminators
+	 * are present to hold GPIOs in a defined state.
+	 *
+	 * In the meantime, setup default state of GPIO
+	 * outputs before we enable them as outputs.
+	 */
+
+	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
+		GPIO_bit(GPIO49_nPWE) |
+		GPIO_bit(GPIO50_nPIOR) |
+		GPIO_bit(GPIO51_nPIOW) |
+		GPIO_bit(GPIO52_nPCE_1) |
+		GPIO_bit(GPIO53_nPCE_2);
+
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO50_nPIOR_MD);
+	pxa_gpio_mode(GPIO51_nPIOW_MD);
+	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+	pxa_gpio_mode(GPIO53_nPCE_2_MD);
+	pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
+	/* Provide our PXA2xx specific timing routines. */
+	ops->set_timing  = pxa2xx_pcmcia_set_timing;
+
+	ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+
+	if (ret == 0) {
+		/*
+		 * We have at least one socket, so set MECR:CIT
+		 * (Card Is There)
+		 */
+		MECR |= MECR_CIT;
+
+		/* Set MECR:NOS (Number Of Sockets) */
+		if (nr > 1)
+			MECR |= MECR_NOS;
+		else
+			MECR &= ~MECR_NOS;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe);
+
+static int pxa2xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level)
+{
+	int ret = 0;
+	if (level == SUSPEND_SAVE_STATE)
+		ret = pcmcia_socket_dev_suspend(dev, state);
+	return ret;
+}
+
+static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level)
+{
+	int ret = 0;
+	if (level == RESUME_RESTORE_STATE)
+		ret = pcmcia_socket_dev_resume(dev);
+	return ret;
+}
+
+static struct device_driver pxa2xx_pcmcia_driver = {
+	.probe		= pxa2xx_drv_pcmcia_probe,
+	.remove		= soc_common_drv_pcmcia_remove,
+	.suspend 	= pxa2xx_drv_pcmcia_suspend,
+	.resume 	= pxa2xx_drv_pcmcia_resume,
+	.name		= "pxa2xx-pcmcia",
+	.bus		= &platform_bus_type,
+};
+
+#ifdef CONFIG_CPU_FREQ
+
+/*
+ * When pxa2xx_pcmcia_notifier() decides that a MC{IO,MEM,ATT} adjustment (due
+ * to a core clock frequency change) is needed, this routine establishes
+ * new values consistent with the clock speed `clock'.
+ */
+static void pxa2xx_pcmcia_update_mcxx(unsigned int clock)
+{
+	struct soc_pcmcia_socket *skt;
+
+	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 );
+	}
+	up(&soc_sockets_lock);
+}
+
+/*
+ * When changing the processor L clock frequency, it is necessary
+ * to adjust the MCXX 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 MCXX
+ * values.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int
+pxa2xx_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freqs = data;
+
+#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock"
+	switch (val) {
+		case CPUFREQ_PRECHANGE:
+			if (freqs->new > freqs->old) {
+				debug( 2, "new frequency %u.%uMHz > %u.%uMHz, "
+						"pre-updating\n",
+						freqs->new / 1000, (freqs->new / 100) % 10,
+						freqs->old / 1000, (freqs->old / 100) % 10);
+				pxa2xx_pcmcia_update_mcxx(freqs->new);
+			}
+			break;
+
+		case CPUFREQ_POSTCHANGE:
+			if (freqs->new < freqs->old) {
+				debug( 2, "new frequency %u.%uMHz < %u.%uMHz, "
+						"post-updating\n",
+						freqs->new / 1000, (freqs->new / 100) % 10,
+						freqs->old / 1000, (freqs->old / 100) % 10);
+				pxa2xx_pcmcia_update_mcxx(freqs->new);
+			}
+			break;
+	}
+
+	return 0;
+}
+
+static struct notifier_block pxa2xx_pcmcia_notifier_block = {
+	.notifier_call	= pxa2xx_pcmcia_notifier
+};
+
+static int __init pxa2xx_pcmcia_cpufreq_init(void)
+{
+	int ret;
+
+	ret = cpufreq_register_notifier(&pxa2xx_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 __exit pxa2xx_pcmcia_cpufreq_exit(void)
+{
+	cpufreq_unregister_notifier(&pxa2xx_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+#else
+#define pxa2xx_pcmcia_cpufreq_init()
+#define pxa2xx_pcmcia_cpufreq_exit()
+#endif
+
+static int __init pxa2xx_pcmcia_init(void)
+{
+	int ret = driver_register(&pxa2xx_pcmcia_driver);
+	if (ret == 0)
+		pxa2xx_pcmcia_cpufreq_init();
+	return ret;
+}
+
+static void __exit pxa2xx_pcmcia_exit(void)
+{
+	pxa2xx_pcmcia_cpufreq_exit();
+	driver_unregister(&pxa2xx_pcmcia_driver);
+}
+
+module_init(pxa2xx_pcmcia_init);
+module_exit(pxa2xx_pcmcia_exit);
+
+MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA2xx core socket driver");
+MODULE_LICENSE("GPL");
diff -puN /dev/null drivers/pcmcia/pxa2xx_base.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/pxa2xx_base.h	2004-05-12 21:00:07.642626824 -0700
@@ -0,0 +1,3 @@
+/* temporary measure */
+extern int pxa2xx_drv_pcmcia_probe(struct device *);
+
diff -puN /dev/null drivers/pcmcia/pxa2xx_lubbock.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/pxa2xx_lubbock.c	2004-05-12 21:00:07.643626672 -0700
@@ -0,0 +1,221 @@
+/*
+ * linux/drivers/pcmcia/pxa2xx_lubbock.c
+ *
+ * Author:	George Davis
+ * Created:	Jan 10, 2002
+ * Copyright:	MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
+ *
+ * Lubbock PCMCIA specific routines.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/sa1111.h>
+
+#include "sa1111_generic.h"
+
+static int
+lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
+				const socket_state_t *state)
+{
+  unsigned long flags, gpio, misc_wr;
+  int ret = 1;
+  struct pcmcia_state new_state;
+
+  local_irq_save(flags);
+
+  gpio = PA_DWR;
+  misc_wr = LUB_MISC_WR;
+
+  /* Lubbock uses the Maxim MAX1602, with the following connections:
+   *
+   * Socket 0 (PCMCIA):
+   *	MAX1602	Lubbock		Register
+   *	Pin	Signal
+   *	-----	-------		----------------------
+   *	A0VPP	S0_PWR0		SA-1111 GPIO A<0>
+   *	A1VPP	S0_PWR1		SA-1111 GPIO A<1>
+   *	A0VCC	S0_PWR2		SA-1111 GPIO A<2>
+   *	A1VCC	S0_PWR3		SA-1111 GPIO A<3>
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	+12V
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   * Socket 1 (CF):
+   *	MAX1602	Lubbock		Register
+   *	Pin	Signal
+   *	-----	-------		----------------------
+   *	A0VPP	GND		VPP is not connected
+   *	A1VPP	GND		VPP is not connected
+   *	A0VCC	S1_PWR0		MISC_WR<14>
+   *	A1VCC	S1_PWR0		MISC_WR<15>
+   *	VX	VCC
+   *	VY	+3.3V
+   *	12IN	GND		VPP is not connected
+   *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
+   *
+   */
+
+again:
+  switch(skt->nr){
+  case 0:
+
+    switch(state->Vcc){
+    case 0:
+      gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
+      break;
+
+    case 33:
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
+      break;
+
+    case 50:
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
+      break;
+
+    default:
+      printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
+      ret = -1;
+    }
+
+    switch(state->Vpp){
+    case 0:
+      gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
+      break;
+
+    case 120:
+      gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
+      break;
+
+    default:
+      /* REVISIT: I'm not sure about this? Is this correct?
+         Is it always safe or do we have potential problems
+         with bogus combinations of Vcc and Vpp settings? */
+      if(state->Vpp == state->Vcc)
+        gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
+      else {
+	printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp);
+	ret = -1;
+	break;
+      }
+    }
+
+    break;
+
+  case 1:
+    switch(state->Vcc){
+    case 0:
+      misc_wr &= ~((1 << 15) | (1 << 14));
+      break;
+
+    case 33:
+      misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
+      gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
+      break;
+
+    case 50:
+      misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
+      break;
+
+    default:
+      printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
+      ret = -1;
+      break;
+    }
+
+    if(state->Vpp!=state->Vcc && state->Vpp!=0){
+      printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp);
+      ret = -1;
+      break;
+    }
+
+    break;
+
+  default:
+    ret = -1;
+  }
+
+  if (ret >= 0) {
+    sa1111_pcmcia_configure_socket(skt, state);
+    LUB_MISC_WR = misc_wr;
+    PA_DWR = gpio;
+  }
+
+  if (ret > 0) {
+    ret = 0;
+#if 1
+    /*
+     * HACK ALERT:
+     * We can't sense the voltage properly on Lubbock before actually
+     * applying some power to the socket (catch 22).
+     * Resense the socket Voltage Sense pins after applying socket power.
+     */
+    sa1111_pcmcia_socket_state(skt, &new_state);
+    if (state->Vcc == 33 && !new_state.vs_3v && !new_state.vs_Xv) {
+      /* Switch to 5V,  Configure socket with 5V voltage */
+      PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+      PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
+      /* We need to hack around the const qualifier as well to keep this
+         ugly workaround localized and not force it to the rest of the code.
+         Barf bags avaliable in the seat pocket in front of you! */
+      ((socket_state_t *)state)->Vcc = 50;
+      ((socket_state_t *)state)->Vpp = 50;
+      goto again;
+    }
+#endif
+  }
+
+  local_irq_restore(flags);
+  return ret;
+}
+
+static struct pcmcia_low_level lubbock_pcmcia_ops = {
+	.owner			= THIS_MODULE,
+	.hw_init		= sa1111_pcmcia_hw_init,
+	.hw_shutdown		= sa1111_pcmcia_hw_shutdown,
+	.socket_state		= sa1111_pcmcia_socket_state,
+	.configure_socket	= lubbock_pcmcia_configure_socket,
+	.socket_init		= sa1111_pcmcia_socket_init,
+	.socket_suspend		= sa1111_pcmcia_socket_suspend,
+	.first			= 0,
+	.nr			= 2,
+};
+
+#include "pxa2xx_base.h"
+
+int __init pcmcia_lubbock_init(struct device *dev)
+{
+	int ret = -ENODEV;
+
+	if (machine_is_lubbock()) {
+		/*
+		 * Set GPIO_A<3:0> to be outputs for the MAX1600,
+		 * and switch to standby mode.
+		 */
+		PA_DWR = 0;
+		PA_DDR = 0;
+		PA_SDR = 0;
+		PA_SSR = 0;
+
+		/* Set CF Socket 1 power to standby mode. */
+		LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
+
+		dev->platform_data = &lubbock_pcmcia_ops;
+		ret = pxa2xx_drv_pcmcia_probe(dev);
+	}
+
+	return ret;
+}
diff -puN drivers/pcmcia/sa1100_adsbitsy.c~bk-pcmcia drivers/pcmcia/sa1100_adsbitsy.c
--- 25/drivers/pcmcia/sa1100_adsbitsy.c~bk-pcmcia	2004-05-12 21:00:07.598633512 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_adsbitsy.c	2004-05-12 21:00:07.645626368 -0700
@@ -20,7 +20,7 @@
 
 #include "sa1111_generic.h"
 
-static int adsbitsy_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int adsbitsy_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
 	PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
@@ -35,7 +35,7 @@ static int adsbitsy_pcmcia_hw_init(struc
 }
 
 static int
-adsbitsy_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+adsbitsy_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	unsigned int pa_dwr_mask, pa_dwr_set;
 	int ret;
diff -puN drivers/pcmcia/sa1100_assabet.c~bk-pcmcia drivers/pcmcia/sa1100_assabet.c
--- 25/drivers/pcmcia/sa1100_assabet.c~bk-pcmcia	2004-05-12 21:00:07.599633360 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_assabet.c	2004-05-12 21:00:07.646626216 -0700
@@ -25,23 +25,23 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, ASSABET_IRQ_GPIO_CF_BVD1, "CF BVD1" },
 };
 
-static int assabet_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int assabet_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = ASSABET_IRQ_GPIO_CF_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 /*
  * Release all resources.
  */
-static void assabet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void assabet_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static void
-assabet_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+assabet_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
 
@@ -55,7 +55,7 @@ assabet_pcmcia_socket_state(struct sa110
 }
 
 static int
-assabet_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+assabet_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	unsigned int mask;
 
@@ -93,22 +93,22 @@ assabet_pcmcia_configure_socket(struct s
  * be called at initialisation, power management event, or
  * pcmcia event.
  */
-static void assabet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void assabet_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
 	/*
 	 * Enable CF bus
 	 */
 	ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
 
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 /*
  * Disable card status IRQs on suspend.
  */
-static void assabet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void assabet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/*
 	 * Tristate the CF bus signals.  Also assert CF
diff -puN drivers/pcmcia/sa1100_badge4.c~bk-pcmcia drivers/pcmcia/sa1100_badge4.c
--- 25/drivers/pcmcia/sa1100_badge4.c~bk-pcmcia	2004-05-12 21:00:07.601633056 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_badge4.c	2004-05-12 21:00:07.646626216 -0700
@@ -75,7 +75,7 @@ static void complain_about_jumpering(con
 }
 
 static int
-badge4_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	int ret;
 
diff -puN drivers/pcmcia/sa1100_cerf.c~bk-pcmcia drivers/pcmcia/sa1100_cerf.c
--- 25/drivers/pcmcia/sa1100_cerf.c~bk-pcmcia	2004-05-12 21:00:07.602632904 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_cerf.c	2004-05-12 21:00:07.647626064 -0700
@@ -27,20 +27,20 @@ static struct pcmcia_irqs irqs[] = {
 	{ CERF_SOCKET, CERF_IRQ_GPIO_CF_BVD1, "CF_BVD1" }
 };
 
-static int cerf_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int cerf_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = CERF_IRQ_GPIO_CF_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void cerf_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void cerf_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static void
-cerf_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+cerf_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
 
@@ -54,7 +54,7 @@ cerf_pcmcia_socket_state(struct sa1100_p
 }
 
 static int
-cerf_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+cerf_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			     const socket_state_t *state)
 {
 	switch (state->Vcc) {
@@ -78,14 +78,14 @@ cerf_pcmcia_configure_socket(struct sa11
 	return 0;
 }
 
-static void cerf_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void cerf_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void cerf_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void cerf_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static struct pcmcia_low_level cerf_pcmcia_ops = { 
diff -puN drivers/pcmcia/sa1100_flexanet.c~bk-pcmcia drivers/pcmcia/sa1100_flexanet.c
--- 25/drivers/pcmcia/sa1100_flexanet.c~bk-pcmcia	2004-05-12 21:00:07.603632752 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_flexanet.c	2004-05-12 21:00:07.647626064 -0700
@@ -28,20 +28,20 @@ static struct pcmcia_irqs irqs[] = {
  *
  * Called by sa1100_pcmcia_driver_init on startup.
  */
-static int flexanet_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int flexanet_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = skt->nr ? IRQ_GPIO_CF2_IRQ : IRQ_GPIO_CF1_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 
 /*
  * Socket shutdown
  */
-static void flexanet_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void flexanet_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 
@@ -52,7 +52,7 @@ static void flexanet_pcmcia_hw_shutdown(
  *
  */
 static void
-flexanet_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+flexanet_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			     struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR; /* Sense the GPIOs, asynchronously */
@@ -85,7 +85,7 @@ flexanet_pcmcia_socket_state(struct sa11
  *
  */
 static int
-flexanet_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+flexanet_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				 const socket_state_t *state)
 {
 	unsigned long value, flags, mask;
@@ -133,14 +133,14 @@ flexanet_pcmcia_configure_socket(struct 
 	return 0;
 }
 
-static void flexanet_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void flexanet_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void flexanet_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void flexanet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 /*
diff -puN drivers/pcmcia/sa1100_freebird.c~bk-pcmcia drivers/pcmcia/sa1100_freebird.c
--- 25/drivers/pcmcia/sa1100_freebird.c~bk-pcmcia	2004-05-12 21:00:07.604632600 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_freebird.c	2004-05-12 21:00:07.648625912 -0700
@@ -20,7 +20,7 @@ static struct pcmcia_irqs irqs[] = {
 	{ 0, IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
 };
 
-static int freebird_pcmcia_init(struct sa1100_pcmcia_socket *skt)
+static int freebird_pcmcia_init(struct soc_pcmcia_socket *skt)
 {
 	/* Enable Linkup CF card */
 	LINKUP_PRC = 0xc0;
@@ -35,12 +35,12 @@ static int freebird_pcmcia_init(struct s
 
 	skt->irq = IRQ_GPIO_FREEBIRD_CF_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void freebird_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
+static void freebird_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs);
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs);
 
 	/* Disable CF card */
 	LINKUP_PRC = 0x40;  /* SSP=1   SOE=0 */
@@ -48,7 +48,7 @@ static void freebird_pcmcia_shutdown(str
 }
 
 static void
-freebird_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+freebird_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long levels = LINKUP_PRS;
 //	printk("LINKUP_PRS=%x\n",levels);
@@ -63,7 +63,7 @@ freebird_pcmcia_socket_state(struct sa11
 }
 
 static int
-freebird_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+freebird_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				 socket_state_t *state)
 {
 	unsigned long value, flags;
@@ -103,14 +103,14 @@ freebird_pcmcia_configure_socket(struct 
 	return 0;
 }
 
-static void freebird_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void freebird_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void freebird_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void freebird_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static struct pcmcia_low_level freebird_pcmcia_ops = {
diff -puN drivers/pcmcia/sa1100_generic.c~bk-pcmcia drivers/pcmcia/sa1100_generic.c
--- 25/drivers/pcmcia/sa1100_generic.c~bk-pcmcia	2004-05-12 21:00:07.606632296 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_generic.c	2004-05-12 21:00:07.648625912 -0700
@@ -43,7 +43,7 @@
 #include <pcmcia/cs.h>
 #include <pcmcia/ss.h>
 
-#include "sa1100.h"
+#include "sa1100_generic.h"
 
 static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
 #ifdef CONFIG_SA1100_ASSABET
@@ -118,7 +118,7 @@ static int sa11x0_drv_pcmcia_resume(stru
 
 static struct device_driver sa11x0_pcmcia_driver = {
 	.probe		= sa11x0_drv_pcmcia_probe,
-	.remove		= sa11xx_drv_pcmcia_remove,
+	.remove		= soc_common_drv_pcmcia_remove,
 	.name		= "sa11x0-pcmcia",
 	.bus		= &platform_bus_type,
 	.suspend 	= sa11x0_drv_pcmcia_suspend,
diff -puN drivers/pcmcia/sa1100_generic.h~bk-pcmcia drivers/pcmcia/sa1100_generic.h
--- 25/drivers/pcmcia/sa1100_generic.h~bk-pcmcia	2004-05-12 21:00:07.607632144 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_generic.h	2004-05-12 21:00:07.649625760 -0700
@@ -1,4 +1,5 @@
-#include "sa11xx_core.h"
+#include "soc_common.h"
+#include "sa11xx_base.h"
 
 /*
  * Declaration for all machine specific init/exit functions.
diff -puN drivers/pcmcia/sa1100_graphicsclient.c~bk-pcmcia drivers/pcmcia/sa1100_graphicsclient.c
--- 25/drivers/pcmcia/sa1100_graphicsclient.c~bk-pcmcia	2004-05-12 21:00:07.608631992 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_graphicsclient.c	2004-05-12 21:00:07.649625760 -0700
@@ -38,7 +38,7 @@ static struct pcmcia_irqs irqs[] = {
 	{ 0, S0_CD_IRQ, "PCMCIA 0 CD" },
 };
 
-static int gcplus_pcmcia_init(struct sa1100_pcmcia_socket *skt)
+static int gcplus_pcmcia_init(struct soc_pcmcia_socket *skt)
 {
 	// Reset PCMCIA
 	// Reset Timing for CPLD(U2) version 8001E or later
@@ -54,10 +54,10 @@ static int gcplus_pcmcia_init(struct sa1
 	skt->irq = S0_STS_IRQ;
 
 	/* Register interrupts */
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void gcplus_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void gcplus_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
 	/* disable IRQs */
 	free_irq(S0_CD_IRQ, skt);
@@ -68,7 +68,7 @@ static void gcplus_pcmcia_hw_shutdown(st
 }
 
 static void
-gcplus_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+gcplus_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long levels = *PCMCIA_Status;
 
@@ -82,7 +82,7 @@ gcplus_pcmcia_socket_state(struct sa1100
 }
 
 static int
-gcplus_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+gcplus_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			       const socket_state_t *state)
 {
 	unsigned long flags;
@@ -125,11 +125,11 @@ gcplus_pcmcia_configure_socket(struct sa
 	return 0;
 }
 
-static void gcplus_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void gcplus_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
 }
 
-static void gcplus_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void gcplus_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
 }
 
diff -puN drivers/pcmcia/sa1100_graphicsmaster.c~bk-pcmcia drivers/pcmcia/sa1100_graphicsmaster.c
--- 25/drivers/pcmcia/sa1100_graphicsmaster.c~bk-pcmcia	2004-05-12 21:00:07.610631688 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_graphicsmaster.c	2004-05-12 21:00:07.650625608 -0700
@@ -19,7 +19,7 @@
 
 #include "sa1111_generic.h"
 
-static int graphicsmaster_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int graphicsmaster_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
   int return_val=0;
 
@@ -36,7 +36,7 @@ static int graphicsmaster_pcmcia_hw_init
 }
 
 static int
-graphicsmaster_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+graphicsmaster_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				       const socket_state_t *state)
 {
 	unsigned int pa_dwr_mask, pa_dwr_set;
diff -L drivers/pcmcia/sa1100.h -puN drivers/pcmcia/sa1100.h~bk-pcmcia /dev/null
--- 25/drivers/pcmcia/sa1100.h
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,164 +0,0 @@
-/*======================================================================
-
-    Device driver for the PCMCIA control functionality of StrongARM
-    SA-1100 microprocessors.
-
-    The contents of this file are subject to the Mozilla Public
-    License Version 1.1 (the "License"); you may not use this file
-    except in compliance with the License. You may obtain a copy of
-    the License at http://www.mozilla.org/MPL/
-
-    Software distributed under the License is distributed on an "AS
-    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-    implied. See the License for the specific language governing
-    rights and limitations under the License.
-
-    The initial developer of the original code is John G. Dorsey
-    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
-    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
-
-    Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
-    case the provisions of the GPL are applicable instead of the
-    above.  If you wish to allow the use of your version of this file
-    only under the terms of the GPL and not to allow others to use
-    your version of this file under the MPL, indicate your decision
-    by deleting the provisions above and replace them with the notice
-    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.
-    
-======================================================================*/
-
-#if !defined(_PCMCIA_SA1100_H)
-# define _PCMCIA_SA1100_H
-
-#include <pcmcia/cs_types.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-#include "sa1100_generic.h"
-
-/* MECR: Expansion Memory Configuration Register
- * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
- *
- * MECR layout is:  
- *
- *   FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
- *
- * (This layout is actually true only for the SA-1110; the FASTn bits are
- * reserved on the SA-1100.)
- */
-
-#define MECR_SOCKET_0_SHIFT (0)
-#define MECR_SOCKET_1_SHIFT (16)
-
-#define MECR_BS_MASK        (0x1f)
-#define MECR_FAST_MODE_MASK (0x01)
-
-#define MECR_BSIO_SHIFT (0)
-#define MECR_BSA_SHIFT  (5)
-#define MECR_BSM_SHIFT  (10)
-#define MECR_FAST_SHIFT (15)
-
-#define MECR_SET(mecr, sock, shift, mask, bs) \
-((mecr)=((mecr)&~(((mask)<<(shift))<<\
-                  ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
-        (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
-
-#define MECR_GET(mecr, sock, shift, mask) \
-((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
- (shift))&(mask))
-
-#define MECR_BSIO_SET(mecr, sock, bs) \
-MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
-
-#define MECR_BSIO_GET(mecr, sock) \
-MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
-
-#define MECR_BSA_SET(mecr, sock, bs) \
-MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
-
-#define MECR_BSA_GET(mecr, sock) \
-MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
-
-#define MECR_BSM_SET(mecr, sock, bs) \
-MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
-
-#define MECR_BSM_GET(mecr, sock) \
-MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
-
-#define MECR_FAST_SET(mecr, sock, fast) \
-MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
-
-#define MECR_FAST_GET(mecr, sock) \
-MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
-
-
-/* This function implements the BS value calculation for setting the MECR
- * using integer arithmetic:
- */
-static inline unsigned int sa1100_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
-						 unsigned int cpu_clock_khz){
-  unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
-  return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
-}
-
-/* This function returns the (approxmiate) command assertion period, in
- * nanoseconds, for a given CPU clock frequency and MECR BS value:
- */
-static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
-						  unsigned int pcmcia_mecr_bs){
-  return (((10000000 * 2) / cpu_clock_khz) * (3 * (pcmcia_mecr_bs + 1))) / 10;
-}
-
-
-/* SA-1100 PCMCIA Memory and I/O timing
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * The SA-1110 Developer's Manual, section 10.2.5, says the following:
- *
- *  "To calculate the recommended BS_xx value for each address space:
- *   divide the command width time (the greater of twIOWR and twIORD,
- *   or the greater of twWE and twOE) by processor cycle time; divide
- *   by 2; divide again by 3 (number of BCLK's per command assertion);
- *   round up to the next whole number; and subtract 1."
- *
- * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
- * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
- * a minimum value of 165ns, as well. Section 4.7.2 (describing
- * common and attribute memory write timing) says that twWE has a
- * minimum value of 150ns for a 250ns cycle time (for 5V operation;
- * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
- * operation, also section 4.7.4). Section 4.7.3 says that taOE
- * has a maximum value of 150ns for a 300ns cycle time (for 5V
- * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
- *
- * When configuring memory maps, Card Services appears to adopt the policy
- * that a memory access time of "0" means "use the default." The default
- * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
- * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
- * memory command width time is 300ns.
- */
-#define SA1100_PCMCIA_IO_ACCESS      (165)
-#define SA1100_PCMCIA_5V_MEM_ACCESS  (150)
-#define SA1100_PCMCIA_3V_MEM_ACCESS  (300)
-
-
-/* The socket driver actually works nicely in interrupt-driven form,
- * so the (relatively infrequent) polling is "just to be sure."
- */
-#define SA1100_PCMCIA_POLL_PERIOD    (2*HZ)
-
-struct pcmcia_low_level;
-
-/* I/O pins replacing memory pins
- * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
- *
- * These signals change meaning when going from memory-only to 
- * memory-or-I/O interface:
- */
-#define iostschg bvd1
-#define iospkr   bvd2
-
-#endif  /* !defined(_PCMCIA_SA1100_H) */
diff -puN drivers/pcmcia/sa1100_h3600.c~bk-pcmcia drivers/pcmcia/sa1100_h3600.c
--- 25/drivers/pcmcia/sa1100_h3600.c~bk-pcmcia	2004-05-12 21:00:07.612631384 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_h3600.c	2004-05-12 21:00:07.650625608 -0700
@@ -23,18 +23,18 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
 };
 
-static int h3600_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = skt->nr ? IRQ_GPIO_H3600_PCMCIA_IRQ1
 			   : IRQ_GPIO_H3600_PCMCIA_IRQ0;
 
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void h3600_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
   
 	/* Disable CF bus: */
 	clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
@@ -43,7 +43,7 @@ static void h3600_pcmcia_hw_shutdown(str
 }
 
 static void
-h3600_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
 
@@ -71,7 +71,7 @@ h3600_pcmcia_socket_state(struct sa1100_
 }
 
 static int
-h3600_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) {
 		printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
@@ -89,7 +89,7 @@ h3600_pcmcia_configure_socket(struct sa1
 	return 0;
 }
 
-static void h3600_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
 	/* Enable CF bus: */
 	set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
@@ -99,12 +99,12 @@ static void h3600_pcmcia_socket_init(str
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(10*HZ / 1000);
 
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void h3600_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/*
 	 * FIXME:  This doesn't fit well.  We don't have the mechanism in
diff -puN drivers/pcmcia/sa1100_jornada720.c~bk-pcmcia drivers/pcmcia/sa1100_jornada720.c
--- 25/drivers/pcmcia/sa1100_jornada720.c~bk-pcmcia	2004-05-12 21:00:07.613631232 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_jornada720.c	2004-05-12 21:00:07.651625456 -0700
@@ -23,7 +23,7 @@
 #warning *** Does SOCKET1_3V actually do anything?
 #define SOCKET1_3V	GPIO_GPIO3
 
-static int jornada720_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
   /*
    * What is all this crap for?
@@ -49,7 +49,7 @@ static int jornada720_pcmcia_hw_init(str
 }
 
 static int
-jornada720_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
   unsigned int pa_dwr_mask, pa_dwr_set;
   int ret;
diff -puN drivers/pcmcia/sa1100_neponset.c~bk-pcmcia drivers/pcmcia/sa1100_neponset.c
--- 25/drivers/pcmcia/sa1100_neponset.c~bk-pcmcia	2004-05-12 21:00:07.614631080 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_neponset.c	2004-05-12 21:00:07.651625456 -0700
@@ -42,7 +42,7 @@
  */
 
 static int
-neponset_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
 	int ret;
@@ -106,7 +106,7 @@ neponset_pcmcia_configure_socket(struct 
 	return 0;
 }
 
-static void neponset_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void neponset_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
 	if (skt->nr == 0)
 		NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
diff -puN drivers/pcmcia/sa1100_pangolin.c~bk-pcmcia drivers/pcmcia/sa1100_pangolin.c
--- 25/drivers/pcmcia/sa1100_pangolin.c~bk-pcmcia	2004-05-12 21:00:07.615630928 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_pangolin.c	2004-05-12 21:00:07.652625304 -0700
@@ -26,7 +26,7 @@ static struct pcmcia_irqs irqs[] = {
 	{ PANGOLIN_SOCK, IRQ_PCMCIA_CD, "PCMCIA CD" },
 };
 
-static int pangolin_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int pangolin_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int res;
 
@@ -37,12 +37,12 @@ static int pangolin_pcmcia_hw_init(struc
 
 	skt->irq = IRQ_PCMCIA_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void pangolin_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void pangolin_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
 	/* Disable PCMCIA bus: */
@@ -51,7 +51,7 @@ static void pangolin_pcmcia_hw_shutdown(
 }
 
 static void
-pangolin_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+pangolin_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			     struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
@@ -66,7 +66,7 @@ pangolin_pcmcia_socket_state(struct sa11
 }
 
 static int
-pangolin_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+pangolin_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				 const socket_state_t *state)
 {
 	unsigned long value, flags;
@@ -115,14 +115,14 @@ pangolin_pcmcia_configure_socket(struct 
 	return 0;
 }
 
-static void pangolin_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void pangolin_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void pangolin_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void pangolin_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static struct pcmcia_low_level pangolin_pcmcia_ops = { 
diff -puN drivers/pcmcia/sa1100_pfs168.c~bk-pcmcia drivers/pcmcia/sa1100_pfs168.c
--- 25/drivers/pcmcia/sa1100_pfs168.c~bk-pcmcia	2004-05-12 21:00:07.617630624 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_pfs168.c	2004-05-12 21:00:07.652625304 -0700
@@ -18,7 +18,7 @@
 
 #include "sa1111_generic.h"
 
-static int pfs168_pcmcia_init(struct sa1100_pcmcia_socket *skt)
+static int pfs168_pcmcia_init(struct soc_pcmcia_socket *skt)
 {
   /* TPS2211 to standby mode: */
   PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
@@ -30,7 +30,7 @@ static int pfs168_pcmcia_init(struct sa1
 }
 
 static int
-pfs168_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+pfs168_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			       const socket_state_t *state)
 {
   unsigned int pa_dwr_mask = 0, pa_dwr_set = 0;
diff -puN drivers/pcmcia/sa1100_shannon.c~bk-pcmcia drivers/pcmcia/sa1100_shannon.c
--- 25/drivers/pcmcia/sa1100_shannon.c~bk-pcmcia	2004-05-12 21:00:07.618630472 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_shannon.c	2004-05-12 21:00:07.653625152 -0700
@@ -21,7 +21,7 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
 };
 
-static int shannon_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int shannon_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	/* All those are inputs */
 	GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | 
@@ -31,16 +31,16 @@ static int shannon_pcmcia_hw_init(struct
 
 	skt->irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void shannon_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void shannon_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static void
-shannon_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+shannon_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			    struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
@@ -69,7 +69,7 @@ shannon_pcmcia_socket_state(struct sa110
 }
 
 static int
-shannon_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+shannon_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
 {
 	switch (state->Vcc) {
@@ -93,14 +93,14 @@ shannon_pcmcia_configure_socket(struct s
 	return 0;
 }
 
-static void shannon_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void shannon_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void shannon_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void shannon_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static struct pcmcia_low_level shannon_pcmcia_ops = {
diff -puN drivers/pcmcia/sa1100_simpad.c~bk-pcmcia drivers/pcmcia/sa1100_simpad.c
--- 25/drivers/pcmcia/sa1100_simpad.c~bk-pcmcia	2004-05-12 21:00:07.619630320 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_simpad.c	2004-05-12 21:00:07.653625152 -0700
@@ -24,19 +24,19 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, IRQ_GPIO_CF_CD, "CF_CD" },
 };
 
-static int simpad_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 
 	clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
 
 	skt->irq = IRQ_GPIO_CF_IRQ;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void simpad_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/* Disable CF bus: */
 	//set_cs3_bit(PCMCIA_BUFF_DIS);
@@ -44,7 +44,7 @@ static void simpad_pcmcia_hw_shutdown(st
 }
 
 static void
-simpad_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			   struct pcmcia_state *state)
 {
 	unsigned long levels = GPLR;
@@ -66,7 +66,7 @@ simpad_pcmcia_socket_state(struct sa1100
 }
 
 static int
-simpad_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			       const socket_state_t *state)
 {
 	unsigned long flags;
@@ -103,14 +103,14 @@ simpad_pcmcia_configure_socket(struct sa
 	return 0;
 }
 
-static void simpad_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void simpad_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 	set_cs3_bit(PCMCIA_RESET);
 }
 
diff -puN drivers/pcmcia/sa1100_stork.c~bk-pcmcia drivers/pcmcia/sa1100_stork.c
--- 25/drivers/pcmcia/sa1100_stork.c~bk-pcmcia	2004-05-12 21:00:07.620630168 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_stork.c	2004-05-12 21:00:07.654625000 -0700
@@ -36,24 +36,24 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
 };
 
-static int stork_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int stork_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	printk("in stork_pcmcia_init\n");
 
 	skt->irq = skt->nr ? IRQ_GPIO_STORK_PCMCIA_B_RDY
 			   : IRQ_GPIO_STORK_PCMCIA_A_RDY;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void stork_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void stork_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
 	int i;
 
         printk("%s\n", __FUNCTION__);
 
         /* disable IRQs */
-        sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+        soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
   
         /* Disable CF bus: */
         storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
@@ -62,7 +62,7 @@ static void stork_pcmcia_hw_shutdown(str
 }
 
 static void
-stork_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+stork_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			  struct pcmcia_state *state)
 {
         unsigned long levels = GPLR;
@@ -95,7 +95,7 @@ stork_pcmcia_socket_state(struct sa1100_
 }
 
 static int
-stork_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+stork_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			      const socket_state_t *state)
 {
 	unsigned long flags;
@@ -156,16 +156,16 @@ stork_pcmcia_configure_socket(struct sa1
         return 0;
 }
 
-static void stork_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void stork_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
         storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
 
-        sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+        soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void stork_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void stork_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/*
 	 * Hack!
diff -puN drivers/pcmcia/sa1100_system3.c~bk-pcmcia drivers/pcmcia/sa1100_system3.c
--- 25/drivers/pcmcia/sa1100_system3.c~bk-pcmcia	2004-05-12 21:00:07.621630016 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_system3.c	2004-05-12 21:00:07.655624848 -0700
@@ -47,7 +47,7 @@
 #	define DPRINTK( x, args... )	/* nix */
 #endif
 
-static int system3_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int system3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
 
@@ -55,12 +55,12 @@ static int system3_pcmcia_hw_init(struct
 	return 0;
 }
 
-void system3_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+void system3_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
 }
 
 static void
-system3_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+system3_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	unsigned long status = PCSR;
 
diff -puN drivers/pcmcia/sa1100_trizeps.c~bk-pcmcia drivers/pcmcia/sa1100_trizeps.c
--- 25/drivers/pcmcia/sa1100_trizeps.c~bk-pcmcia	2004-05-12 21:00:07.623629712 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_trizeps.c	2004-05-12 21:00:07.655624848 -0700
@@ -32,7 +32,7 @@ static struct pcmcia_irqs irqs[] = {
  *
  *
  ******************************************************/
-static int trizeps_pcmcia_init(struct sa1100_pcmcia_socket *skt)
+static int trizeps_pcmcia_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = TRIZEPS_IRQ_PCMCIA_IRQ0;
 
@@ -43,18 +43,18 @@ static int trizeps_pcmcia_init(struct sa
 	GPDR &= ~((GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_CD0))
 		    | (GPIO_GPIO(TRIZEPS_GPIO_PCMCIA_IRQ0)));
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 /**
  *
  *
  ******************************************************/
-static void trizeps_pcmcia_shutdown(struct sa1100_pcmcia_socket *skt)
+static void trizeps_pcmcia_shutdown(struct soc_pcmcia_socket *skt)
 {
 	printk(">>>>>PCMCIA TRIZEPS shutdown\n");
 
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/* Disable CF bus: */
 	TRIZEPS_BCR_set(TRIZEPS_BCR1, TRIZEPS_nPCM_ENA_REG);
@@ -64,7 +64,7 @@ static void trizeps_pcmcia_shutdown(stru
  *
  ******************************************************/
 static void
-trizeps_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+trizeps_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			    struct pcmcia_state *state_array)
 {
 	unsigned long levels = GPLR;
@@ -83,7 +83,7 @@ trizeps_pcmcia_socket_state(struct sa110
  *
  ******************************************************/
 static int
-trizeps_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+trizeps_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
 {
 	unsigned long flags;
@@ -129,14 +129,14 @@ trizeps_pcmcia_configure_socket(struct s
 	return 0;
 }
 
-static void trizeps_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void trizeps_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void trizeps_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void trizeps_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 /**
diff -puN drivers/pcmcia/sa1100_xp860.c~bk-pcmcia drivers/pcmcia/sa1100_xp860.c
--- 25/drivers/pcmcia/sa1100_xp860.c~bk-pcmcia	2004-05-12 21:00:07.624629560 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_xp860.c	2004-05-12 21:00:07.656624696 -0700
@@ -19,7 +19,7 @@
 #define NCR_A0VPP	(1<<16)
 #define NCR_A1VPP	(1<<17)
 
-static int xp860_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int xp860_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
   /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
   PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
@@ -42,7 +42,7 @@ static int xp860_pcmcia_hw_init(struct s
 }
 
 static int
-xp860_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+xp860_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
   unsigned int gpio_mask, pa_dwr_mask;
   unsigned int gpio_set, pa_dwr_set;
diff -puN drivers/pcmcia/sa1100_yopy.c~bk-pcmcia drivers/pcmcia/sa1100_yopy.c
--- 25/drivers/pcmcia/sa1100_yopy.c~bk-pcmcia	2004-05-12 21:00:07.625629408 -0700
+++ 25-akpm/drivers/pcmcia/sa1100_yopy.c	2004-05-12 21:00:07.656624696 -0700
@@ -33,19 +33,19 @@ static struct pcmcia_irqs irqs[] = {
 	{ 0, IRQ_CF_BVD1, "CF_BVD1" },
 };
 
-static int yopy_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+static int yopy_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	skt->irq = IRQ_CF_IREQ;
 
 	pcmcia_power(0);
 	pcmcia_reset(1);
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void yopy_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+static void yopy_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 
 	/* Disable CF */
 	pcmcia_reset(1);
@@ -53,7 +53,7 @@ static void yopy_pcmcia_hw_shutdown(stru
 }
 
 static void
-yopy_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt,
+yopy_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 			 struct pcmcia_state_array *state)
 {
 	unsigned long levels = GPLR;
@@ -68,7 +68,7 @@ yopy_pcmcia_socket_state(struct sa1100_p
 }
 
 static int
-yopy_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt,
+yopy_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 			     const socket_state_t *state)
 {
 	switch (state->Vcc) {
@@ -93,14 +93,14 @@ yopy_pcmcia_configure_socket(struct sa11
 	return 0;
 }
 
-static void yopy_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+static void yopy_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-static void yopy_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+static void yopy_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static struct pcmcia_low_level yopy_pcmcia_ops = {
diff -puN drivers/pcmcia/sa1111_generic.c~bk-pcmcia drivers/pcmcia/sa1111_generic.c
--- 25/drivers/pcmcia/sa1111_generic.c~bk-pcmcia	2004-05-12 21:00:07.626629256 -0700
+++ 25-akpm/drivers/pcmcia/sa1111_generic.c	2004-05-12 21:00:07.657624544 -0700
@@ -29,20 +29,20 @@ static struct pcmcia_irqs irqs[] = {
 	{ 1, IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1"            },
 };
 
-int sa1111_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt)
+int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	if (skt->irq == NO_IRQ)
 		skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
 
-	return sa11xx_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-void sa1111_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *skt)
+void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-void sa1111_pcmcia_socket_state(struct sa1100_pcmcia_socket *skt, struct pcmcia_state *state)
+void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
 {
 	struct sa1111_dev *sadev = SA1111_DEV(skt->dev);
 	unsigned long status = sa1111_readl(sadev->mapbase + SA1111_PCSR);
@@ -70,7 +70,7 @@ void sa1111_pcmcia_socket_state(struct s
 	}
 }
 
-int sa1111_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state)
+int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
 {
 	struct sa1111_dev *sadev = SA1111_DEV(skt->dev);
 	unsigned int pccr_skt_mask, pccr_set_mask, val;
@@ -110,14 +110,14 @@ int sa1111_pcmcia_configure_socket(struc
 	return 0;
 }
 
-void sa1111_pcmcia_socket_init(struct sa1100_pcmcia_socket *skt)
+void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
-void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt)
+void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
 {
-	sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
+	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
 
 static int pcmcia_probe(struct sa1111_dev *dev)
@@ -148,6 +148,9 @@ static int pcmcia_probe(struct sa1111_de
 #ifdef CONFIG_SA1100_JORNADA720
 	pcmcia_jornada720_init(&dev->dev);
 #endif
+#ifdef CONFIG_ARCH_LUBBOCK
+	pcmcia_lubbock_init(&dev->dev);
+#endif
 #ifdef CONFIG_ASSABET_NEPONSET
 	pcmcia_neponset_init(dev);
 #endif
@@ -165,7 +168,7 @@ static int pcmcia_probe(struct sa1111_de
 
 static int __devexit pcmcia_remove(struct sa1111_dev *dev)
 {
-	sa11xx_drv_pcmcia_remove(&dev->dev);
+	soc_common_drv_pcmcia_remove(&dev->dev);
 	release_mem_region(dev->res.start, 512);
 	return 0;
 }
diff -puN drivers/pcmcia/sa1111_generic.h~bk-pcmcia drivers/pcmcia/sa1111_generic.h
--- 25/drivers/pcmcia/sa1111_generic.h~bk-pcmcia	2004-05-12 21:00:07.627629104 -0700
+++ 25-akpm/drivers/pcmcia/sa1111_generic.h	2004-05-12 21:00:07.658624392 -0700
@@ -1,13 +1,15 @@
-#include "sa11xx_core.h"
+#include "soc_common.h"
+#include "sa11xx_base.h"
 
-extern int sa1111_pcmcia_hw_init(struct sa1100_pcmcia_socket *);
-extern void sa1111_pcmcia_hw_shutdown(struct sa1100_pcmcia_socket *);
-extern void sa1111_pcmcia_socket_state(struct sa1100_pcmcia_socket *, struct pcmcia_state *);
-extern int sa1111_pcmcia_configure_socket(struct sa1100_pcmcia_socket *, const socket_state_t *);
-extern void sa1111_pcmcia_socket_init(struct sa1100_pcmcia_socket *);
-extern void sa1111_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *);
+extern int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *);
+extern void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *);
+extern void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *, struct pcmcia_state *);
+extern int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *, const socket_state_t *);
+extern void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *);
+extern void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *);
 
 extern int pcmcia_badge4_init(struct device *);
 extern int pcmcia_jornada720_init(struct device *);
+extern int pcmcia_lubbock_init(struct device *);
 extern int pcmcia_neponset_init(struct sa1111_dev *);
 
diff -puN /dev/null drivers/pcmcia/sa11xx_base.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/sa11xx_base.c	2004-05-12 21:00:07.659624240 -0700
@@ -0,0 +1,257 @@
+/*======================================================================
+
+    Device driver for the PCMCIA control functionality of StrongARM
+    SA-1100 microprocessors.
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is John G. Dorsey
+    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
+    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    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.
+
+======================================================================*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "soc_common.h"
+#include "sa11xx_base.h"
+
+
+/*
+ * 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 soc_pcmcia_socket *skt,
+				  unsigned int cpu_speed,
+				  unsigned int cmd_time)
+{
+	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()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * set MECR value for socket <sock> 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 soc_pcmcia_socket *skt, unsigned int cpu_clock)
+{
+	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);
+
+	speed = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+	bs_attr = skt->ops->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;
+}
+
+static int
+sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
+{
+	return sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
+}
+
+static int
+sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf)
+{
+	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),
+		   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),
+		   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),
+		   sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr)));
+
+	return p - buf;
+}
+
+int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
+			    int first, int nr)
+{
+	/*
+	 * set default MECR calculation if the board specific
+	 * code did not specify one...
+	 */
+	if (!ops->get_timing)
+		ops->get_timing = sa1100_pcmcia_default_mecr_timing;
+
+	/* Provide our SA11x0 specific timing routines. */
+	ops->set_timing  = sa1100_pcmcia_set_timing;
+	ops->show_timing = sa1100_pcmcia_show_timing;
+
+	return soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+}
+EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
+
+#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 soc_pcmcia_socket *skt;
+
+	down(&soc_pcmcia_sockets_lock);
+	list_for_each_entry(skt, &soc_pcmcia_sockets, node)
+		sa1100_pcmcia_set_mecr(skt, clock);
+	up(&soc_pcmcia_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 <john+@cs.cmu.edu>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver");
+MODULE_LICENSE("Dual MPL/GPL");
diff -puN /dev/null drivers/pcmcia/sa11xx_base.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/sa11xx_base.h	2004-05-12 21:00:07.661623936 -0700
@@ -0,0 +1,123 @@
+/*======================================================================
+
+    Device driver for the PCMCIA control functionality of StrongARM
+    SA-1100 microprocessors.
+
+    The contents of this file are subject to the Mozilla Public
+    License Version 1.1 (the "License"); you may not use this file
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is John G. Dorsey
+    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
+    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    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.
+
+======================================================================*/
+
+#if !defined(_PCMCIA_SA1100_H)
+# define _PCMCIA_SA1100_H
+
+/* SA-1100 PCMCIA Memory and I/O timing
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * The SA-1110 Developer's Manual, section 10.2.5, says the following:
+ *
+ *  "To calculate the recommended BS_xx value for each address space:
+ *   divide the command width time (the greater of twIOWR and twIORD,
+ *   or the greater of twWE and twOE) by processor cycle time; divide
+ *   by 2; divide again by 3 (number of BCLK's per command assertion);
+ *   round up to the next whole number; and subtract 1."
+ */
+
+/* MECR: Expansion Memory Configuration Register
+ * (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
+ *
+ * MECR layout is:
+ *
+ *   FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
+ *
+ * (This layout is actually true only for the SA-1110; the FASTn bits are
+ * reserved on the SA-1100.)
+ */
+
+#define MECR_SOCKET_0_SHIFT (0)
+#define MECR_SOCKET_1_SHIFT (16)
+
+#define MECR_BS_MASK        (0x1f)
+#define MECR_FAST_MODE_MASK (0x01)
+
+#define MECR_BSIO_SHIFT (0)
+#define MECR_BSA_SHIFT  (5)
+#define MECR_BSM_SHIFT  (10)
+#define MECR_FAST_SHIFT (15)
+
+#define MECR_SET(mecr, sock, shift, mask, bs) \
+((mecr)=((mecr)&~(((mask)<<(shift))<<\
+                  ((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))|\
+        (((bs)<<(shift))<<((sock)==0?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT)))
+
+#define MECR_GET(mecr, sock, shift, mask) \
+((((mecr)>>(((sock)==0)?MECR_SOCKET_0_SHIFT:MECR_SOCKET_1_SHIFT))>>\
+ (shift))&(mask))
+
+#define MECR_BSIO_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSIO_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSIO_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSA_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSA_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSA_SHIFT, MECR_BS_MASK)
+
+#define MECR_BSM_SET(mecr, sock, bs) \
+MECR_SET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK, (bs))
+
+#define MECR_BSM_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_BSM_SHIFT, MECR_BS_MASK)
+
+#define MECR_FAST_SET(mecr, sock, fast) \
+MECR_SET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK, (fast))
+
+#define MECR_FAST_GET(mecr, sock) \
+MECR_GET((mecr), (sock), MECR_FAST_SHIFT, MECR_FAST_MODE_MASK)
+
+
+/* This function implements the BS value calculation for setting the MECR
+ * using integer arithmetic:
+ */
+static inline unsigned int sa1100_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
+						 unsigned int cpu_clock_khz){
+  unsigned int t = ((pcmcia_cycle_ns * cpu_clock_khz) / 6) - 1000000;
+  return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
+}
+
+/* This function returns the (approximate) command assertion period, in
+ * nanoseconds, for a given CPU clock frequency and MECR BS value:
+ */
+static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
+						  unsigned int pcmcia_mecr_bs){
+  return (((10000000 * 2) / cpu_clock_khz) * (3 * (pcmcia_mecr_bs + 1))) / 10;
+}
+
+
+extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
+
+#endif  /* !defined(_PCMCIA_SA1100_H) */
diff -puN drivers/pcmcia/sa11xx_core.c~bk-pcmcia drivers/pcmcia/sa11xx_core.c
diff -L drivers/pcmcia/sa11xx_core.h -puN drivers/pcmcia/sa11xx_core.h~bk-pcmcia /dev/null
--- 25/drivers/pcmcia/sa11xx_core.h
+++ /dev/null	2003-09-15 06:40:47.000000000 -0700
@@ -1,121 +0,0 @@
-/*
- * linux/include/asm/arch/pcmcia.h
- *
- * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
- *
- * This file contains definitions for the low-level SA-1100 kernel PCMCIA
- * interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
- */
-#ifndef _ASM_ARCH_PCMCIA
-#define _ASM_ARCH_PCMCIA
-
-/* include the world */
-#include <pcmcia/version.h>
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/bulkmem.h>
-#include <pcmcia/cistpl.h>
-#include "cs_internal.h"
-
-struct device;
-
-/* Ideally, we'd support up to MAX_SOCK sockets, but the SA-1100 only
- * has support for two. This shows up in lots of hardwired ways, such
- * as the fact that MECR only has enough bits to configure two sockets.
- * Since it's so entrenched in the hardware, limiting the software
- * in this way doesn't seem too terrible.
- */
-#define SA1100_PCMCIA_MAX_SOCK   (2)
-
-struct pcmcia_state {
-  unsigned detect: 1,
-            ready: 1,
-             bvd1: 1,
-             bvd2: 1,
-           wrprot: 1,
-            vs_3v: 1,
-            vs_Xv: 1;
-};
-
-/*
- * This structure encapsulates per-socket state which we might need to
- * use when responding to a Card Services query of some kind.
- */
-struct sa1100_pcmcia_socket {
-	struct pcmcia_socket	socket;
-
-	/*
-	 * Info from low level handler
-	 */
-	struct device		*dev;
-	unsigned int		nr;
-	unsigned int		irq;
-
-	/*
-	 * Core PCMCIA state
-	 */
-	struct pcmcia_low_level *ops;
-
-	unsigned int		status;
-	socket_state_t		cs_state;
-
-	unsigned short		spd_io[MAX_IO_WIN];
-	unsigned short		spd_mem[MAX_WIN];
-	unsigned short		spd_attr[MAX_WIN];
-
-	struct resource		res_skt;
-	struct resource		res_io;
-	struct resource		res_mem;
-	struct resource		res_attr;
-	void			*virt_io;
-
-	unsigned int		irq_state;
-
-	struct timer_list	poll_timer;
-	struct list_head	node;
-};
-
-struct pcmcia_low_level {
-	struct module *owner;
-
-	int (*hw_init)(struct sa1100_pcmcia_socket *);
-	void (*hw_shutdown)(struct sa1100_pcmcia_socket *);
-
-	void (*socket_state)(struct sa1100_pcmcia_socket *, struct pcmcia_state *);
-	int (*configure_socket)(struct sa1100_pcmcia_socket *, const socket_state_t *);
-
-	/*
-	 * Enable card status IRQs on (re-)initialisation.  This can
-	 * be called at initialisation, power management event, or
-	 * pcmcia event.
-	 */
-	void (*socket_init)(struct sa1100_pcmcia_socket *);
-
-	/*
-	 * Disable card status IRQs and PCMCIA bus on suspend.
-	 */
-	void (*socket_suspend)(struct sa1100_pcmcia_socket *);
-
-	/*
-	 * Calculate MECR timing clock wait states
-	 */
-	unsigned int (*socket_get_timing)(struct sa1100_pcmcia_socket *,
-			unsigned int cpu_speed, unsigned int cmd_time);
-};
-
-struct pcmcia_irqs {
-	int sock;
-	int irq;
-	const char *str;
-};
-
-int sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
-void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
-void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
-void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr);
-
-extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
-extern int sa11xx_drv_pcmcia_remove(struct device *dev);
-
-#endif
diff -puN /dev/null drivers/pcmcia/soc_common.c
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/soc_common.c	2004-05-12 21:00:09.989270080 -0700
@@ -0,0 +1,774 @@
+/*======================================================================
+
+    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
+    except in compliance with the License. You may obtain a copy of
+    the License at http://www.mozilla.org/MPL/
+
+    Software distributed under the License is distributed on an "AS
+    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+    implied. See the License for the specific language governing
+    rights and limitations under the License.
+
+    The initial developer of the original code is John G. Dorsey
+    <john+@cs.cmu.edu>.  Portions created by John G. Dorsey are
+    Copyright (C) 1999 John G. Dorsey.  All Rights Reserved.
+
+    Alternatively, the contents of this file may be used under the
+    terms of the GNU Public License version 2 (the "GPL"), in which
+    case the provisions of the GPL are applicable instead of the
+    above.  If you wish to allow the use of your version of this file
+    only under the terms of the GPL and not to allow others to use
+    your version of this file under the MPL, indicate your decision
+    by deleting the provisions above and replace them with the notice
+    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.
+
+======================================================================*/
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "soc_common.h"
+
+#ifdef DEBUG
+
+static int pc_debug;
+module_param(pc_debug, int, 0644);
+
+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);
+	}
+}
+
+#endif
+
+#define to_soc_pcmcia_socket(x)	container_of(x, struct soc_pcmcia_socket, socket)
+
+static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
+{
+	struct pcmcia_state state;
+	unsigned int stat;
+
+	memset(&state, 0, sizeof(struct pcmcia_state));
+
+	skt->ops->socket_state(skt, &state);
+
+	stat = state.detect  ? SS_DETECT : 0;
+	stat |= state.ready  ? SS_READY  : 0;
+	stat |= state.wrprot ? SS_WRPROT : 0;
+	stat |= state.vs_3v  ? SS_3VCARD : 0;
+	stat |= state.vs_Xv  ? SS_XVCARD : 0;
+
+	/* The power status of individual sockets is not available
+	 * explicitly from the hardware, so we just remember the state
+	 * and regurgitate it upon request:
+	 */
+	stat |= skt->cs_state.Vcc ? SS_POWERON : 0;
+
+	if (skt->cs_state.flags & SS_IOCARD)
+		stat |= state.bvd1 ? SS_STSCHG : 0;
+	else {
+		if (state.bvd1 == 0)
+			stat |= SS_BATDEAD;
+		else if (state.bvd2 == 0)
+			stat |= SS_BATWARN;
+	}
+	return stat;
+}
+
+/*
+ * soc_common_pcmcia_config_skt
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * Convert PCMCIA socket state to our socket configure structure.
+ */
+static int
+soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+{
+	int ret;
+
+	ret = skt->ops->configure_socket(skt, state);
+	if (ret == 0) {
+		/*
+		 * This really needs a better solution.  The IRQ
+		 * may or may not be claimed by the driver.
+		 */
+		if (skt->irq_state != 1 && state->io_irq) {
+			skt->irq_state = 1;
+			set_irq_type(skt->irq, IRQT_FALLING);
+		} else if (skt->irq_state == 1 && state->io_irq == 0) {
+			skt->irq_state = 0;
+			set_irq_type(skt->irq, IRQT_NOEDGE);
+		}
+
+		skt->cs_state = *state;
+	}
+
+	if (ret < 0)
+		printk(KERN_ERR "soc_common_pcmcia: unable to configure "
+		       "socket %d\n", skt->nr);
+
+	return ret;
+}
+
+/* soc_common_pcmcia_sock_init()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * (Re-)Initialise the socket, turning on status interrupts
+ * and PCMCIA bus.  This must wait for power to stabilise
+ * so that the card status signals report correctly.
+ *
+ * Returns: 0
+ */
+static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
+{
+	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
+
+	debug(skt, 2, "initializing socket\n");
+
+	skt->ops->socket_init(skt);
+	return 0;
+}
+
+
+/*
+ * 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 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);
+
+	return ret;
+}
+
+static spinlock_t status_lock = SPIN_LOCK_UNLOCKED;
+
+static void soc_common_check_status(struct soc_pcmcia_socket *skt)
+{
+	unsigned int events;
+
+	debug(skt, 4, "entering PCMCIA monitoring thread\n");
+
+	do {
+		unsigned int status;
+		unsigned long flags;
+
+		status = soc_common_pcmcia_skt_state(skt);
+
+		spin_lock_irqsave(&status_lock, flags);
+		events = (status ^ skt->status) & skt->cs_state.csc_mask;
+		skt->status = status;
+		spin_unlock_irqrestore(&status_lock, flags);
+
+		debug(skt, 4, "events: %s%s%s%s%s%s\n",
+			events == 0         ? "<NONE>"   : "",
+			events & SS_DETECT  ? "DETECT "  : "",
+			events & SS_READY   ? "READY "   : "",
+			events & SS_BATDEAD ? "BATDEAD " : "",
+			events & SS_BATWARN ? "BATWARN " : "",
+			events & SS_STSCHG  ? "STSCHG "  : "");
+
+		if (events)
+			pcmcia_parse_events(&skt->socket, events);
+	} while (events);
+}
+
+/* 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 soc_pcmcia_socket *skt = (struct soc_pcmcia_socket *)dummy;
+	debug(skt, 4, "polling for events\n");
+
+	mod_timer(&skt->poll_timer, jiffies + SOC_PCMCIA_POLL_PERIOD);
+
+	soc_common_check_status(skt);
+}
+
+
+/*
+ * Service routine for socket driver interrupts (requested by the
+ * low-level PCMCIA init() operation via soc_common_pcmcia_thread()).
+ * The actual interrupt-servicing work is performed by
+ * 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 soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	struct soc_pcmcia_socket *skt = dev;
+
+	debug(skt, 3, "servicing IRQ %d\n", irq);
+
+	soc_common_check_status(skt);
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ *  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.
+ *
+ * As a debugging note, during card startup, the PCMCIA core issues
+ * three set_socket() commands in a row the first with RESET deasserted,
+ * the second with RESET asserted, and the last with RESET deasserted
+ * again. Following the third set_socket(), a get_status() command will
+ * be issued. The kernel is looking for the SS_READY flag (see
+ * setup_socket(), reset_socket(), and unreset_socket() in cs.c).
+ *
+ * Returns: 0
+ */
+static int
+soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
+{
+	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
+
+	skt->status = soc_common_pcmcia_skt_state(skt);
+	*status = skt->status;
+
+	return 0;
+}
+
+
+/*
+ * 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)
+{
+	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)?"<NONE> ":"",
+			(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)?"<NONE> ":"",
+			(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
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int
+soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+{
+	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",
+		map->map, map->speed, map->start, map->stop);
+	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
+		(map->flags==0)?"<NONE>":"",
+		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+		(map->flags&MAP_16BIT)?"16BIT ":"",
+		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+		(map->flags&MAP_0WS)?"0WS ":"",
+		(map->flags&MAP_WRPROT)?"WRPROT ":"",
+		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
+		(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+
+	if (map->map >= MAX_IO_WIN) {
+		printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
+		       map->map);
+		return -1;
+	}
+
+	if (map->flags & MAP_ACTIVE) {
+		if (speed == 0)
+			speed = SOC_PCMCIA_IO_ACCESS;
+	} else {
+		speed = 0;
+	}
+
+	skt->spd_io[map->map] = speed;
+	skt->ops->set_timing(skt);
+
+	if (map->stop == 1)
+		map->stop = PAGE_SIZE-1;
+
+	map->stop -= map->start;
+	map->stop += (unsigned long)skt->virt_io;
+	map->start = (unsigned long)skt->virt_io;
+
+	return 0;
+}
+
+
+/*
+ * 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
+ * supplied by Card Services.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int
+soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+{
+	struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
+	struct resource *res;
+	unsigned short speed = map->speed;
+
+	debug(skt, 2, "map %u speed %u card_start %08x\n",
+		map->map, map->speed, map->card_start);
+	debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
+		(map->flags==0)?"<NONE>":"",
+		(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
+		(map->flags&MAP_16BIT)?"16BIT ":"",
+		(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
+		(map->flags&MAP_0WS)?"0WS ":"",
+		(map->flags&MAP_WRPROT)?"WRPROT ":"",
+		(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
+		(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+
+	if (map->map >= MAX_WIN)
+		return -EINVAL;
+
+	if (map->flags & MAP_ACTIVE) {
+		if (speed == 0)
+			speed = 300;
+	} else {
+		speed = 0;
+	}
+
+	if (map->flags & MAP_ATTRIB) {
+		res = &skt->res_attr;
+		skt->spd_attr[map->map] = speed;
+		skt->spd_mem[map->map] = 0;
+	} else {
+		res = &skt->res_mem;
+		skt->spd_attr[map->map] = 0;
+		skt->spd_mem[map->map] = speed;
+	}
+
+	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;
+
+	return 0;
+}
+
+struct bittbl {
+	unsigned int mask;
+	const char *name;
+};
+
+static struct bittbl status_bits[] = {
+	{ SS_WRPROT,		"SS_WRPROT"	},
+	{ SS_BATDEAD,		"SS_BATDEAD"	},
+	{ SS_BATWARN,		"SS_BATWARN"	},
+	{ SS_READY,		"SS_READY"	},
+	{ SS_DETECT,		"SS_DETECT"	},
+	{ SS_POWERON,		"SS_POWERON"	},
+	{ SS_STSCHG,		"SS_STSCHG"	},
+	{ SS_3VCARD,		"SS_3VCARD"	},
+	{ SS_XVCARD,		"SS_XVCARD"	},
+};
+
+static struct bittbl conf_bits[] = {
+	{ SS_PWR_AUTO,		"SS_PWR_AUTO"	},
+	{ SS_IOCARD,		"SS_IOCARD"	},
+	{ SS_RESET,		"SS_RESET"	},
+	{ SS_DMA_MODE,		"SS_DMA_MODE"	},
+	{ SS_SPKR_ENA,		"SS_SPKR_ENA"	},
+	{ SS_OUTPUT_ENA,	"SS_OUTPUT_ENA"	},
+};
+
+static void
+dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+{
+	char *b = *p;
+	int i;
+
+	b += sprintf(b, "%-9s:", prefix);
+	for (i = 0; i < sz; i++)
+		if (val & bits[i].mask)
+			b += sprintf(b, " %s", bits[i].name);
+	*b++ = '\n';
+	*p = b;
+}
+
+/*
+ * 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 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);
+
+	dump_bits(&p, "status", skt->status,
+		  status_bits, ARRAY_SIZE(status_bits));
+	dump_bits(&p, "csc_mask", skt->cs_state.csc_mask,
+		  status_bits, ARRAY_SIZE(status_bits));
+	dump_bits(&p, "cs_flags", skt->cs_state.flags,
+		  conf_bits, ARRAY_SIZE(conf_bits));
+
+	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);
+	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 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 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, soc_common_pcmcia_interrupt,
+				  SA_INTERRUPT, irqs[i].str, skt);
+		if (res)
+			break;
+		set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+	}
+
+	if (res) {
+		printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n",
+			irqs[i].irq, res);
+
+		while (i--)
+			if (irqs[i].sock == skt->nr)
+				free_irq(irqs[i].irq, skt);
+	}
+	return res;
+}
+EXPORT_SYMBOL(soc_pcmcia_request_irqs);
+
+void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt,
+			  struct pcmcia_irqs *irqs, int nr)
+{
+	int i;
+
+	for (i = 0; i < nr; i++)
+		if (irqs[i].sock == skt->nr)
+			free_irq(irqs[i].irq, skt);
+}
+EXPORT_SYMBOL(soc_pcmcia_free_irqs);
+
+void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
+			     struct pcmcia_irqs *irqs, int nr)
+{
+	int i;
+
+	for (i = 0; i < nr; i++)
+		if (irqs[i].sock == skt->nr)
+			set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+}
+EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
+
+void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
+			    struct pcmcia_irqs *irqs, int nr)
+{
+	int i;
+
+	for (i = 0; i < nr; i++)
+		if (irqs[i].sock == skt->nr) {
+			set_irq_type(irqs[i].irq, IRQT_RISING);
+			set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
+		}
+}
+EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
+
+
+LIST_HEAD(soc_pcmcia_sockets);
+DECLARE_MUTEX(soc_pcmcia_sockets_lock);
+
+static const char *skt_names[] = {
+	"PCMCIA socket 0",
+	"PCMCIA socket 1",
+};
+
+struct skt_dev_info {
+	int nskt;
+	struct soc_pcmcia_socket skt[0];
+};
+
+#define SKT_DEV_INFO_SIZE(n) \
+	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
+
+int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
+{
+	struct skt_dev_info *sinfo;
+	int ret, i;
+
+	down(&soc_pcmcia_sockets_lock);
+
+	sinfo = kmalloc(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->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 = soc_common_pcmcia_poll_event;
+		skt->poll_timer.data = (unsigned long)skt;
+		skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
+
+		skt->nr		= first + i;
+		skt->irq	= NO_IRQ;
+		skt->dev	= dev;
+		skt->ops	= ops;
+
+		skt->res_skt.start	= _PCMCIA(skt->nr);
+		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1;
+		skt->res_skt.name	= skt_names[skt->nr];
+		skt->res_skt.flags	= IORESOURCE_MEM;
+
+		ret = request_resource(&iomem_resource, &skt->res_skt);
+		if (ret)
+			goto out_err_1;
+
+		skt->res_io.start	= _PCMCIAIO(skt->nr);
+		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1;
+		skt->res_io.name	= "io";
+		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		ret = request_resource(&skt->res_skt, &skt->res_io);
+		if (ret)
+			goto out_err_2;
+
+		skt->res_mem.start	= _PCMCIAMem(skt->nr);
+		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1;
+		skt->res_mem.name	= "memory";
+		skt->res_mem.flags	= IORESOURCE_MEM;
+
+		ret = request_resource(&skt->res_skt, &skt->res_mem);
+		if (ret)
+			goto out_err_3;
+
+		skt->res_attr.start	= _PCMCIAAttr(skt->nr);
+		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;
+
+		skt->virt_io = ioremap(skt->res_io.start, 0x10000);
+		if (skt->virt_io == NULL) {
+			ret = -ENOMEM;
+			goto out_err_5;
+		}
+
+		list_add(&skt->node, &soc_pcmcia_sockets);
+
+		/*
+		 * We initialize default socket timing here, because
+		 * we are not guaranteed to see a SetIOMap operation at
+		 * runtime.
+		 */
+		ops->set_timing(skt);
+
+		ret = ops->hw_init(skt);
+		if (ret)
+			goto out_err_6;
+
+		skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
+		skt->socket.irq_mask = 0;
+		skt->socket.map_size = PAGE_SIZE;
+		skt->socket.pci_irq = skt->irq;
+		skt->socket.io_offset = (unsigned long)skt->virt_io;
+
+		skt->status = soc_common_pcmcia_skt_state(skt);
+
+		ret = pcmcia_register_socket(&skt->socket);
+		if (ret)
+			goto out_err_7;
+
+		WARN_ON(skt->socket.sock != i);
+
+		add_timer(&skt->poll_timer);
+
+		class_device_create_file(&skt->socket.dev, &class_device_attr_status);
+	}
+
+	dev_set_drvdata(dev, sinfo);
+	ret = 0;
+	goto out;
+
+	do {
+		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+
+		del_timer_sync(&skt->poll_timer);
+		pcmcia_unregister_socket(&skt->socket);
+
+ out_err_7:
+		flush_scheduled_work();
+
+		ops->hw_shutdown(skt);
+ out_err_6:
+ 		list_del(&skt->node);
+		iounmap(skt->virt_io);
+ out_err_5:
+		release_resource(&skt->res_attr);
+ out_err_4:
+		release_resource(&skt->res_mem);
+ out_err_3:
+		release_resource(&skt->res_io);
+ out_err_2:
+		release_resource(&skt->res_skt);
+ out_err_1:
+		i--;
+	} while (i > 0);
+
+	kfree(sinfo);
+
+ out:
+	up(&soc_pcmcia_sockets_lock);
+	return ret;
+}
+
+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(&soc_pcmcia_sockets_lock);
+	for (i = 0; i < sinfo->nskt; i++) {
+		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+
+		del_timer_sync(&skt->poll_timer);
+
+		pcmcia_unregister_socket(&skt->socket);
+
+		flush_scheduled_work();
+
+		skt->ops->hw_shutdown(skt);
+
+		soc_common_pcmcia_config_skt(skt, &dead_socket);
+
+		list_del(&skt->node);
+		iounmap(skt->virt_io);
+		skt->virt_io = NULL;
+		release_resource(&skt->res_attr);
+		release_resource(&skt->res_mem);
+		release_resource(&skt->res_io);
+		release_resource(&skt->res_skt);
+	}
+	up(&soc_pcmcia_sockets_lock);
+
+	kfree(sinfo);
+
+	return 0;
+}
diff -puN /dev/null drivers/pcmcia/soc_common.h
--- /dev/null	2003-09-15 06:40:47.000000000 -0700
+++ 25-akpm/drivers/pcmcia/soc_common.h	2004-05-12 21:00:09.990269928 -0700
@@ -0,0 +1,179 @@
+/*
+ * linux/drivers/pcmcia/soc_common.h
+ *
+ * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
+ *
+ * This file contains definitions for the PCMCIA support code common to
+ * integrated SOCs like the SA-11x0 and PXA2xx microprocessors.
+ */
+#ifndef _ASM_ARCH_PCMCIA
+#define _ASM_ARCH_PCMCIA
+
+/* include the world */
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+
+struct device;
+struct pcmcia_low_level;
+
+/*
+ * This structure encapsulates per-socket state which we might need to
+ * use when responding to a Card Services query of some kind.
+ */
+struct soc_pcmcia_socket {
+	struct pcmcia_socket	socket;
+
+	/*
+	 * Info from low level handler
+	 */
+	struct device		*dev;
+	unsigned int		nr;
+	unsigned int		irq;
+
+	/*
+	 * Core PCMCIA state
+	 */
+	struct pcmcia_low_level *ops;
+
+	unsigned int		status;
+	socket_state_t		cs_state;
+
+	unsigned short		spd_io[MAX_IO_WIN];
+	unsigned short		spd_mem[MAX_WIN];
+	unsigned short		spd_attr[MAX_WIN];
+
+	struct resource		res_skt;
+	struct resource		res_io;
+	struct resource		res_mem;
+	struct resource		res_attr;
+	void			*virt_io;
+
+	unsigned int		irq_state;
+
+	struct timer_list	poll_timer;
+	struct list_head	node;
+};
+
+struct pcmcia_state {
+  unsigned detect: 1,
+            ready: 1,
+             bvd1: 1,
+             bvd2: 1,
+           wrprot: 1,
+            vs_3v: 1,
+            vs_Xv: 1;
+};
+
+struct pcmcia_low_level {
+	struct module *owner;
+
+	/* first socket in system */
+	int first;
+	/* nr of sockets */
+	int nr;
+
+	int (*hw_init)(struct soc_pcmcia_socket *);
+	void (*hw_shutdown)(struct soc_pcmcia_socket *);
+
+	void (*socket_state)(struct soc_pcmcia_socket *, struct pcmcia_state *);
+	int (*configure_socket)(struct soc_pcmcia_socket *, const socket_state_t *);
+
+	/*
+	 * Enable card status IRQs on (re-)initialisation.  This can
+	 * be called at initialisation, power management event, or
+	 * pcmcia event.
+	 */
+	void (*socket_init)(struct soc_pcmcia_socket *);
+
+	/*
+	 * Disable card status IRQs and PCMCIA bus on suspend.
+	 */
+	void (*socket_suspend)(struct soc_pcmcia_socket *);
+
+	/*
+	 * Hardware specific timing routines.
+	 * If provided, the get_timing routine overrides the SOC default.
+	 */
+	unsigned int (*get_timing)(struct soc_pcmcia_socket *, unsigned int, unsigned int);
+	int (*set_timing)(struct soc_pcmcia_socket *);
+	int (*show_timing)(struct soc_pcmcia_socket *, char *);
+};
+
+
+struct pcmcia_irqs {
+	int sock;
+	int irq;
+	const char *str;
+};
+
+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 struct list_head soc_pcmcia_sockets;
+extern struct semaphore soc_pcmcia_sockets_lock;
+
+extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
+extern int soc_common_drv_pcmcia_remove(struct device *dev);
+
+
+#ifdef DEBUG
+
+extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
+			     int lvl, const char *fmt, ...);
+
+#define debug(skt, lvl, fmt, arg...) \
+	soc_pcmcia_debug(skt, __func__, lvl, fmt , ## arg)
+
+#else
+#define debug(skt, lvl, fmt, arg...) do { } while (0)
+#endif
+
+
+/*
+ * The PC Card Standard, Release 7, section 4.13.4, says that twIORD
+ * has a minimum value of 165ns. Section 4.13.5 says that twIOWR has
+ * a minimum value of 165ns, as well. Section 4.7.2 (describing
+ * common and attribute memory write timing) says that twWE has a
+ * minimum value of 150ns for a 250ns cycle time (for 5V operation;
+ * see section 4.7.4), or 300ns for a 600ns cycle time (for 3.3V
+ * operation, also section 4.7.4). Section 4.7.3 says that taOE
+ * has a maximum value of 150ns for a 300ns cycle time (for 5V
+ * operation), or 300ns for a 600ns cycle time (for 3.3V operation).
+ *
+ * When configuring memory maps, Card Services appears to adopt the policy
+ * that a memory access time of "0" means "use the default." The default
+ * PCMCIA I/O command width time is 165ns. The default PCMCIA 5V attribute
+ * and memory command width time is 150ns; the PCMCIA 3.3V attribute and
+ * memory command width time is 300ns.
+ */
+#define SOC_PCMCIA_IO_ACCESS		(165)
+#define SOC_PCMCIA_5V_MEM_ACCESS	(150)
+#define SOC_PCMCIA_3V_MEM_ACCESS	(300)
+#define SOC_PCMCIA_ATTR_MEM_ACCESS	(300)
+
+/*
+ * The socket driver actually works nicely in interrupt-driven form,
+ * so the (relatively infrequent) polling is "just to be sure."
+ */
+#define SOC_PCMCIA_POLL_PERIOD    (2*HZ)
+
+
+/* I/O pins replacing memory pins
+ * (PCMCIA System Architecture, 2nd ed., by Don Anderson, p.75)
+ *
+ * These signals change meaning when going from memory-only to
+ * memory-or-I/O interface:
+ */
+#define iostschg bvd1
+#define iospkr   bvd2
+
+#endif
diff -puN include/asm-arm/arch-pxa/pxa-regs.h~bk-pcmcia include/asm-arm/arch-pxa/pxa-regs.h
--- 25/include/asm-arm/arch-pxa/pxa-regs.h~bk-pcmcia	2004-05-12 21:00:07.632628344 -0700
+++ 25-akpm/include/asm-arm/arch-pxa/pxa-regs.h	2004-05-12 21:00:09.992269624 -0700
@@ -1336,6 +1336,19 @@ typedef void            (*ExcpHndlr) (vo
 #define MDMRS		__REG(0x48000040)  /* MRS value to be written to SDRAM */
 #define BOOT_DEF	__REG(0x48000044)  /* Read-Only Boot-Time Register. Contains BOOT_SEL and PKG_SEL */
 
+/*
+ * More handy macros for PCMCIA
+ *
+ * Arg is socket number
+ */
+#define MCMEM(s)	__REG2(0x48000028, (s)<<2 )  /* Card interface Common Memory Space Socket s Timing */
+#define MCATT(s)	__REG2(0x48000030, (s)<<2 )  /* Card interface Attribute Space Socket s Timing Configuration */
+#define MCIO(s)		__REG2(0x48000038, (s)<<2 )  /* Card interface I/O Space Socket s Timing Configuration */
+
+/* MECR register defines */
+#define MECR_NOS	(1 << 0)	/* Number Of Sockets: 0 -> 1 sock, 1 -> 2 sock */
+#define MECR_CIT	(1 << 1)	/* Card Is There: 0 -> no card, 1 -> card inserted */
+
 #define MDREFR_K2FREE	(1 << 25)	/* SDRAM Free-Running Control */
 #define MDREFR_K1FREE	(1 << 24)	/* SDRAM Free-Running Control */
 #define MDREFR_K0FREE	(1 << 23)	/* SDRAM Free-Running Control */

_
