--- /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 -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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 and Ian Molton "); +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 +#include +#include +#include +#include +#include + +#include +#include + +#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 #include -#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 - . 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 -#include -#include -#include -#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 + . 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 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 "); +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 + . 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 - * - * 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 -#include -#include -#include -#include -#include -#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 + . 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 ? "" : "", + 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)?" ":"", + (state->csc_mask&SS_DETECT)?"DETECT ":"", + (state->csc_mask&SS_READY)?"READY ":"", + (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"", + (state->csc_mask&SS_BATWARN)?"BATWARN ":"", + (state->csc_mask&SS_STSCHG)?"STSCHG ":"", + (state->flags==0)?" ":"", + (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"", + (state->flags&SS_IOCARD)?"IOCARD ":"", + (state->flags&SS_RESET)?"RESET ":"", + (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"", + (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"", + state->Vcc, state->Vpp, state->io_irq); + + return soc_common_pcmcia_config_skt(skt, state); +} + + +/* + * Implements the set_io_map() operation for the in-kernel PCMCIA + * service (formerly SS_SetIOMap in Card Services). We configure + * the map speed as requested, but override the address ranges + * 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)?"":"", + (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)?"":"", + (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 + * + * 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 +#include +#include +#include +#include +#include +#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 */ _