Commit 73b5d164 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents ba1abdbf 3bfc2601
Kernel Low-Level PCMCIA Interface Documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
John G Dorsey <john+@cs.cmu.edu>
Updated: 30 June, 2000
Note: this interface has not been finalized!
See also: http://www.cs.cmu.edu/~wearable/software/pcmcia-arm.html
Introduction
Early versions of PCMCIA Card Services for StrongARM were designed to
permit a single socket driver to run on a variety of SA-1100 boards by
using a userland configuration process. During the conversion to the 2.3
kernel series, all of the configuration has moved into sub-drivers in the
kernel proper (see linux/drivers/pcmcia/sa1100*). This document describes
the low-level interface between those sub-drivers and the sa1100 socket
driver module.
Presently, there are six operations which must be provided by the
board-specific code. Only functions whose implementation is likely to
differ across board designs are required at this level. Some examples
include:
- configuring card detect lines to generate interrupts
- sensing the legal voltage levels for inserted cards
- asserting the reset signal for a card
Functions which are assumed to be the same across all designs are
performed within the generic socket driver itself. Some examples of these
kinds of operations include:
- configuring memory access times based on the core clock frequency
- reads/writes on memory, byte swizzling, ...
The current implementation allows the specific per-board set of low-level
operations to be determined at run time. For each specific board, the
following structure should be filled in:
struct pcmcia_low_level {
int (*init)(struct pcmcia_init *);
int (*shutdown)(void);
int (*socket_state)(struct pcmcia_state_array *);
int (*get_irq_info)(struct pcmcia_irq_info *);
int (*configure_socket)(const struct pcmcia_configure *);
};
The component functions are described in detail below. Using the
machine_is_*() tests, the pointer `pcmcia_low_level' should be assigned to
the location of the table for your board.
0. init(struct pcmcia_init *init)
This operation has three responsibilities:
- perform any board-specific initialization tasks
- associate the given handler with any interrupt-generating signals
such as card detection, or battery voltage detection
- set up any necessary edge detection for card ready signals
Argument passing for this operation is implemented by the following
structure:
struct pcmcia_init {
void (*handler)(int irq, void *dev, struct pt_regs *regs);
struct pcmcia_maps *maps;
};
Here, `handler' is provided by the socket driver, and `maps' must be
modified if the default mapping isn't appropriate. This operation should
return one of two values:
- the highest-numbered socket available, plus one
- a negative number, indicating an error in configuration
Note that the former case is _not_ the same as "the number of sockets
available." In particular, if your design uses SA-1100 slot "one" but
not slot "zero," you MUST report "2" to the socket driver.
1. shutdown(void)
This operation takes no arguments, and will be called during cleanup for
the socket driver module. Any state associated with the socket controller,
including allocated data structures, reserved IRQs, etc. should be
released in this routine.
The return value for this operation is not examined.
2. socket_state(struct pcmcia_state_array *state_array)
This operation will be invoked from the interrupt handler which was set up
in the earlier call to init(). Note, however, that it should not include
any side effects which would be inappropriate if the operation were to
occur when no interrupt is pending. (An extra invocation of this operation
currently takes place to initialize state in the socket driver.)
Argument passing for this operation is handled by a structure which
contains an array of the following type:
struct pcmcia_state {
unsigned detect: 1,
ready: 1,
bvd1: 1,
bvd2: 1,
wrprot: 1,
vs_3v: 1,
vs_Xv: 1;
};
Upon return from the operation, a struct pcmcia_state should be filled in
for each socket available in the hardware. For every array element (up to
`size' in the struct pcmcia_state_saarray) which does not correspond to an
available socket, zero the element bits. (This includes element [0] if
socket zero is not used.)
Regardless of how the various signals are routed to the SA-1100, the bits
in struct pcmcia_state always have the following semantics:
detect - 1 if a card is fully inserted, 0 otherwise
ready - 1 if the card ready signal is asserted, 0 otherwise
bvd1 - the value of the Battery Voltage Detect 1 signal
bvd2 - the value of the Battery Voltage Detect 2 signal
wrprot - 1 if the card is write-protected, 0 otherwise
vs_3v - 1 if the card must be operated at 3.3V, 0 otherwise
vs_Xv - 1 if the card must be operated at X.XV, 0 otherwise
A note about the BVD signals: if your board does not make both lines
directly observable to the processor, just return reasonable values. The
standard interpretation of the BVD signals is:
BVD1 BVD2
0 x battery is dead
1 0 battery warning
1 1 battery ok
Regarding the voltage sense flags (vs_3v, vs_Xv), these bits should be set
based on a sampling of the Voltage Sense pins, if available. The standard
interpretation of the VS signals (for a "low-voltage" socket) is:
VS1 VS2
0 0 X.XV, else 3.3V, else none
0 1 3.3V, else none
1 0 X.XV, else none
1 1 5V, else none
More information about the BVD and VS conventions is available in chapter
5 of "PCMCIA System Architecture," 2nd ed., by Don Anderson.
This operation should return 1 if an IRQ is actually pending for the
socket controller, 0 if no IRQ is pending (but no error condition exists,
such as an undersized state array), or -1 on any error.
3. get_irq_info(struct pcmcia_irq_info *info)
This operation obtains the IRQ assignment which is legal for the given
socket. An argument of the following type is passed:
struct pcmcia_irq_info {
unsigned int sock;
unsigned int irq ;
};
The `sock' field contains the socket index being queried. The `irq' field
should contain the IRQ number corresponding to the card ready signal from
the device.
This operation should return 0 on success, or -1 on any error.
4. configure_socket(const struct pcmcia_configure *configure)
This operation allows the caller to apply power to the socket, issue a
reset, or enable various outputs. The argument is of the following type:
struct pcmcia_configure {
unsigned sock: 8,
vcc: 8,
vpp: 8,
output: 1,
speaker: 1,
reset: 1;
};
The `sock' field contains the index of the socket to be configured. The
`vcc' and `vpp' fields contain the voltages to be applied for Vcc and Vpp,
respectively, in units of 0.1V. (Note that vpp==120 indicates that
programming voltage should be applied.)
The two output enables, `output' and `speaker', refer to the card data
signal enable and the card speaker enable, respectively. The `reset' bit,
when set, indicates that the card reset should be asserted.
This operation should return 0 on success, or -1 on any error.
Board-Specific Notes
The following information is known about various SA-11x0 board designs
which may be used as reference while adding support to the kernel.
Carnegie Mellon Itsy/Cue (http://www.cs.cmu.edu/~wearable/itsy/)
Itsy Chip Select 3 (CS3) Interface
("ITSY MEMORY/PCMCIA ADD-ON BOARD with BATTERY and CHARGER CIRCUITRY,"
memo dated 5-20-99, from Tim Manns to Richard Martin, et. al)
Read:
ABVD2 (SS)D0 A slot, Battery Voltage Detect
ABVD1 (SS)D1
AVSS2 (SS)D2 A slot, Voltage Sense
AVSS1 (SS)D3
GND (SS)D4
GND (SS)D5
GND (SS)D6
GND (SS)D7
BBVD2 (SS)D8 B slot, Battery Voltage Detect
BBVD1 (SS)D9
BVSS2 (SS)D10 B slot, Voltage Sense
BVSS1 (SS)D11
GND (SS)D12
GND (SS)D13
GND (SS)D14
GND (SS)D15
Write:
(SS)D0 A_VPP_VCC LTC1472 VPPEN1
(SS)D1 A_VPP_PGM LTC1472 VPPEN0
(SS)D2 A_VCC_3 LTC1472 VCCEN0
(SS)D3 A_VCC_5 LTC1472 VCCEN1
(SS)D4 RESET (A SLOT)
(SS)D5 GND
(SS)D6 GND
(SS)D7 GND
(SS)D8 B_VPP_VCC LTC1472 VPPEN1
(SS)D9 B_VPP_PGM LTC1472 VPPEN0
(SS)D10 B_VCC_3 LTC1472 VCCEN0
(SS)D11 B_VCC_5 LTC1472 VCCEN1
(SS)D12 RESET (B SLOT)
(SS)D13 GND
(SS)D14 GND
(SS)D15 GND
GPIO pin assignments are as follows: (from schematics)
GPIO 10 Slot 0 Card Detect
GPIO 11 Slot 1 Card Detect
GPIO 12 Slot 0 Ready/Interrupt
GPIO 13 Slot 1 Ready/Interrupt
Intel SA-1100 Multimedia Board (http://developer.intel.com/design/strong/)
CPLD Registers
SA-1100 Multimedia Development Board with Companion SA-1101 Development
Board User's Guide, p.4-42
This SA-1100/1101 development package uses only one GPIO pin (24) to
signal changes in card status, and requires software to inspect a
PCMCIA status register to determine the source.
Read: (PCMCIA Power Sense Register - 0x19400000)
S0VS1 0 Slot 0 voltage sense
S0VS2 1
S0BVD1 2 Slot 0 battery voltage sense
S0BVD2 3
S1VS1 4 Slot 1 voltage sense
S1VS2 5
S1BVD1 6 Slot 1 battery voltage sense
S1BVD2 7
Read/Write: (PCMCIA Power Control Register - 0x19400002)
S0VPP0 0 Slot 0 Vpp
S0VPP1 1
S0VCC0 2 Slot 0 Vcc
S0VCC1 3
S1VPP0 4 Slot 1 Vpp
S1VPP1 5
S1VCC0 6 Slot 1 Vcc
S1VCC1 7
Read: (PCMCIA Status Register - 0x19400004)
S0CD1 0 Slot 0 Card Detect 1
S0RDY 1 Slot 0 Ready/Interrupt
S0STSCHG 2 Slot 0 Status Change
S0Reset 3 Slot 0 Reset (RW)
S1CD1 4 Slot 1 Card Detect 1
S1RDY 5 Slot 1 Ready/Interrupt
S1STSCHG 6 Slot 1 Status Change
S1Reset 7 Slot 1 Reset (RW)
Intel SA-1100 Evaluation Platform (http://developer.intel.com/design/strong/)
Brutus I/O Pins and Chipselect Register
pcmcia-brutus.c, by Ivo Clarysse
(What's the official reference for this info?)
This SA-1100 development board uses more GPIO pins than say, the Itsy
or the SA-1100/1101 multimedia package. The pin assignments are as
follows:
GPIO 2 Slot 0 Battery Voltage Detect 1
GPIO 3 Slot 0 Ready/Interrupt
GPIO 4 Slot 0 Card Detect
GPIO 5 Slot 1 Battery Voltage Detect 1
GPIO 6 Slot 1 Ready/Interrupt
GPIO 7 Slot 1 Card Detect
Like the Itsy, Brutus uses a chipselect register in static memory
bank 3 for the other signals, such as voltage sense or reset:
Read:
P0_VS1 8 Slot 0 Voltage Sense
P0_VS2 9
P0_STSCHG 10 Slot 0 Status Change
P1_VS1 12 Slot 1 Voltage Sense
P1_VS2 13
P1_STSCHG 14 Slot 1 Status Change
Read/Write:
P0_ 16 Slot 0 MAX1600EAI control line
P0_ 17 Slot 0 MAX1600EAI control line
P0_ 18 Slot 0 MAX1600EAI control line
P0_ 19 Slot 0 MAX1600EAI control line
P0_ 20 Slot 0 12V
P0_ 21 Slot 0 Vpp to Vcc (CONFIRM?)
P0_ 22 Slot 0 enable fan-out drivers & xcvrs
P0_SW_RST 23 Slot 0 Reset
P1_ 24 Slot 1 MAX1600EAI control line
P1_ 25 Slot 1 MAX1600EAI control line
P1_ 26 Slot 1 MAX1600EAI control line
P1_ 27 Slot 1 MAX1600EAI control line
P1_ 28 Slot 1 12V
P1_ 29 Slot 1 Vpp to Vcc (CONFIRM?)
P1_ 30 Slot 1 enable fan-out drivers & xcvrs
P1_SW_RST 31 Slot 1 Reset
For each slot, the bits labelled "MAX1600EAI" should (apparently)
be written with the value 0101 for Vcc 3.3V, and 1001 for Vcc 5V.
Intel SA-1110 Development Platform (http://developer.intel.com/design/strong/)
GPIO Pin Descriptions and Board Control Register
SA-1110 Microprocessor Development Board User's Guide, p.4-7, 4-10
The Assabet board contains only a single Compact Flash slot,
attached to slot 1 on the SA-1110. Card detect, ready, and BVD
signals are routed through GPIO, with power and reset placed in a
control register. Note that the CF bus must be enabled before use.
GPIO 21 Slot 1 Compact Flash interrupt
GPIO 22 Slot 1 card detect (CD1 NOR CD2)
GPIO 24 Slot 1 Battery Voltage Detect 2
GPIO 25 Slot 1 Battery Voltage Detect 1
Write-only: (Board Control Register - 0x12000000)
CF_PWR 0 CF bus power (3.3V)
CF_RST 1 CF reset
CF_Bus_On 7 CF bus enable
......@@ -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
......
......@@ -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) += sa1100_simpad.o
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
/*======================================================================
Device driver for the PCMCIA control functionality of PXA2xx
microprocessors.
The contents of this file may be used under the
terms of the GNU Public License version 2 (the "GPL")
(c) Ian Molton (spyro@f2s.com) 2003
(c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
derived from sa11xx_base.c
Portions created by John G. Dorsey are
Copyright (C) 1999 John G. Dorsey.
======================================================================*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/cpufreq.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
#include "soc_common.h"
#include "pxa2xx_base.h"
#define MCXX_SETUP_MASK (0x7f)
#define MCXX_ASST_MASK (0x1f)
#define MCXX_HOLD_MASK (0x3f)
#define MCXX_SETUP_SHIFT (0)
#define MCXX_ASST_SHIFT (7)
#define MCXX_HOLD_SHIFT (14)
static inline u_int pxa2xx_mcxx_hold(u_int pcmcia_cycle_ns,
u_int mem_clk_10khz)
{
u_int code = pcmcia_cycle_ns * mem_clk_10khz;
return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
}
static inline u_int pxa2xx_mcxx_asst(u_int pcmcia_cycle_ns,
u_int mem_clk_10khz)
{
u_int code = pcmcia_cycle_ns * mem_clk_10khz;
return (code / 300000) + ((code % 300000) ? 1 : 0) - 1;
}
static inline u_int pxa2xx_mcxx_setup(u_int pcmcia_cycle_ns,
u_int mem_clk_10khz)
{
u_int code = pcmcia_cycle_ns * mem_clk_10khz;
return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
}
/* This function returns the (approximate) command assertion period, in
* nanoseconds, for a given CPU clock frequency and MCXX_ASST value:
*/
static inline u_int pxa2xx_pcmcia_cmd_time(u_int mem_clk_10khz,
u_int pcmcia_mcxx_asst)
{
return (300000 * (pcmcia_mcxx_asst + 1) / mem_clk_10khz);
}
static int pxa2xx_pcmcia_set_mcmem( int sock, int speed, int clock )
{
MCMEM(sock) = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
return 0;
}
static int pxa2xx_pcmcia_set_mcio( int sock, int speed, int clock )
{
MCIO(sock) = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
return 0;
}
static int pxa2xx_pcmcia_set_mcatt( int sock, int speed, int clock )
{
MCATT(sock) = ((pxa2xx_mcxx_setup(speed, clock)
& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
| ((pxa2xx_mcxx_asst(speed, clock)
& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
| ((pxa2xx_mcxx_hold(speed, clock)
& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
return 0;
}
static int pxa2xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int lclk)
{
int sock = skt->nr;
pxa2xx_pcmcia_set_mcmem( sock, SOC_PCMCIA_5V_MEM_ACCESS, lclk );
pxa2xx_pcmcia_set_mcatt( sock, SOC_PCMCIA_ATTR_MEM_ACCESS, lclk );
pxa2xx_pcmcia_set_mcio( sock, SOC_PCMCIA_IO_ACCESS, lclk );
return 0;
}
static int pxa2xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
{
unsigned int lclk = get_lclk_frequency_10khz();
return pxa2xx_pcmcia_set_mcxx(skt, lclk);
}
int pxa2xx_drv_pcmcia_probe(struct device *dev)
{
int ret;
struct pcmcia_low_level *ops;
int first, nr;
if (!dev || !dev->platform_data)
return -ENODEV;
ops = (struct pcmcia_low_level *)dev->platform_data;
first = ops->first;
nr = ops->nr;
/* Setup GPIOs for PCMCIA/CF alternate function mode.
*
* It would be nice if set_GPIO_mode included support
* for driving GPIO outputs to default high/low state
* before programming GPIOs as outputs. Setting GPIO
* outputs to default high/low state via GPSR/GPCR
* before defining them as outputs should reduce
* the possibility of glitching outputs during GPIO
* setup. This of course assumes external terminators
* are present to hold GPIOs in a defined state.
*
* In the meantime, setup default state of GPIO
* outputs before we enable them as outputs.
*/
GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
GPIO_bit(GPIO49_nPWE) |
GPIO_bit(GPIO50_nPIOR) |
GPIO_bit(GPIO51_nPIOW) |
GPIO_bit(GPIO52_nPCE_1) |
GPIO_bit(GPIO53_nPCE_2);
pxa_gpio_mode(GPIO48_nPOE_MD);
pxa_gpio_mode(GPIO49_nPWE_MD);
pxa_gpio_mode(GPIO50_nPIOR_MD);
pxa_gpio_mode(GPIO51_nPIOW_MD);
pxa_gpio_mode(GPIO52_nPCE_1_MD);
pxa_gpio_mode(GPIO53_nPCE_2_MD);
pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
pxa_gpio_mode(GPIO55_nPREG_MD);
pxa_gpio_mode(GPIO56_nPWAIT_MD);
pxa_gpio_mode(GPIO57_nIOIS16_MD);
/* Provide our PXA2xx specific timing routines. */
ops->set_timing = pxa2xx_pcmcia_set_timing;
ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
if (ret == 0) {
/*
* We have at least one socket, so set MECR:CIT
* (Card Is There)
*/
MECR |= MECR_CIT;
/* Set MECR:NOS (Number Of Sockets) */
if (nr > 1)
MECR |= MECR_NOS;
else
MECR &= ~MECR_NOS;
}
return ret;
}
EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe);
static int pxa2xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level)
{
int ret = 0;
if (level == SUSPEND_SAVE_STATE)
ret = pcmcia_socket_dev_suspend(dev, state);
return ret;
}
static int pxa2xx_drv_pcmcia_resume(struct device *dev, u32 level)
{
int ret = 0;
if (level == RESUME_RESTORE_STATE)
ret = pcmcia_socket_dev_resume(dev);
return ret;
}
static struct device_driver pxa2xx_pcmcia_driver = {
.probe = pxa2xx_drv_pcmcia_probe,
.remove = soc_common_drv_pcmcia_remove,
.suspend = pxa2xx_drv_pcmcia_suspend,
.resume = pxa2xx_drv_pcmcia_resume,
.name = "pxa2xx-pcmcia",
.bus = &platform_bus_type,
};
#ifdef CONFIG_CPU_FREQ
/*
* When pxa2xx_pcmcia_notifier() decides that a MC{IO,MEM,ATT} adjustment (due
* to a core clock frequency change) is needed, this routine establishes
* new values consistent with the clock speed `clock'.
*/
static void pxa2xx_pcmcia_update_mcxx(unsigned int clock)
{
struct soc_pcmcia_socket *skt;
down(&soc_sockets_lock);
list_for_each_entry(skt, &soc_sockets, node) {
pxa2xx_pcmcia_set_mcio(skt->nr, calc_speed(skt->spd_io,
MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS), clock);
pxa2xx_pcmcia_set_mcmem(skt->nr, calc_speed(skt->spd_io,
MAX_IO_WIN, SOC_PCMCIA_3V_MEM_ACCESS), clock );
pxa2xx_pcmcia_set_mcatt(skt->nr, calc_speed(skt->spd_io,
MAX_IO_WIN, SOC_PCMCIA_3V_MEM_ACCESS), clock );
}
up(&soc_sockets_lock);
}
/*
* When changing the processor L clock frequency, it is necessary
* to adjust the MCXX timings accordingly. We've recorded the timings
* requested by Card Services, so this is just a matter of finding
* out what our current speed is, and then recomputing the new MCXX
* values.
*
* Returns: 0 on success, -1 on error
*/
static int
pxa2xx_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
{
struct cpufreq_freqs *freqs = data;
#warning "it's not clear if this is right since the core CPU (N) clock has no effect on the memory (L) clock"
switch (val) {
case CPUFREQ_PRECHANGE:
if (freqs->new > freqs->old) {
debug( 2, "new frequency %u.%uMHz > %u.%uMHz, "
"pre-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
pxa2xx_pcmcia_update_mcxx(freqs->new);
}
break;
case CPUFREQ_POSTCHANGE:
if (freqs->new < freqs->old) {
debug( 2, "new frequency %u.%uMHz < %u.%uMHz, "
"post-updating\n",
freqs->new / 1000, (freqs->new / 100) % 10,
freqs->old / 1000, (freqs->old / 100) % 10);
pxa2xx_pcmcia_update_mcxx(freqs->new);
}
break;
}
return 0;
}
static struct notifier_block pxa2xx_pcmcia_notifier_block = {
.notifier_call = pxa2xx_pcmcia_notifier
};
static int __init pxa2xx_pcmcia_cpufreq_init(void)
{
int ret;
ret = cpufreq_register_notifier(&pxa2xx_pcmcia_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret < 0)
printk(KERN_ERR "Unable to register CPU frequency change "
"notifier for PCMCIA (%d)\n", ret);
return ret;
}
static void __exit pxa2xx_pcmcia_cpufreq_exit(void)
{
cpufreq_unregister_notifier(&pxa2xx_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
}
#else
#define pxa2xx_pcmcia_cpufreq_init()
#define pxa2xx_pcmcia_cpufreq_exit()
#endif
static int __init pxa2xx_pcmcia_init(void)
{
int ret = driver_register(&pxa2xx_pcmcia_driver);
if (ret == 0)
pxa2xx_pcmcia_cpufreq_init();
return ret;
}
static void __exit pxa2xx_pcmcia_exit(void)
{
pxa2xx_pcmcia_cpufreq_exit();
driver_unregister(&pxa2xx_pcmcia_driver);
}
module_init(pxa2xx_pcmcia_init);
module_exit(pxa2xx_pcmcia_exit);
MODULE_AUTHOR("Stefan Eletzhofer <stefan.eletzhofer@inquant.de> and Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services: PXA2xx core socket driver");
MODULE_LICENSE("GPL");
/* temporary measure */
extern int pxa2xx_drv_pcmcia_probe(struct device *);
/*
* linux/drivers/pcmcia/pxa2xx_lubbock.c
*
* Author: George Davis
* Created: Jan 10, 2002
* Copyright: MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
*
* Lubbock PCMCIA specific routines.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/hardware/sa1111.h>
#include "sa1111_generic.h"
static int
lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
const socket_state_t *state)
{
unsigned long flags, gpio, misc_wr;
int ret = 1;
struct pcmcia_state new_state;
local_irq_save(flags);
gpio = PA_DWR;
misc_wr = LUB_MISC_WR;
/* Lubbock uses the Maxim MAX1602, with the following connections:
*
* Socket 0 (PCMCIA):
* MAX1602 Lubbock Register
* Pin Signal
* ----- ------- ----------------------
* A0VPP S0_PWR0 SA-1111 GPIO A<0>
* A1VPP S0_PWR1 SA-1111 GPIO A<1>
* A0VCC S0_PWR2 SA-1111 GPIO A<2>
* A1VCC S0_PWR3 SA-1111 GPIO A<3>
* VX VCC
* VY +3.3V
* 12IN +12V
* CODE +3.3V Cirrus Code, CODE = High (VY)
*
* Socket 1 (CF):
* MAX1602 Lubbock Register
* Pin Signal
* ----- ------- ----------------------
* A0VPP GND VPP is not connected
* A1VPP GND VPP is not connected
* A0VCC S1_PWR0 MISC_WR<14>
* A1VCC S1_PWR0 MISC_WR<15>
* VX VCC
* VY +3.3V
* 12IN GND VPP is not connected
* CODE +3.3V Cirrus Code, CODE = High (VY)
*
*/
again:
switch(skt->nr){
case 0:
switch(state->Vcc){
case 0:
gpio &= ~(GPIO_bit(2) | GPIO_bit(3));
break;
case 33:
gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(3);
break;
case 50:
gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
ret = -1;
}
switch(state->Vpp){
case 0:
gpio &= ~(GPIO_bit(0) | GPIO_bit(1));
break;
case 120:
gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(1);
break;
default:
/* REVISIT: I'm not sure about this? Is this correct?
Is it always safe or do we have potential problems
with bogus combinations of Vcc and Vpp settings? */
if(state->Vpp == state->Vcc)
gpio = (gpio & ~(GPIO_bit(0) | GPIO_bit(1))) | GPIO_bit(0);
else {
printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__, state->Vpp);
ret = -1;
break;
}
}
break;
case 1:
switch(state->Vcc){
case 0:
misc_wr &= ~((1 << 15) | (1 << 14));
break;
case 33:
misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
gpio = (gpio & ~(GPIO_bit(2) | GPIO_bit(3))) | GPIO_bit(2);
break;
case 50:
misc_wr = (misc_wr & ~(1 << 15)) | (1 << 14);
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, state->Vcc);
ret = -1;
break;
}
if(state->Vpp!=state->Vcc && state->Vpp!=0){
printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__, state->Vpp);
ret = -1;
break;
}
break;
default:
ret = -1;
}
if (ret >= 0) {
sa1111_pcmcia_configure_socket(skt, state);
LUB_MISC_WR = misc_wr;
PA_DWR = gpio;
}
if (ret > 0) {
ret = 0;
#if 1
/*
* HACK ALERT:
* We can't sense the voltage properly on Lubbock before actually
* applying some power to the socket (catch 22).
* Resense the socket Voltage Sense pins after applying socket power.
*/
sa1111_pcmcia_socket_state(skt, &new_state);
if (state->Vcc == 33 && !new_state.vs_3v && !new_state.vs_Xv) {
/* Switch to 5V, Configure socket with 5V voltage */
PA_DWR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
PA_DDR &= ~(GPIO_bit(0) | GPIO_bit(1) | GPIO_bit(2) | GPIO_bit(3));
/* We need to hack around the const qualifier as well to keep this
ugly workaround localized and not force it to the rest of the code.
Barf bags avaliable in the seat pocket in front of you! */
((socket_state_t *)state)->Vcc = 50;
((socket_state_t *)state)->Vpp = 50;
goto again;
}
#endif
}
local_irq_restore(flags);
return ret;
}
static struct pcmcia_low_level lubbock_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = sa1111_pcmcia_hw_init,
.hw_shutdown = sa1111_pcmcia_hw_shutdown,
.socket_state = sa1111_pcmcia_socket_state,
.configure_socket = lubbock_pcmcia_configure_socket,
.socket_init = sa1111_pcmcia_socket_init,
.socket_suspend = sa1111_pcmcia_socket_suspend,
.first = 0,
.nr = 2,
};
#include "pxa2xx_base.h"
int __init pcmcia_lubbock_init(struct device *dev)
{
int ret = -ENODEV;
if (machine_is_lubbock()) {
/*
* Set GPIO_A<3:0> to be outputs for the MAX1600,
* and switch to standby mode.
*/
PA_DWR = 0;
PA_DDR = 0;
PA_SDR = 0;
PA_SSR = 0;
/* Set CF Socket 1 power to standby mode. */
LUB_MISC_WR &= ~(GPIO_bit(15) | GPIO_bit(14));
dev->platform_data = &lubbock_pcmcia_ops;
ret = pxa2xx_drv_pcmcia_probe(dev);
}
return ret;
}
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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;
......
......@@ -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 sa1100_pcmcia_socket *skt, struct pcmcia_stat
}
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 sa1100_pcmcia_socket *skt, const socket_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
......
......@@ -75,7 +75,7 @@ static void complain_about_jumpering(const char *whom,
}
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;
......
......@@ -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_pcmcia_socket *skt, struct pcmcia_state *
}
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 sa1100_pcmcia_socket *skt,
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 = {
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
*
*/
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 sa1100_pcmcia_socket *skt,
*
*/
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 sa1100_pcmcia_socket *skt,
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));
}
/*
......
......@@ -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 sa1100_pcmcia_socket *skt)
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(struct sa1100_pcmcia_socket *skt)
}
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 sa1100_pcmcia_socket *skt, struct pcmcia_sta
}
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 sa1100_pcmcia_socket *skt,
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 = {
......
......@@ -43,7 +43,7 @@
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
#include "sa1100.h"
#include "sa1100_generic.h"
static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
#ifdef CONFIG_SA1100_ASSABET
......@@ -118,7 +118,7 @@ static int sa11x0_drv_pcmcia_resume(struct device *dev, u32 level)
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,
......
#include "sa11xx_core.h"
#include "soc_common.h"
#include "sa11xx_base.h"
/*
* Declaration for all machine specific init/exit functions.
......
......@@ -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 sa1100_pcmcia_socket *skt)
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(struct sa1100_pcmcia_socket *skt)
}
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_pcmcia_socket *skt, struct pcmcia_state
}
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 sa1100_pcmcia_socket *skt,
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)
{
}
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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;
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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_pcmcia_socket *skt, struct pcmcia_state
}
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 sa1100_pcmcia_socket *skt, const socket_sta
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(struct sa1100_pcmcia_socket *skt)
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
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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;
......
......@@ -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 sa1100_pcmcia_socket *skt, const socket_
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);
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
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(struct sa1100_pcmcia_socket *skt)
}
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 sa1100_pcmcia_socket *skt,
}
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 sa1100_pcmcia_socket *skt,
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 = {
......
......@@ -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 sa1100_pcmcia_socket *skt)
}
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;
......
......@@ -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 sa1100_pcmcia_socket *skt)
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 sa1100_pcmcia_socket *skt,
}
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 sa1100_pcmcia_socket *skt,
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 = {
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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_pcmcia_socket *skt,
}
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 sa1100_pcmcia_socket *skt,
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);
}
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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_pcmcia_socket *skt,
}
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 sa1100_pcmcia_socket *skt,
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!
......
......@@ -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 sa1100_pcmcia_socket *skt)
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;
......
......@@ -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 sa1100_pcmcia_socket *skt)
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(struct sa1100_pcmcia_socket *skt)
*
******************************************************/
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 sa1100_pcmcia_socket *skt,
*
******************************************************/
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 sa1100_pcmcia_socket *skt,
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));
}
/**
......
......@@ -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 sa1100_pcmcia_socket *skt)
}
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;
......
......@@ -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(struct sa1100_pcmcia_socket *skt)
}
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_pcmcia_socket *skt,
}
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 sa1100_pcmcia_socket *skt,
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 = {
......
......@@ -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 sa1100_pcmcia_socket *skt, struct pcmcia_
}
}
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(struct sa1100_pcmcia_socket *skt, const socke
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_dev *dev)
#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_dev *dev)
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;
}
......
#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 *);
/*======================================================================
Device driver for the PCMCIA control functionality of StrongARM
SA-1100 microprocessors.
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The initial developer of the original code is John G. Dorsey
<john+@cs.cmu.edu>. Portions created by John G. Dorsey are
Copyright (C) 1999 John G. Dorsey. All Rights Reserved.
Alternatively, the contents of this file may be used under the
terms of the GNU Public License version 2 (the "GPL"), in which
case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
by deleting the provisions above and replace them with the notice
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the MPL or the GPL.
======================================================================*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/cpufreq.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include "soc_common.h"
#include "sa11xx_base.h"
/*
* sa1100_pcmcia_default_mecr_timing
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* Calculate MECR clock wait states for given CPU clock
* speed and command wait state. This function can be over-
* written by a board specific version.
*
* The default is to simply calculate the BS values as specified in
* the INTEL SA1100 development manual
* "Expansion Memory (PCMCIA) Configuration Register (MECR)"
* that's section 10.2.5 in _my_ version of the manual ;)
*/
static unsigned int
sa1100_pcmcia_default_mecr_timing(struct soc_pcmcia_socket *skt,
unsigned int cpu_speed,
unsigned int cmd_time)
{
return sa1100_pcmcia_mecr_bs(cmd_time, cpu_speed);
}
static unsigned short
calc_speed(unsigned short *spds, int num, unsigned short dflt)
{
unsigned short speed = 0;
int i;
for (i = 0; i < num; i++)
if (speed < spds[i])
speed = spds[i];
if (speed == 0)
speed = dflt;
return speed;
}
/* sa1100_pcmcia_set_mecr()
* ^^^^^^^^^^^^^^^^^^^^^^^^
*
* set MECR value for socket <sock> based on this sockets
* io, mem and attribute space access speed.
* Call board specific BS value calculation to allow boards
* to tweak the BS values.
*/
static int
sa1100_pcmcia_set_mecr(struct soc_pcmcia_socket *skt, unsigned int cpu_clock)
{
u32 mecr, old_mecr;
unsigned long flags;
unsigned short speed;
unsigned int bs_io, bs_mem, bs_attr;
speed = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
bs_io = skt->ops->get_timing(skt, cpu_clock, speed);
speed = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
bs_mem = skt->ops->get_timing(skt, cpu_clock, speed);
speed = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
bs_attr = skt->ops->get_timing(skt, cpu_clock, speed);
local_irq_save(flags);
old_mecr = mecr = MECR;
MECR_FAST_SET(mecr, skt->nr, 0);
MECR_BSIO_SET(mecr, skt->nr, bs_io);
MECR_BSA_SET(mecr, skt->nr, bs_attr);
MECR_BSM_SET(mecr, skt->nr, bs_mem);
if (old_mecr != mecr)
MECR = mecr;
local_irq_restore(flags);
debug(skt, 2, "FAST %X BSM %X BSA %X BSIO %X\n",
MECR_FAST_GET(mecr, skt->nr),
MECR_BSM_GET(mecr, skt->nr), MECR_BSA_GET(mecr, skt->nr),
MECR_BSIO_GET(mecr, skt->nr));
return 0;
}
static int
sa1100_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
{
return sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
}
static int
sa1100_pcmcia_show_timing(struct soc_pcmcia_socket *skt, char *buf)
{
unsigned int clock = cpufreq_get(0);
unsigned long mecr = MECR;
char *p = buf;
p+=sprintf(p, "I/O : %u (%u)\n",
calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS),
sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, skt->nr)));
p+=sprintf(p, "attribute: %u (%u)\n",
calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS),
sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, skt->nr)));
p+=sprintf(p, "common : %u (%u)\n",
calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS),
sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr)));
return p - buf;
}
int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
int first, int nr)
{
/*
* set default MECR calculation if the board specific
* code did not specify one...
*/
if (!ops->get_timing)
ops->get_timing = sa1100_pcmcia_default_mecr_timing;
/* Provide our SA11x0 specific timing routines. */
ops->set_timing = sa1100_pcmcia_set_timing;
ops->show_timing = sa1100_pcmcia_show_timing;
return soc_common_drv_pcmcia_probe(dev, ops, first, nr);
}
EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
#ifdef CONFIG_CPU_FREQ
/* sa1100_pcmcia_update_mecr()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
* When sa1100_pcmcia_notifier() decides that a MECR adjustment (due
* to a core clock frequency change) is needed, this routine establishes
* new BS_xx values consistent with the clock speed `clock'.
*/
static void sa1100_pcmcia_update_mecr(unsigned int clock)
{
struct soc_pcmcia_socket *skt;
down(&soc_pcmcia_sockets_lock);
list_for_each_entry(skt, &soc_pcmcia_sockets, node)
sa1100_pcmcia_set_mecr(skt, clock);
up(&soc_pcmcia_sockets_lock);
}
/* sa1100_pcmcia_notifier()
* ^^^^^^^^^^^^^^^^^^^^^^^^
* When changing the processor core clock frequency, it is necessary
* to adjust the MECR timings accordingly. We've recorded the timings
* requested by Card Services, so this is just a matter of finding
* out what our current speed is, and then recomputing the new MECR
* values.
*
* Returns: 0 on success, -1 on error
*/
static int
sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freqs = data;
switch (val) {
case CPUFREQ_PRECHANGE:
if (freqs->new > freqs->old)
sa1100_pcmcia_update_mecr(freqs->new);
break;
case CPUFREQ_POSTCHANGE:
if (freqs->new < freqs->old)
sa1100_pcmcia_update_mecr(freqs->new);
break;
}
return 0;
}
static struct notifier_block sa1100_pcmcia_notifier_block = {
.notifier_call = sa1100_pcmcia_notifier
};
static int __init sa11xx_pcmcia_init(void)
{
int ret;
printk(KERN_INFO "SA11xx PCMCIA\n");
ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret < 0)
printk(KERN_ERR "Unable to register CPU frequency change "
"notifier (%d)\n", ret);
return ret;
}
module_init(sa11xx_pcmcia_init);
static void __exit sa11xx_pcmcia_exit(void)
{
cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
}
module_exit(sa11xx_pcmcia_exit);
#endif
MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver");
MODULE_LICENSE("Dual MPL/GPL");
......@@ -27,23 +27,27 @@
and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this
file under either the MPL or the GPL.
======================================================================*/
#if !defined(_PCMCIA_SA1100_H)
# define _PCMCIA_SA1100_H
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
#include "sa1100_generic.h"
/* 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:
* MECR layout is:
*
* FAST1 BSM1<4:0> BSA1<4:0> BSIO1<4:0> FAST0 BSM0<4:0> BSA0<4:0> BSIO0<4:0>
*
......@@ -105,7 +109,7 @@ static inline unsigned int sa1100_pcmcia_mecr_bs(unsigned int pcmcia_cycle_ns,
return (t / 1000000) + (((t % 1000000) == 0) ? 0 : 1);
}
/* This function returns the (approxmiate) command assertion period, in
/* 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,
......@@ -114,51 +118,6 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
}
/* 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
extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);
#endif /* !defined(_PCMCIA_SA1100_H) */
/*======================================================================
Device driver for the PCMCIA control functionality of StrongARM
SA-1100 microprocessors.
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
......@@ -27,23 +27,16 @@
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.
======================================================================*/
/*
* Please see linux/Documentation/arm/SA1100/PCMCIA for more information
* on the low-level kernel interface.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/config.h>
#include <linux/cpufreq.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
......@@ -52,108 +45,30 @@
#include <asm/irq.h>
#include <asm/system.h>
#include "sa11xx_core.h"
#include "sa1100.h"
#include "soc_common.h"
#ifdef DEBUG
static int pc_debug;
static int pc_debug;
module_param(pc_debug, int, 0644);
#define debug(skt, lvl, fmt, arg...) do { \
if (pc_debug > (lvl)) \
printk(KERN_DEBUG "skt%u: %s: " fmt, \
(skt)->nr, __func__ , ## arg); \
} while (0)
#else
#define debug(skt, lvl, fmt, arg...) do { } while (0)
#endif
#define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket)
/*
* 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 sa1100_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)
void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
int lvl, const char *fmt, ...)
{
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;
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);
}
}
/* sa1100_pcmcia_set_mecr()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* set MECR value for socket <sock> based on this sockets
* io, mem and attribute space access speed.
* Call board specific BS value calculation to allow boards
* to tweak the BS values.
*/
static int
sa1100_pcmcia_set_mecr(struct sa1100_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, SA1100_PCMCIA_IO_ACCESS);
bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed);
speed = calc_speed(skt->spd_mem, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS);
bs_mem = skt->ops->socket_get_timing(skt, cpu_clock, speed);
speed = calc_speed(skt->spd_attr, MAX_WIN, SA1100_PCMCIA_3V_MEM_ACCESS);
bs_attr = skt->ops->socket_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));
#endif
return 0;
}
#define to_soc_pcmcia_socket(x) container_of(x, struct soc_pcmcia_socket, socket)
static unsigned int sa1100_pcmcia_skt_state(struct sa1100_pcmcia_socket *skt)
static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
{
struct pcmcia_state state;
unsigned int stat;
......@@ -186,13 +101,13 @@ static unsigned int sa1100_pcmcia_skt_state(struct sa1100_pcmcia_socket *skt)
}
/*
* sa1100_pcmcia_config_skt
* ^^^^^^^^^^^^^^^^^^^^^^^^
* soc_common_pcmcia_config_skt
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* Convert PCMCIA socket state to our socket configure structure.
*/
static int
sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state)
soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
{
int ret;
......@@ -214,14 +129,14 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state
}
if (ret < 0)
printk(KERN_ERR "sa1100_pcmcia: unable to configure "
printk(KERN_ERR "soc_common_pcmcia: unable to configure "
"socket %d\n", skt->nr);
return ret;
}
/* sa1100_pcmcia_sock_init()
* ^^^^^^^^^^^^^^^^^^^^^^^^^
/* soc_common_pcmcia_sock_init()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*
* (Re-)Initialise the socket, turning on status interrupts
* and PCMCIA bus. This must wait for power to stabilise
......@@ -229,9 +144,9 @@ sa1100_pcmcia_config_skt(struct sa1100_pcmcia_socket *skt, socket_state_t *state
*
* Returns: 0
*/
static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock)
static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "initializing socket\n");
......@@ -241,22 +156,22 @@ static int sa1100_pcmcia_sock_init(struct pcmcia_socket *sock)
/*
* sa1100_pcmcia_suspend()
* ^^^^^^^^^^^^^^^^^^^^^^^
* 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 sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
int ret;
debug(skt, 2, "suspending socket\n");
ret = sa1100_pcmcia_config_skt(skt, &dead_socket);
ret = soc_common_pcmcia_config_skt(skt, &dead_socket);
if (ret == 0)
skt->ops->socket_suspend(skt);
......@@ -265,10 +180,7 @@ static int sa1100_pcmcia_suspend(struct pcmcia_socket *sock)
static spinlock_t status_lock = SPIN_LOCK_UNLOCKED;
/* sa1100_check_status()
* ^^^^^^^^^^^^^^^^^^^^^
*/
static void sa1100_check_status(struct sa1100_pcmcia_socket *skt)
static void soc_common_check_status(struct soc_pcmcia_socket *skt)
{
unsigned int events;
......@@ -278,7 +190,7 @@ static void sa1100_check_status(struct sa1100_pcmcia_socket *skt)
unsigned int status;
unsigned long flags;
status = sa1100_pcmcia_skt_state(skt);
status = soc_common_pcmcia_skt_state(skt);
spin_lock_irqsave(&status_lock, flags);
events = (status ^ skt->status) & skt->cs_state.csc_mask;
......@@ -298,45 +210,40 @@ static void sa1100_check_status(struct sa1100_pcmcia_socket *skt)
} while (events);
}
/* sa1100_pcmcia_poll_event()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
* Let's poll for events in addition to IRQs since IRQ only is unreliable...
*/
static void sa1100_pcmcia_poll_event(unsigned long dummy)
/* 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 sa1100_pcmcia_socket *skt = (struct sa1100_pcmcia_socket *)dummy;
struct soc_pcmcia_socket *skt = (struct soc_pcmcia_socket *)dummy;
debug(skt, 4, "polling for events\n");
mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD);
mod_timer(&skt->poll_timer, jiffies + SOC_PCMCIA_POLL_PERIOD);
sa1100_check_status(skt);
soc_common_check_status(skt);
}
/* sa1100_pcmcia_interrupt()
* ^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* Service routine for socket driver interrupts (requested by the
* low-level PCMCIA init() operation via sa1100_pcmcia_thread()).
* low-level PCMCIA init() operation via soc_common_pcmcia_thread()).
* The actual interrupt-servicing work is performed by
* sa1100_pcmcia_thread(), largely because the Card Services event-
* 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 sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
{
struct sa1100_pcmcia_socket *skt = dev;
struct soc_pcmcia_socket *skt = dev;
debug(skt, 3, "servicing IRQ %d\n", irq);
sa1100_check_status(skt);
soc_common_check_status(skt);
return IRQ_HANDLED;
}
/* sa1100_pcmcia_get_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
* Implements the get_status() operation for the in-kernel PCMCIA
/*
* 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.
......@@ -351,39 +258,37 @@ static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *r
* Returns: 0
*/
static int
sa1100_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
skt->status = sa1100_pcmcia_skt_state(skt);
skt->status = soc_common_pcmcia_skt_state(skt);
*status = skt->status;
return 0;
}
/* sa1100_pcmcia_get_socket()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* Implements the get_socket() operation for the in-kernel PCMCIA
* service (formerly SS_GetSocket in Card Services). Not a very
* service (formerly SS_GetSocket in Card Services). Not a very
* exciting routine.
*
* Returns: 0
*/
static int
sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "\n");
debug(skt, 2, "\n");
*state = skt->cs_state;
*state = skt->cs_state;
return 0;
return 0;
}
/* sa1100_pcmcia_set_socket()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* 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
......@@ -393,31 +298,30 @@ sa1100_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
* Returns: 0
*/
static int
sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
(state->csc_mask==0)?"<NONE> ":"",
(state->csc_mask&SS_DETECT)?"DETECT ":"",
(state->csc_mask&SS_READY)?"READY ":"",
(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
(state->flags==0)?"<NONE> ":"",
(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
(state->flags&SS_IOCARD)?"IOCARD ":"",
(state->flags&SS_RESET)?"RESET ":"",
(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
state->Vcc, state->Vpp, state->io_irq);
return sa1100_pcmcia_config_skt(skt, state);
} /* sa1100_pcmcia_set_socket() */
/* sa1100_pcmcia_set_io_map()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
(state->csc_mask==0)?"<NONE> ":"",
(state->csc_mask&SS_DETECT)?"DETECT ":"",
(state->csc_mask&SS_READY)?"READY ":"",
(state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
(state->csc_mask&SS_BATWARN)?"BATWARN ":"",
(state->csc_mask&SS_STSCHG)?"STSCHG ":"",
(state->flags==0)?"<NONE> ":"",
(state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
(state->flags&SS_IOCARD)?"IOCARD ":"",
(state->flags&SS_RESET)?"RESET ":"",
(state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
(state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
state->Vcc, state->Vpp, state->io_irq);
return soc_common_pcmcia_config_skt(skt, state);
}
/*
* Implements the set_io_map() operation for the in-kernel PCMCIA
* service (formerly SS_SetIOMap in Card Services). We configure
* the map speed as requested, but override the address ranges
......@@ -426,9 +330,9 @@ sa1100_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
* Returns: 0 on success, -1 on error
*/
static int
sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
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",
......@@ -451,13 +355,13 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
if (map->flags & MAP_ACTIVE) {
if (speed == 0)
speed = SA1100_PCMCIA_IO_ACCESS;
speed = SOC_PCMCIA_IO_ACCESS;
} else {
speed = 0;
}
skt->spd_io[map->map] = speed;
sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
skt->ops->set_timing(skt);
if (map->stop == 1)
map->stop = PAGE_SIZE-1;
......@@ -467,11 +371,10 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
map->start = (unsigned long)skt->virt_io;
return 0;
} /* sa1100_pcmcia_set_io_map() */
}
/* sa1100_pcmcia_set_mem_map()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* 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
......@@ -480,9 +383,9 @@ sa1100_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
* Returns: 0 on success, -1 on error
*/
static int
sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
{
struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock);
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
struct resource *res;
unsigned short speed = map->speed;
......@@ -518,7 +421,7 @@ sa1100_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map
skt->spd_mem[map->map] = speed;
}
sa1100_pcmcia_set_mecr(skt, cpufreq_get(0));
skt->ops->set_timing(skt);
map->sys_stop -= map->sys_start;
map->sys_stop += res->start + map->card_start;
......@@ -567,18 +470,15 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
*p = b;
}
/* show_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* 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 sa1100_pcmcia_socket *skt = container_of(class_dev,
struct sa1100_pcmcia_socket, socket.dev);
unsigned int clock = cpufreq_get(0);
unsigned long mecr = MECR;
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);
......@@ -593,42 +493,34 @@ static ssize_t show_status(struct class_device *class_dev, char *buf)
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);
p+=sprintf(p, "I/O : %u (%u)\n",
calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_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, SA1100_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, SA1100_PCMCIA_3V_MEM_ACCESS),
sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, skt->nr)));
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 sa11xx_pcmcia_operations = {
.init = sa1100_pcmcia_sock_init,
.suspend = sa1100_pcmcia_suspend,
.get_status = sa1100_pcmcia_get_status,
.get_socket = sa1100_pcmcia_get_socket,
.set_socket = sa1100_pcmcia_set_socket,
.set_io_map = sa1100_pcmcia_set_io_map,
.set_mem_map = sa1100_pcmcia_set_mem_map,
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 sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr)
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, sa1100_pcmcia_interrupt,
res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt,
SA_INTERRUPT, irqs[i].str, skt);
if (res)
break;
......@@ -645,9 +537,10 @@ int sa11xx_request_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir
}
return res;
}
EXPORT_SYMBOL(sa11xx_request_irqs);
EXPORT_SYMBOL(soc_pcmcia_request_irqs);
void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr)
void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt,
struct pcmcia_irqs *irqs, int nr)
{
int i;
......@@ -655,9 +548,10 @@ void sa11xx_free_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs
if (irqs[i].sock == skt->nr)
free_irq(irqs[i].irq, skt);
}
EXPORT_SYMBOL(sa11xx_free_irqs);
EXPORT_SYMBOL(soc_pcmcia_free_irqs);
void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr)
void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
struct pcmcia_irqs *irqs, int nr)
{
int i;
......@@ -665,9 +559,10 @@ void sa11xx_disable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *i
if (irqs[i].sock == skt->nr)
set_irq_type(irqs[i].irq, IRQT_NOEDGE);
}
EXPORT_SYMBOL(sa11xx_disable_irqs);
EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *irqs, int nr)
void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
struct pcmcia_irqs *irqs, int nr)
{
int i;
......@@ -677,10 +572,11 @@ void sa11xx_enable_irqs(struct sa1100_pcmcia_socket *skt, struct pcmcia_irqs *ir
set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
}
}
EXPORT_SYMBOL(sa11xx_enable_irqs);
EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
static LIST_HEAD(sa1100_sockets);
static DECLARE_MUTEX(sa1100_sockets_lock);
LIST_HEAD(soc_pcmcia_sockets);
DECLARE_MUTEX(soc_pcmcia_sockets_lock);
static const char *skt_names[] = {
"PCMCIA socket 0",
......@@ -689,26 +585,18 @@ static const char *skt_names[] = {
struct skt_dev_info {
int nskt;
struct sa1100_pcmcia_socket skt[0];
struct soc_pcmcia_socket skt[0];
};
#define SKT_DEV_INFO_SIZE(n) \
(sizeof(struct skt_dev_info) + (n)*sizeof(struct sa1100_pcmcia_socket))
(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket))
int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
{
struct skt_dev_info *sinfo;
unsigned int cpu_clock;
int ret, i;
/*
* set default MECR calculation if the board specific
* code did not specify one...
*/
if (!ops->socket_get_timing)
ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing;
down(&sa1100_sockets_lock);
down(&soc_pcmcia_sockets_lock);
sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
if (!sinfo) {
......@@ -719,22 +607,20 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr));
sinfo->nskt = nr;
cpu_clock = cpufreq_get(0);
/*
* Initialise the per-socket structure.
*/
for (i = 0; i < nr; i++) {
struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
struct soc_pcmcia_socket *skt = &sinfo->skt[i];
skt->socket.ops = &sa11xx_pcmcia_operations;
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 = sa1100_pcmcia_poll_event;
skt->poll_timer.function = soc_common_pcmcia_poll_event;
skt->poll_timer.data = (unsigned long)skt;
skt->poll_timer.expires = jiffies + SA1100_PCMCIA_POLL_PERIOD;
skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;
skt->nr = first + i;
skt->irq = NO_IRQ;
......@@ -772,7 +658,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
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;
......@@ -783,14 +669,14 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
goto out_err_5;
}
list_add(&skt->node, &sa1100_sockets);
list_add(&skt->node, &soc_pcmcia_sockets);
/*
* We initialize the MECR to default values here, because
* We initialize default socket timing here, because
* we are not guaranteed to see a SetIOMap operation at
* runtime.
*/
sa1100_pcmcia_set_mecr(skt, cpu_clock);
ops->set_timing(skt);
ret = ops->hw_init(skt);
if (ret)
......@@ -802,7 +688,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
skt->socket.pci_irq = skt->irq;
skt->socket.io_offset = (unsigned long)skt->virt_io;
skt->status = sa1100_pcmcia_skt_state(skt);
skt->status = soc_common_pcmcia_skt_state(skt);
ret = pcmcia_register_socket(&skt->socket);
if (ret)
......@@ -820,7 +706,7 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
goto out;
do {
struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
struct soc_pcmcia_socket *skt = &sinfo->skt[i];
del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
......@@ -847,21 +733,20 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, in
kfree(sinfo);
out:
up(&sa1100_sockets_lock);
up(&soc_pcmcia_sockets_lock);
return ret;
}
EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe);
int sa11xx_drv_pcmcia_remove(struct device *dev)
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(&sa1100_sockets_lock);
down(&soc_pcmcia_sockets_lock);
for (i = 0; i < sinfo->nskt; i++) {
struct sa1100_pcmcia_socket *skt = &sinfo->skt[i];
struct soc_pcmcia_socket *skt = &sinfo->skt[i];
del_timer_sync(&skt->poll_timer);
......@@ -871,7 +756,7 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
skt->ops->hw_shutdown(skt);
sa1100_pcmcia_config_skt(skt, &dead_socket);
soc_common_pcmcia_config_skt(skt, &dead_socket);
list_del(&skt->node);
iounmap(skt->virt_io);
......@@ -881,91 +766,9 @@ int sa11xx_drv_pcmcia_remove(struct device *dev)
release_resource(&skt->res_io);
release_resource(&skt->res_skt);
}
up(&sa1100_sockets_lock);
up(&soc_pcmcia_sockets_lock);
kfree(sinfo);
return 0;
}
EXPORT_SYMBOL(sa11xx_drv_pcmcia_remove);
#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 sa1100_pcmcia_socket *skt;
down(&sa1100_sockets_lock);
list_for_each_entry(skt, &sa1100_sockets, node)
sa1100_pcmcia_set_mecr(skt, clock);
up(&sa1100_sockets_lock);
}
/* sa1100_pcmcia_notifier()
* ^^^^^^^^^^^^^^^^^^^^^^^^
* When changing the processor core clock frequency, it is necessary
* to adjust the MECR timings accordingly. We've recorded the timings
* requested by Card Services, so this is just a matter of finding
* out what our current speed is, and then recomputing the new MECR
* values.
*
* Returns: 0 on success, -1 on error
*/
static int
sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freqs = data;
switch (val) {
case CPUFREQ_PRECHANGE:
if (freqs->new > freqs->old)
sa1100_pcmcia_update_mecr(freqs->new);
break;
case CPUFREQ_POSTCHANGE:
if (freqs->new < freqs->old)
sa1100_pcmcia_update_mecr(freqs->new);
break;
}
return 0;
}
static struct notifier_block sa1100_pcmcia_notifier_block = {
.notifier_call = sa1100_pcmcia_notifier
};
static int __init sa11xx_pcmcia_init(void)
{
int ret;
printk(KERN_INFO "SA11xx PCMCIA\n");
ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block,
CPUFREQ_TRANSITION_NOTIFIER);
if (ret < 0)
printk(KERN_ERR "Unable to register CPU frequency change "
"notifier (%d)\n", ret);
return ret;
}
module_init(sa11xx_pcmcia_init);
static void __exit sa11xx_pcmcia_exit(void)
{
cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
}
module_exit(sa11xx_pcmcia_exit);
#endif
MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-11xx core socket driver");
MODULE_LICENSE("Dual MPL/GPL");
/*
* linux/include/asm/arch/pcmcia.h
* linux/drivers/pcmcia/soc_common.h
*
* Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
*
* This file contains definitions for the low-level SA-1100 kernel PCMCIA
* interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
* 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
......@@ -18,31 +18,15 @@
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
struct device;
/* Ideally, we'd support up to MAX_SOCK sockets, but the SA-1100 only
* has support for two. This shows up in lots of hardwired ways, such
* as the fact that MECR only has enough bits to configure two sockets.
* Since it's so entrenched in the hardware, limiting the software
* in this way doesn't seem too terrible.
*/
#define SA1100_PCMCIA_MAX_SOCK (2)
struct pcmcia_state {
unsigned detect: 1,
ready: 1,
bvd1: 1,
bvd2: 1,
wrprot: 1,
vs_3v: 1,
vs_Xv: 1;
};
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 sa1100_pcmcia_socket {
struct soc_pcmcia_socket {
struct pcmcia_socket socket;
/*
......@@ -76,46 +60,120 @@ struct sa1100_pcmcia_socket {
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;
int (*hw_init)(struct sa1100_pcmcia_socket *);
void (*hw_shutdown)(struct sa1100_pcmcia_socket *);
/* first socket in system */
int first;
/* nr of sockets */
int nr;
void (*socket_state)(struct sa1100_pcmcia_socket *, struct pcmcia_state *);
int (*configure_socket)(struct sa1100_pcmcia_socket *, const socket_state_t *);
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 sa1100_pcmcia_socket *);
void (*socket_init)(struct soc_pcmcia_socket *);
/*
* Disable card status IRQs and PCMCIA bus on suspend.
*/
void (*socket_suspend)(struct sa1100_pcmcia_socket *);
void (*socket_suspend)(struct soc_pcmcia_socket *);
/*
* Calculate MECR timing clock wait states
* Hardware specific timing routines.
* If provided, the get_timing routine overrides the SOC default.
*/
unsigned int (*socket_get_timing)(struct sa1100_pcmcia_socket *,
unsigned int cpu_speed, unsigned int cmd_time);
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;
};
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 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)
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);
/*
* 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
......@@ -1336,6 +1336,19 @@ typedef void (*ExcpHndlr) (void) ;
#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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment