summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@penguin.transmeta.com>2002-03-04 22:58:48 -0800
committerLinus Torvalds <torvalds@penguin.transmeta.com>2002-03-04 22:58:48 -0800
commitf60852d2d272bf0c3339f78b04b927b854233ebc (patch)
tree1e0c20ba7db41f1e4c96e3d0b71a77850158abf2
parenta22655dcc61ec0adb5c12841a0955a3ad5d7c8a8 (diff)
parented78e24bb038b0e8e43f753a569e1d1d65f5e38d (diff)
Merge bk://bk.arm.linux.org.uk
into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
-rw-r--r--arch/arm/config.in1
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/process.c3
-rw-r--r--arch/arm/mach-adifcc/mm.c2
-rw-r--r--arch/arm/mach-anakin/mm.c2
-rw-r--r--arch/arm/mach-arc/mm.c7
-rw-r--r--arch/arm/mach-clps711x/autcpu12.c2
-rw-r--r--arch/arm/mach-clps711x/edb7211-mm.c8
-rw-r--r--arch/arm/mach-sa1100/adsbitsy.c2
-rw-r--r--arch/arm/mach-sa1100/assabet.c4
-rw-r--r--arch/arm/mach-sa1100/cerf.c8
-rw-r--r--arch/arm/mach-sa1100/empeg.c2
-rw-r--r--arch/arm/mach-sa1100/flexanet.c8
-rw-r--r--arch/arm/mach-sa1100/freebird.c4
-rw-r--r--arch/arm/mach-sa1100/graphicsclient.c177
-rw-r--r--arch/arm/mach-sa1100/graphicsmaster.c81
-rw-r--r--arch/arm/mach-sa1100/h3600.c6
-rw-r--r--arch/arm/mach-sa1100/huw_webpanel.c2
-rw-r--r--arch/arm/mach-sa1100/itsy.c4
-rw-r--r--arch/arm/mach-sa1100/jornada720.c6
-rw-r--r--arch/arm/mach-sa1100/lart.c4
-rw-r--r--arch/arm/mach-sa1100/nanoengine.c6
-rw-r--r--arch/arm/mach-sa1100/neponset.c4
-rw-r--r--arch/arm/mach-sa1100/omnimeter.c2
-rw-r--r--arch/arm/mach-sa1100/pangolin.c2
-rw-r--r--arch/arm/mach-sa1100/pfs168.c28
-rw-r--r--arch/arm/mach-sa1100/pleb.c4
-rw-r--r--arch/arm/mach-sa1100/simpad.c2
-rw-r--r--arch/arm/mach-sa1100/stork.c8
-rw-r--r--arch/arm/mach-sa1100/system3.c136
-rw-r--r--arch/arm/mach-sa1100/victor.c2
-rw-r--r--arch/arm/mach-sa1100/xp860.c6
-rw-r--r--arch/arm/mach-sa1100/yopy.c6
-rw-r--r--arch/arm/mm/fault-armv.c3
-rw-r--r--arch/arm/mm/fault-common.c6
-rw-r--r--arch/arm/mm/init.c35
-rw-r--r--arch/arm/mm/minicache.c2
-rw-r--r--arch/arm/mm/mm-armv.c26
-rw-r--r--arch/arm/mm/proc-xscale.S19
-rw-r--r--drivers/pcmcia/Config.in1
-rw-r--r--drivers/pcmcia/Makefile25
-rw-r--r--drivers/pcmcia/sa1100.h94
-rw-r--r--drivers/pcmcia/sa1100_adsbitsy.c223
-rw-r--r--drivers/pcmcia/sa1100_assabet.c257
-rw-r--r--drivers/pcmcia/sa1100_badge4.c186
-rw-r--r--drivers/pcmcia/sa1100_cerf.c153
-rw-r--r--drivers/pcmcia/sa1100_flexanet.c194
-rw-r--r--drivers/pcmcia/sa1100_freebird.c106
-rw-r--r--drivers/pcmcia/sa1100_generic.c1349
-rw-r--r--drivers/pcmcia/sa1100_generic.h77
-rw-r--r--drivers/pcmcia/sa1100_graphicsclient.c56
-rw-r--r--drivers/pcmcia/sa1100_graphicsmaster.c223
-rw-r--r--drivers/pcmcia/sa1100_h3600.c272
-rw-r--r--drivers/pcmcia/sa1100_jornada720.c225
-rw-r--r--drivers/pcmcia/sa1100_neponset.c346
-rw-r--r--drivers/pcmcia/sa1100_pangolin.c87
-rw-r--r--drivers/pcmcia/sa1100_pfs168.c227
-rw-r--r--drivers/pcmcia/sa1100_shannon.c177
-rw-r--r--drivers/pcmcia/sa1100_simpad.c62
-rw-r--r--drivers/pcmcia/sa1100_stork.c120
-rw-r--r--drivers/pcmcia/sa1100_system3.c131
-rw-r--r--drivers/pcmcia/sa1100_xp860.c257
-rw-r--r--drivers/pcmcia/sa1100_yopy.c110
-rw-r--r--drivers/pcmcia/sa1111_generic.c180
-rw-r--r--drivers/pcmcia/sa1111_generic.h7
-rw-r--r--fs/partitions/Config.in2
-rw-r--r--include/asm-arm/arch-sa1100/graphicsclient.h9
-rw-r--r--include/asm-arm/arch-sa1100/irqs.h3
-rw-r--r--include/asm-arm/arch-sa1100/system3.h18
-rw-r--r--include/asm-arm/pgalloc.h120
-rw-r--r--include/asm-arm/pgtable.h13
-rw-r--r--include/asm-arm/proc-armv/pgalloc.h39
-rw-r--r--include/asm-arm/proc-armv/pgtable.h2
73 files changed, 3300 insertions, 2685 deletions
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 7fdca800a30f..f69db6f8608e 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -682,7 +682,6 @@ comment 'Kernel hacking'
bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
bool 'Verbose user fault messages' CONFIG_DEBUG_USER
bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
-dep_bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE $CONFIG_CPU_26
bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 035f0f43699a..a84ba04ad73e 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -169,10 +169,6 @@ EXPORT_SYMBOL(__virt_to_bus);
EXPORT_SYMBOL(__bus_to_virt);
#endif
-#ifndef CONFIG_NO_PGT_CACHE
-EXPORT_SYMBOL(quicklists);
-#endif
-
/* string / mem functions */
EXPORT_SYMBOL_NOVERS(strcpy);
EXPORT_SYMBOL_NOVERS(strncpy);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index e0b2eac9faa0..c95b4f4b68e3 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -95,9 +95,6 @@ void cpu_idle(void)
idle();
leds_event(led_idle_end);
schedule();
-#ifndef CONFIG_NO_PGT_CACHE
- check_pgt_cache();
-#endif
}
}
diff --git a/arch/arm/mach-adifcc/mm.c b/arch/arm/mach-adifcc/mm.c
index 3d0db7087fdf..a77f235f5c24 100644
--- a/arch/arm/mach-adifcc/mm.c
+++ b/arch/arm/mach-adifcc/mm.c
@@ -14,7 +14,7 @@
static struct map_desc adifcc_io_desc[] __initdata = {
/* on-board devices */
- { 0xff400000, 0x00400000, 0x00300000, DOMAIN_IO, 1, 1, 0, 0},
+ { 0xff400000, 0x00400000, 0x00300000, DOMAIN_IO, 0, 1, 0, 0},
LAST_DESC
};
diff --git a/arch/arm/mach-anakin/mm.c b/arch/arm/mach-anakin/mm.c
index 631e7d7daebe..39bb59668930 100644
--- a/arch/arm/mach-anakin/mm.c
+++ b/arch/arm/mach-anakin/mm.c
@@ -20,7 +20,7 @@
static struct map_desc anakin_io_desc[] __initdata = {
{ IO_BASE, IO_START, IO_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
- { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 1, 1, 0, 0 },
+ { FLASH_BASE, FLASH_START, FLASH_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
{ VGA_BASE, VGA_START, VGA_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-arc/mm.c b/arch/arm/mach-arc/mm.c
index aec1dad545c8..6a96065fbab2 100644
--- a/arch/arm/mach-arc/mm.c
+++ b/arch/arm/mach-arc/mm.c
@@ -78,15 +78,16 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
- new_pte = pte_alloc(mm, new_pmd, 0);
+ new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
init_pgd = pgd_offset_k(0);
init_pmd = pmd_offset(init_pgd, 0);
- init_pte = pte_offset(init_pmd, 0);
-
+ init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
+ pte_unmap_nested(init_pte);
+ pte_unmap(new_pte);
/*
* most of the page table entries are zeroed
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index dff16c19364d..82b2839ed899 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -51,7 +51,7 @@ static struct map_desc autcpu12_io_desc[] __initdata = {
/* virtual, physical, length, domain, r, w, c, b */
/* memory-mapped extra io and CS8900A Ethernet chip */
/* ethernet chip */
- { AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, DOMAIN_IO, 1, 1, 0, 0 },
+ { AUTCPU12_VIRT_CS8900A, AUTCPU12_PHYS_CS8900A, SZ_1M, DOMAIN_IO, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-clps711x/edb7211-mm.c b/arch/arm/mach-clps711x/edb7211-mm.c
index e4e970451f18..47e999599226 100644
--- a/arch/arm/mach-clps711x/edb7211-mm.c
+++ b/arch/arm/mach-clps711x/edb7211-mm.c
@@ -56,12 +56,12 @@ static struct map_desc edb7211_io_desc[] __initdata = {
/* virtual, physical, length, domain, r, w, c, b */
/* memory-mapped extra keyboard row and CS8900A Ethernet chip */
- { EP7211_VIRT_EXTKBD, EP7211_PHYS_EXTKBD, MB1, DOMAIN_IO, 1, 1, 0, 0 },
- { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, MB1, DOMAIN_IO, 1, 1, 0, 0 },
+ { EP7211_VIRT_EXTKBD, EP7211_PHYS_EXTKBD, MB1, DOMAIN_IO, 0, 1, 0, 0 },
+ { EP7211_VIRT_CS8900A, EP7211_PHYS_CS8900A, MB1, DOMAIN_IO, 0, 1, 0, 0 },
/* flash banks */
- { EP7211_VIRT_FLASH1, EP7211_PHYS_FLASH1, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
- { EP7211_VIRT_FLASH2, EP7211_PHYS_FLASH2, MB1 * 8, DOMAIN_KERNEL, 1, 1, 0, 0 },
+ { EP7211_VIRT_FLASH1, EP7211_PHYS_FLASH1, MB1 * 8, DOMAIN_KERNEL, 0, 1, 0, 0 },
+ { EP7211_VIRT_FLASH2, EP7211_PHYS_FLASH2, MB1 * 8, DOMAIN_KERNEL, 0, 1, 0, 0 },
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
index eedeabb18634..72e7c953061c 100644
--- a/arch/arm/mach-sa1100/adsbitsy.c
+++ b/arch/arm/mach-sa1100/adsbitsy.c
@@ -125,7 +125,7 @@ fixup_adsbitsy(struct machine_desc *desc, struct param_struct *params,
static struct map_desc adsbitsy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1111 */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 35d05f80e31b..5f8ed1c0d556 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -230,8 +230,8 @@ fixup_assabet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc assabet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
/* f3000000 - neponset system registers */
/* f4000000 - neponset SA1111 registers */
LAST_DESC
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index bf2385ab4cd4..8ebd37634fc5 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -64,11 +64,11 @@ fixup_cerf(struct machine_desc *desc, struct param_struct *params,
static struct map_desc cerf_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Crystal Ethernet Chip */
+ { 0xf0000000, 0x08000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Crystal Ethernet Chip */
#ifdef CONFIG_SA1100_CERF_CPLD
- { 0xf1000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD Chip */
- { 0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CerfPDA Bluetooth */
- { 0xf3000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* CerfPDA Serial */
+ { 0xf1000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD Chip */
+ { 0xf2000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CerfPDA Bluetooth */
+ { 0xf3000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* CerfPDA Serial */
#endif
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/empeg.c b/arch/arm/mach-sa1100/empeg.c
index 682e99d522d2..d35f3c71534a 100644
--- a/arch/arm/mach-sa1100/empeg.c
+++ b/arch/arm/mach-sa1100/empeg.c
@@ -31,7 +31,7 @@ fixup_empeg(struct machine_desc *desc, struct param_struct *params,
static struct map_desc empeg_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/flexanet.c b/arch/arm/mach-sa1100/flexanet.c
index 8ce7cea310c8..a470b49e3815 100644
--- a/arch/arm/mach-sa1100/flexanet.c
+++ b/arch/arm/mach-sa1100/flexanet.c
@@ -172,10 +172,10 @@ fixup_flexanet(struct machine_desc *desc, struct param_struct *params,
static struct map_desc flexanet_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Ethernet controller */
- { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Instrument boards */
- { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* External peripherals */
+ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf1000000, 0x18000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Ethernet controller */
+ { 0xD0000000, 0x40000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Instrument boards */
+ { 0xD8000000, 0x48000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* External peripherals */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
index 3a28685b6a21..c0b6e5f7b9d1 100644
--- a/arch/arm/mach-sa1100/freebird.c
+++ b/arch/arm/mach-sa1100/freebird.c
@@ -66,8 +66,8 @@ fixup_freebird(struct machine_desc *desc, struct param_struct *params,
static struct map_desc freebird_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
- { 0xf2000000, 0x19000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0},
+ { 0xf0000000, 0x12000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Board Control Register */
+ { 0xf2000000, 0x19000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0},
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/graphicsclient.c b/arch/arm/mach-sa1100/graphicsclient.c
index 9178fed76dec..9997cdc11686 100644
--- a/arch/arm/mach-sa1100/graphicsclient.c
+++ b/arch/arm/mach-sa1100/graphicsclient.c
@@ -32,67 +32,62 @@
* Handlers for GraphicsClient's external IRQ logic
*/
-static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+gc_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- int i;
+ unsigned int mask;
+
+ while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
+ /* clear the parent IRQ */
+ GEDR = GPIO_GPIO0;
- while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
- for( i = 0; i < 16; i++ )
- if( irq & (1<<i) )
- do_IRQ( ADS_EXT_IRQ(i), regs );
+ irq = ADS_EXT_IRQ(0);
+ desc = irq_desc + irq;
+
+ do {
+ if (mask & 1)
+ desc->handle(irq, desc, regs);
+ mask >>= 1;
+ irq++;
+ desc++;
+ } while (mask);
}
}
-static struct irqaction ADS_ext_irq = {
- name: "ADS_ext_IRQ",
- handler: ADS_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
-static void ADS_mask_and_ack_irq0(unsigned int irq)
+static void gc_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
-static void ADS_mask_irq0(unsigned int irq)
-{
- ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
-}
-
-static void ADS_unmask_irq0(unsigned int irq)
+static void gc_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
-static struct irqchip ADS0_chip = {
- ack: ADS_mask_and_ack_irq0,
- mask: ADS_mask_irq0,
- unmask: ADS_unmask_irq0,
+static struct irqchip gc_irq1_chip = {
+ ack: gc_mask_irq1,
+ mask: gc_mask_irq1,
+ unmask: gc_unmask_irq1,
};
-static void ADS_mask_and_ack_irq1(unsigned int irq)
+static void gc_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
-static void ADS_mask_irq1(unsigned int irq)
-{
- ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
-}
-
-static void ADS_unmask_irq1(unsigned int irq)
+static void gc_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
-static struct irqchip ADS1_chip = {
- ack: ADS_mask_and_ack_irq1,
- mask: ADS_mask_irq1,
- unmask: ADS_unmask_irq1,
+static struct irqchip gc_irq2_chip = {
+ ack: gc_mask_irq2,
+ mask: gc_mask_irq2,
+ unmask: gc_unmask_irq2,
};
static void __init graphicsclient_init_irq(void)
@@ -105,22 +100,23 @@ static void __init graphicsclient_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
+
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
- set_irq_chip(irq, &ADS0_chip);
+ set_irq_chip(irq, &gc_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
- set_irq_chip(irq, &ADS1_chip);
+ set_irq_chip(irq, &gc_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
- set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
- setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
+ set_irq_type(IRQ_GPIO0, IRQT_FALLING);
+ set_irq_chained_handler(IRQ_GPIO0, gc_irq_handler);
}
@@ -148,111 +144,6 @@ static struct map_desc graphicsclient_io_desc[] __initdata = {
LAST_DESC
};
-static struct gc_uart_ctrl_data_t gc_uart_ctrl_data[] = {
- { GPIO_GC_UART0_CTS, 0, NULL,NULL },
- { GPIO_GC_UART1_CTS, 0, NULL,NULL },
- { GPIO_GC_UART2_CTS, 0, NULL,NULL }
-};
-
-#error Old code. Someone needs to decide what to do with this
-#if 0
-static void
-graphicsclient_cts_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct gc_uart_ctrl_data_t * uart_data = (struct gc_uart_ctrl_data_t *)dev_id;
- int cts = !(GPLR & uart_data->cts_gpio);
-
- /* NOTE: I supose that we will no get any interrupt
- if the GPIO is not changed, so maybe
- the cts_prev_state can be removed ... */
- if (cts != uart_data->cts_prev_state) {
- uart_data->cts_prev_state = cts;
-
- uart_handle_cts_change(uart_data->info, cts);
- }
-}
-
-static int
-graphicsclient_register_cts_intr(int gpio, int irq,
- struct gc_uart_ctrl_data_t *uart_data)
-{
- int ret = 0;
-
- set_GPIO_IRQ_edge(gpio, GPIO_BOTH_EDGES);
-
- ret = request_irq(irq, graphicsclient_cts_intr,
- 0, "GC RS232 CTS", uart_data);
- if (ret) {
- printk(KERN_ERR "uart_open: failed to register CTS irq (%d)\n",
- ret);
- free_irq(irq, uart_data);
- }
-
- return ret;
-}
-
-static int
-graphicsclient_uart_open(struct uart_port *port, struct uart_info *info)
-{
- int ret = 0;
-
- if (port->mapbase == _Ser1UTCR0) {
- Ser1SDCR0 |= SDCR0_UART;
- /* Set RTS Output */
- GPSR = GPIO_GC_UART0_RTS;
-
- gc_uart_ctrl_data[0].cts_prev_state = 0;
- gc_uart_ctrl_data[0].info = info;
- gc_uart_ctrl_data[0].port = port;
-
- /* register uart0 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART0_CTS,
- IRQ_GC_UART0_CTS,
- &gc_uart_ctrl_data[0]);
- } else if (port->mapbase == _Ser2UTCR0) {
- Ser2UTCR4 = Ser2HSCR0 = 0;
- /* Set RTS Output */
- GPSR = GPIO_GC_UART1_RTS;
-
- gc_uart_ctrl_data[1].cts_prev_state = 0;
- gc_uart_ctrl_data[1].info = info;
- gc_uart_ctrl_data[1].port = port;
-
- /* register uart1 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART1_CTS,
- IRQ_GC_UART1_CTS,
- &gc_uart_ctrl_data[1]);
- } else if (port->mapbase == _Ser3UTCR0) {
- /* Set RTS Output */
- GPSR = GPIO_GC_UART2_RTS;
-
- gc_uart_ctrl_data[2].cts_prev_state = 0;
- gc_uart_ctrl_data[2].info = info;
- gc_uart_ctrl_data[2].port = port;
-
- /* register uart2 CTS irq */
- ret = graphicsclient_register_cts_intr(GPIO_GC_UART2_CTS,
- IRQ_GC_UART2_CTS,
- &gc_uart_ctrl_data[2]);
- }
- return ret;
-}
-
-static int
-graphicsclient_uart_close(struct uart_port *port, struct uart_info *info)
-{
- if (port->mapbase == _Ser1UTCR0) {
- free_irq(IRQ_GC_UART0_CTS, &gc_uart_ctrl_data[0]);
- } else if (port->mapbase == _Ser2UTCR0) {
- free_irq(IRQ_GC_UART1_CTS, &gc_uart_ctrl_data[1]);
- } else if (port->mapbase == _Ser3UTCR0) {
- free_irq(IRQ_GC_UART2_CTS, &gc_uart_ctrl_data[2]);
- }
-
- return 0;
-}
-#endif
-
static u_int graphicsclient_get_mctrl(struct uart_port *port)
{
u_int result = TIOCM_CD | TIOCM_DSR;
diff --git a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
index c4e52db5e428..b2eaecb33257 100644
--- a/arch/arm/mach-sa1100/graphicsmaster.c
+++ b/arch/arm/mach-sa1100/graphicsmaster.c
@@ -93,68 +93,62 @@ __initcall(graphicsmaster_init);
* Handlers for GraphicsMaster's external IRQ logic
*/
-static void ADS_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+gm_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
- int i;
-
- while( (irq = ADS_INT_ST1 | (ADS_INT_ST2 << 8)) ){
- for( i = 0; i < 16; i++ )
- if( irq & (1<<i) ) {
- do_IRQ( ADS_EXT_IRQ(i), regs );
- }
+ unsigned int mask;
+
+ while ((mask = ADS_INT_ST1 | (ADS_INT_ST2 << 8))) {
+ /* clear the parent IRQ */
+ GEDR = GPIO_GPIO0;
+
+ irq = ADS_EXT_IRQ(0);
+ desc = irq_desc + irq;
+
+ do {
+ if (mask & 1)
+ desc->handle(irq, desc, regs);
+ mask >>= 1;
+ irq++;
+ desc++;
+ } while (mask);
}
}
-static struct irqaction ADS_ext_irq = {
- name: "ADS_ext_IRQ",
- handler: ADS_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
-static void ADS_mask_and_ack_irq0(unsigned int irq)
+static void gm_mask_irq1(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(0)));
ADS_INT_EN1 &= ~mask;
ADS_INT_ST1 = mask;
}
-static void ADS_mask_irq0(unsigned int irq)
-{
- ADS_INT_ST1 = (1 << (irq - ADS_EXT_IRQ(0)));
-}
-
-static void ADS_unmask_irq0(unsigned int irq)
+static void gm_unmask_irq1(unsigned int irq)
{
ADS_INT_EN1 |= (1 << (irq - ADS_EXT_IRQ(0)));
}
-static struct irqchip ADS0_chip = {
- ack: ADS_mask_and_ack_irq0,
- mask: ADS_mask_irq0,
- unmask: ADS_unmask_irq0,
+static struct irqchip gm_irq1_chip = {
+ ack: gm_mask_irq1,
+ mask: gm_mask_irq1,
+ unmask: gm_unmask_irq1,
};
-static void ADS_mask_and_ack_irq1(unsigned int irq)
+static void gm_mask_irq2(unsigned int irq)
{
int mask = (1 << (irq - ADS_EXT_IRQ(8)));
ADS_INT_EN2 &= ~mask;
ADS_INT_ST2 = mask;
}
-static void ADS_mask_irq1(unsigned int irq)
-{
- ADS_INT_ST2 = (1 << (irq - ADS_EXT_IRQ(8)));
-}
-
-static void ADS_unmask_irq1(unsigned int irq)
+static void gm_unmask_irq2(unsigned int irq)
{
ADS_INT_EN2 |= (1 << (irq - ADS_EXT_IRQ(8)));
}
-static struct irqchip ADS1_chip = {
- ack: ADS_mask_irq1,
- mask: ADS_mask_irq1,
- unmask: ADS_mask_irq1,
+static struct irqchip gm_irq2_chip = {
+ ack: gm_mask_irq2,
+ mask: gm_mask_irq2,
+ unmask: gm_unmask_irq2,
};
static void __init graphicsmaster_init_irq(void)
@@ -167,22 +161,23 @@ static void __init graphicsmaster_init_irq(void)
/* disable all IRQs */
ADS_INT_EN1 = 0;
ADS_INT_EN2 = 0;
+
/* clear all IRQs */
ADS_INT_ST1 = 0xff;
ADS_INT_ST2 = 0xff;
for (irq = ADS_EXT_IRQ(0); irq <= ADS_EXT_IRQ(7); irq++) {
- set_irq_chip(irq, &ADS0_chip);
+ set_irq_chip(irq, &gm_irq1_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
for (irq = ADS_EXT_IRQ(8); irq <= ADS_EXT_IRQ(15); irq++) {
- set_irq_chip(irq, &ADS1_chip);
+ set_irq_chip(irq, &gm_irq2_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_PROBE | IRQF_VALID);
}
- set_GPIO_IRQ_edge(GPIO_GPIO0, GPIO_FALLING_EDGE);
- setup_arm_irq( IRQ_GPIO0, &ADS_ext_irq );
+ set_irq_type(IRQ_GPIO0, IRQT_FALLING);
+ set_irq_chained_handler(IRQ_GPIO0, gm_irq_handler);
}
@@ -206,9 +201,9 @@ fixup_graphicsmaster(struct machine_desc *desc, struct param_struct *params,
static struct map_desc graphicsmaster_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CPLD */
- { 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* CAN */
- { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+ { 0xf1000000, 0x40000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CAN */
+ { 0xf4000000, 0x18000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 633166a0ae05..6ce68739ce4a 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -489,9 +489,9 @@ static struct sa1100_port_fns h3600_port_fns __initdata = {
static struct map_desc h3600_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 CS#5 */
- { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 CS#2 */
- { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 CS#4 */
+ { H3600_EGPIO_VIRT, 0x49000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 CS#5 */
+ { H3600_BANK_2_VIRT, 0x10000000, 0x02800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 2 CS#2 */
+ { H3600_BANK_4_VIRT, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 4 CS#4 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
index 41a8ec5eedbf..98aba2ee8e8b 100644
--- a/arch/arm/mach-sa1100/huw_webpanel.c
+++ b/arch/arm/mach-sa1100/huw_webpanel.c
@@ -77,7 +77,7 @@ fixup_huw_webpanel(struct machine_desc *desc, struct param_struct *params,
**/
static struct map_desc huw_webpanel_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0xc1fb8000, 0x00048000, DOMAIN_IO, 1, 1, 0, 0 }, /* Parameter */
+ { 0xf0000000, 0xc1fb8000, 0x00048000, DOMAIN_IO, 0, 1, 0, 0 }, /* Parameter */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/itsy.c b/arch/arm/mach-sa1100/itsy.c
index b715af6c3b9b..4594855326b1 100644
--- a/arch/arm/mach-sa1100/itsy.c
+++ b/arch/arm/mach-sa1100/itsy.c
@@ -31,8 +31,8 @@ fixup_itsy(struct machine_desc *desc, struct param_struct *params,
likely wrong. */
static struct map_desc itsy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x49000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index c9dd8efc1379..98e94f85a9c1 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -66,9 +66,9 @@ fixup_jornada720(struct machine_desc *desc, struct param_struct *params,
static struct map_desc jornada720_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson registers */
- { 0xf1000000, 0x48200000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Epson frame buffer */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x48000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Epson registers */
+ { 0xf1000000, 0x48200000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Epson frame buffer */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index fd1895dd4e32..4141747fcc80 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -18,8 +18,8 @@
static struct map_desc lart_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
- { 0xec000000, 0x08000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash, alternative location */
+ { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash memory */
+ { 0xec000000, 0x08000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash, alternative location */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
index 8aad8bd919b3..bf12430352cd 100644
--- a/arch/arm/mach-sa1100/nanoengine.c
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -34,9 +34,9 @@ fixup_nanoengine(struct machine_desc *desc, struct param_struct *params,
static struct map_desc nanoengine_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf1000000, 0x18A00000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Internal PCI Config Space */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf1000000, 0x18A00000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Internal PCI Config Space */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index e9ecf3498a6d..34158578a552 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -184,8 +184,8 @@ __initcall(neponset_init);
static struct map_desc neponset_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
index 76eaa1fb724d..604d9265a46f 100644
--- a/arch/arm/mach-sa1100/omnimeter.c
+++ b/arch/arm/mach-sa1100/omnimeter.c
@@ -54,7 +54,7 @@ fixup_omnimeter(struct machine_desc *desc, struct param_struct *params,
static struct map_desc omnimeter_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xd2000000, 0x10000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* TS */
+ { 0xd2000000, 0x10000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* TS */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pangolin.c b/arch/arm/mach-sa1100/pangolin.c
index f27c7f4aa836..37c4f6cbdf6a 100644
--- a/arch/arm/mach-sa1100/pangolin.c
+++ b/arch/arm/mach-sa1100/pangolin.c
@@ -30,7 +30,7 @@ fixup_pangolin(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pangolin_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
index 8820c4a97b3f..18a1396deccf 100644
--- a/arch/arm/mach-sa1100/pfs168.c
+++ b/arch/arm/mach-sa1100/pfs168.c
@@ -103,20 +103,20 @@ fixup_pfs168(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pfs168_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* 16C752 DUART port A (COM5) */
- { 0xf0001000, 0x10800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* 16C752 DUART port B (COM6) */
- { 0xf0002000, 0x11000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM1 RTS control (SYSC1RTS) */
- { 0xf0003000, 0x11400000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Status LED control (SYSLED) */
- { 0xf0004000, 0x11800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* DTMF code read (SYSDTMF) */
- { 0xf0005000, 0x11c00000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* LCD configure, enable (SYSLCDDE) */
- { 0xf0006000, 0x12000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM1 DSR and motion sense (SYSC1DSR) */
- { 0xf0007000, 0x12800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* COM3 xmit enable (SYSC3TEN) */
- { 0xf0008000, 0x13000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Control register A (SYSCTLA) */
- { 0xf0009000, 0x13800000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* Control register B (SYSCTLB) */
- { 0xf000a000, 0x18000000, 0x00001000, DOMAIN_IO, 1, 1, 0, 0 }, /* SMC91C96 */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf0000000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* 16C752 DUART port A (COM5) */
+ { 0xf0001000, 0x10800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* 16C752 DUART port B (COM6) */
+ { 0xf0002000, 0x11000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM1 RTS control (SYSC1RTS) */
+ { 0xf0003000, 0x11400000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Status LED control (SYSLED) */
+ { 0xf0004000, 0x11800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* DTMF code read (SYSDTMF) */
+ { 0xf0005000, 0x11c00000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD configure, enable (SYSLCDDE) */
+ { 0xf0006000, 0x12000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM1 DSR and motion sense (SYSC1DSR) */
+ { 0xf0007000, 0x12800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* COM3 xmit enable (SYSC3TEN) */
+ { 0xf0008000, 0x13000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Control register A (SYSCTLA) */
+ { 0xf0009000, 0x13800000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* Control register B (SYSCTLB) */
+ { 0xf000a000, 0x18000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 }, /* SMC91C96 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
+ { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index 49c608198034..d6fb7a186491 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -35,8 +35,8 @@ fixup_pleb(struct machine_desc *desc, struct param_struct *params,
static struct map_desc pleb_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
- { 0xe8400000, 0x08000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash, alternative location */
+ { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash memory */
+ { 0xe8400000, 0x08000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* main flash, alternative location */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 3f897f5c98ce..ec23699c6b38 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -58,7 +58,7 @@ fixup_simpad(struct machine_desc *desc, struct param_struct *params,
static struct map_desc simpad_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+ { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* MQ200 */
{ 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* Paules CS3, write only */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c
index eacf6f8d786f..b57d653571c9 100644
--- a/arch/arm/mach-sa1100/stork.c
+++ b/arch/arm/mach-sa1100/stork.c
@@ -305,10 +305,10 @@ stork_kbd_unexpected_up(unsigned char code)
struct map_desc stork_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
- { 0xf1000000, 0x10000000, 0x02800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
- { 0xf3800000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
+ { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { STORK_VM_BASE_CS1, STORK_VM_OFF_CS1, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
+ { 0xf1000000, 0x10000000, 0x02800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 2 */
+ { 0xf3800000, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* static memory bank 4 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
index 9745fea25720..34d08d17dc75 100644
--- a/arch/arm/mach-sa1100/system3.c
+++ b/arch/arm/mach-sa1100/system3.c
@@ -58,6 +58,7 @@
#include "generic.h"
#include "sa1111.h"
+#include <asm/hardware/sa1111.h>
#define DEBUG 1
@@ -74,19 +75,17 @@
/* init funcs */
static void __init fixup_system3(struct machine_desc *desc,
struct param_struct *params, char **cmdline, struct meminfo *mi);
-static void __init get_system3_scr(void);
static int __init system3_init(void);
static void __init system3_init_irq(void);
static void __init system3_map_io(void);
-static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs );
-static int system3_get_mctrl(struct uart_port *port);
+static u_int system3_get_mctrl(struct uart_port *port);
static void system3_set_mctrl(struct uart_port *port, u_int mctrl);
static void system3_uart_pm(struct uart_port *port, u_int state, u_int oldstate);
static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data);
-static int system3_lcd_power(int on);
-static int system3_backlight_power(int on);
+static void system3_lcd_power(int on);
+static void system3_backlight_power(int on);
extern void convert_to_tag_list(struct param_struct *params, int mem_init);
@@ -101,9 +100,9 @@ extern void convert_to_tag_list(struct param_struct *params, int mem_init);
static struct map_desc system3_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
- { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
- { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xe8000000, 0x00000000, 0x01000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash bank 0 */
+ { 0xf3000000, PT_CPLD_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* System Registers */
+ { 0xf4000000, PT_SA1111_BASE, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
@@ -113,12 +112,6 @@ static struct sa1100_port_fns system3_port_fns __initdata = {
pm: system3_uart_pm,
};
-static struct irqaction system3_irq = {
- name: "PT Digital Board SA1111 IRQ",
- handler: system3_IRQ_demux,
- flags: SA_INTERRUPT
-};
-
static struct notifier_block system3_clkchg_block = {
notifier_call: sdram_notifier,
};
@@ -145,56 +138,82 @@ static void __init system3_map_io(void)
/*********************************************************************
* Install IRQ handler
*/
-static void system3_IRQ_demux( int irq, void *dev_id, struct pt_regs *regs )
+static void
+system3_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
{
u_char irr;
- for(;;){
- //irr = PTCPLD_REG_IRQSR & (PT_IRQ_LAN | PT_IRQ_USAR | PT_IRQ_SA1111);
- irr = PT_IRQSR & (PT_IRQ_LAN | PT_IRQ_SA1111);
+ //DPRINTK( "irq=%d, desc=%p, regs=%p\n", irq, desc, regs );
- irr ^= (PT_IRQ_LAN);
- if (!irr) break;
+ while (1) {
+ struct irqdesc *d;
- if( irr & PT_IRQ_LAN )
- do_IRQ(IRQ_SYSTEM3_SMC9196, regs);
+ /*
+ * Acknowledge the parent IRQ.
+ */
+ desc->chip->ack(irq);
-#if 0
- /* Highspeed Serial Bus not yet used */
- if( irr & PT_IRQ_USAR )
- do_IRQ(PT_USAR_IRQ, regs);
-#endif
+ /*
+ * Read the interrupt reason register. Let's have all
+ * active IRQ bits high. Note: there is a typo in the
+ * Neponset user's guide for the SA1111 IRR level.
+ */
+ //irr = PT_IRQSR & (PT_IRR_LAN | PT_IRR_SA1111);
+ irr = PT_IRQSR & (PT_IRR_SA1111);
- if( irr & PT_IRQ_SA1111 )
- sa1111_IRQ_demux(irq, dev_id, regs);
- }
-}
+ /* SMC IRQ is low-active, so "switch" bit over */
+ //irr ^= (PT_IRR_LAN);
+ //DPRINTK( "irr=0x%02x\n", irr );
-static void __init system3_init_irq(void)
-{
- int irq;
+ if ((irr & (PT_IRR_LAN | PT_IRR_SA1111)) == 0)
+ break;
- DPRINTK( "%s\n", "START" );
+ /*
+ * Since there is no individual mask, we have to
+ * mask the parent IRQ. This is safe, since we'll
+ * recheck the register for any pending IRQs.
+ */
+ if (irr & (PT_IRR_LAN)) {
+ desc->chip->mask(irq);
+
+ if (irr & PT_IRR_LAN) {
+ //DPRINTK( "SMC9196, irq=%d\n", IRQ_SYSTEM3_SMC9196 );
+ d = irq_desc + IRQ_SYSTEM3_SMC9196;
+ d->handle(IRQ_SYSTEM3_SMC9196, d, regs);
+ }
+
+#if 0 /* no SSP yet on system 4 */
+ if (irr & IRR_USAR) {
+ d = irq_desc + IRQ_NEPONSET_USAR;
+ d->handle(IRQ_NEPONSET_USAR, d, regs);
+ }
+#endif
- /* SA1111 IRQ not routed to a GPIO. */
- sa1111_init_irq(-1);
+ desc->chip->unmask(irq);
+ }
- /* setup extra IRQs */
- irq = IRQ_SYSTEM3_SMC9196;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
+ if (irr & PT_IRR_SA1111) {
+ //DPRINTK( "SA1111, irq=%d\n", IRQ_SYSTEM3_SA1111 );
+ d = irq_desc + IRQ_SYSTEM3_SA1111;
+ d->handle(IRQ_SYSTEM3_SA1111, d, regs);
+ }
+ }
+}
-#if 0
- /* Highspeed Serial Bus not yet used */
- irq = PT_USAR_IRQ;
- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
-#endif
+static void __init system3_init_irq(void)
+{
+ /*
+ * Install handler for GPIO25.
+ */
+ set_irq_type(IRQ_GPIO25, IRQT_RISING);
+ set_irq_chained_handler(IRQ_GPIO25, system3_irq_handler);
- /* IRQ by CPLD */
- set_GPIO_IRQ_edge( GPIO_GPIO(25), GPIO_RISING_EDGE );
- setup_arm_irq( IRQ_GPIO25, &system3_irq );
+ /*
+ * install eth irq
+ */
+ set_irq_handler(IRQ_SYSTEM3_SMC9196, do_simple_IRQ);
+ set_irq_flags(IRQ_SYSTEM3_SMC9196, IRQF_VALID | IRQF_PROBE);
}
/**********************************************************************
@@ -270,7 +289,7 @@ static void system3_set_mctrl(struct uart_port *port, u_int mctrl)
}
}
-static int system3_get_mctrl(struct uart_port *port)
+static u_int system3_get_mctrl(struct uart_port *port)
{
u_int ret = 0;
u_int irqsr = PT_IRQSR;
@@ -358,12 +377,8 @@ static void system3_lcd_brightness(unsigned char value)
static void system3_lcd_power(int on)
{
-#error why is backlight stuff here???
if (on) {
system3_lcd_on();
- system3_lcd_backlight_on();
- system3_lcd_contrast(0x95);
- system3_lcd_brightness(240);
} else {
system3_lcd_off();
}
@@ -407,10 +422,12 @@ static int __init system3_init(void)
*/
sa1110_mb_disable();
+ system3_init_irq();
+
/*
* Probe for a SA1111.
*/
- ret = sa1111_probe(0x40000000);
+ ret = sa1111_probe(PT_SA1111_BASE);
if (ret < 0) {
printk( KERN_WARNING"PT Digital Board: no SA1111 found!\n" );
goto DONE;
@@ -443,7 +460,11 @@ static int __init system3_init(void)
*/
sa1110_mb_enable();
- system3_init_irq();
+ /*
+ * Initialise SA1111 IRQs
+ */
+ sa1111_init_irq(IRQ_SYSTEM3_SA1111);
+
#if defined( CONFIG_CPU_FREQ )
ret = cpufreq_register_notifier(&system3_clkchg_block);
@@ -453,6 +474,7 @@ static int __init system3_init(void)
}
#endif
+
ret = 0;
DONE:
DPRINTK( "ret=%d\n", ret );
diff --git a/arch/arm/mach-sa1100/victor.c b/arch/arm/mach-sa1100/victor.c
index a4378e32d4a2..27611b41fd7a 100644
--- a/arch/arm/mach-sa1100/victor.c
+++ b/arch/arm/mach-sa1100/victor.c
@@ -60,7 +60,7 @@ fixup_victor(struct machine_desc *desc, struct param_struct *params,
static struct map_desc victor_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+ { 0xe8000000, 0x00000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/xp860.c b/arch/arm/mach-sa1100/xp860.c
index 4e9f38b56869..c4ad798742ee 100644
--- a/arch/arm/mach-sa1100/xp860.c
+++ b/arch/arm/mach-sa1100/xp860.c
@@ -67,9 +67,9 @@ fixup_xp860(struct machine_desc *desc, struct param_struct *params,
static struct map_desc xp860_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SCSI */
- { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* LAN */
- { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
+ { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCSI */
+ { 0xf1000000, 0x18000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* LAN */
+ { 0xf4000000, 0x40000000, 0x00800000, DOMAIN_IO, 0, 1, 0, 0 }, /* SA-1111 */
LAST_DESC
};
diff --git a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
index fa8b5c8fc9c6..fc36c00aa49b 100644
--- a/arch/arm/mach-sa1100/yopy.c
+++ b/arch/arm/mach-sa1100/yopy.c
@@ -69,9 +69,9 @@ __initcall(yopy_hw_init);
static struct map_desc yopy_io_desc[] __initdata = {
/* virtual physical length domain r w c b */
- { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash 0 */
- { 0xec000000, 0x08000000, 0x04000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash 1 */
- { 0xf0000000, 0x48000000, 0x00300000, DOMAIN_IO, 1, 1, 0, 0 }, /* LCD */
+ { 0xe8000000, 0x00000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash 0 */
+ { 0xec000000, 0x08000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* Flash 1 */
+ { 0xf0000000, 0x48000000, 0x00300000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD */
{ 0xf1000000, 0x10000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO */
LAST_DESC
};
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 30a10cb07775..22428e7d98b4 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -151,7 +151,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
if (pmd_bad(*pmd))
goto bad_pmd;
- pte = pte_offset(pmd, address);
+ pte = pte_offset_map(pmd, address);
entry = *pte;
/*
@@ -164,6 +164,7 @@ static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
set_pte(pte, entry);
flush_tlb_page(vma, address);
}
+ pte_unmap(pte);
return;
bad_pgd:
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
index 699e5208d1d4..b39fd67963f7 100644
--- a/arch/arm/mm/fault-common.c
+++ b/arch/arm/mm/fault-common.c
@@ -83,11 +83,15 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
}
- pte = pte_offset(pmd, addr);
+#ifndef CONFIG_HIGHMEM
+ /* We must not map this if we have highmem enabled */
+ pte = pte_offset_map(pmd, addr);
printk(", *pte = %08lx", pte_val(*pte));
#ifdef CONFIG_CPU_32
printk(", *ppte = %08lx", pte_val(pte[-PTRS_PER_PTE]));
#endif
+ pte_unmap(pte);
+#endif
} while(0);
printk("\n");
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b2fcc416756f..c9b4ba1f39ea 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -64,38 +64,6 @@ static struct meminfo meminfo __initdata = { 0, };
*/
struct page *empty_zero_page;
-#ifndef CONFIG_NO_PGT_CACHE
-struct pgtable_cache_struct quicklists;
-
-int do_check_pgt_cache(int low, int high)
-{
- int freed = 0;
-
- if(pgtable_cache_size > high) {
- do {
- if(pgd_quicklist) {
- free_pgd_slow(get_pgd_fast());
- freed++;
- }
- if(pmd_quicklist) {
- pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
- freed++;
- }
- if(pte_quicklist) {
- pte_free_slow(pte_alloc_one_fast(NULL, 0));
- freed++;
- }
- } while(pgtable_cache_size > low);
- }
- return freed;
-}
-#else
-int do_check_pgt_cache(int low, int high)
-{
- return 0;
-}
-#endif
-
/* This is currently broken
* PG_skip is used on sparc/sparc64 architectures to "skip" certain
* parts of the address space.
@@ -145,9 +113,6 @@ void show_mem(void)
printk("%d slab pages\n", slab);
printk("%d pages shared\n", shared);
printk("%d pages swap cached\n", cached);
-#ifndef CONFIG_NO_PGT_CACHE
- printk("%ld page tables cached\n", pgtable_cache_size);
-#endif
show_buffers();
}
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
index 8aa87e9b2487..7f20b9d0ea85 100644
--- a/arch/arm/mm/minicache.c
+++ b/arch/arm/mm/minicache.c
@@ -58,7 +58,7 @@ static int __init minicache_init(void)
pmd = pmd_alloc(&init_mm, pgd, minicache_address);
if (!pmd)
BUG();
- minicache_pte = pte_alloc(&init_mm, pmd, minicache_address);
+ minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
if (!minicache_pte)
BUG();
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 10605d6aa11e..d8dfc4e019ac 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -98,11 +98,15 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
if (!new_pmd)
goto no_pmd;
- new_pte = pte_alloc(mm, new_pmd, 0);
+ new_pte = pte_alloc_map(mm, new_pmd, 0);
if (!new_pte)
goto no_pte;
+ init_pmd = pmd_offset(init_pgd, 0);
+ init_pte = pte_offset_map_nested(init_pmd, 0);
set_pte(new_pte, *init_pte);
+ pte_unmap_nested(init_pte);
+ pte_unmap(new_pte);
spin_unlock(&mm->page_table_lock);
}
@@ -138,7 +142,7 @@ no_pgd:
void free_pgd_slow(pgd_t *pgd)
{
pmd_t *pmd;
- pte_t *pte;
+ struct page *pte;
if (!pgd)
return;
@@ -153,7 +157,7 @@ void free_pgd_slow(pgd_t *pgd)
goto free;
}
- pte = pte_offset(pmd, 0);
+ pte = pmd_page(*pmd);
pmd_clear(pmd);
pte_free(pte);
pmd_free(pmd);
@@ -198,7 +202,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
}
- ptep = pte_offset(pmdp, virt);
+ ptep = pte_offset_kernel(pmdp, virt);
set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
}
@@ -225,6 +229,20 @@ static void __init create_mapping(struct map_desc *md)
int prot_sect, prot_pte;
long off;
+ if (md->prot_read && md->prot_write &&
+ !md->cacheable && !md->bufferable) {
+ printk(KERN_WARNING "Security risk: creating user "
+ "accessible mapping for 0x%08lx at 0x%08lx\n",
+ md->physical, md->virtual);
+ }
+
+ if (md->virtual != vectors_base() && md->virtual < PAGE_OFFSET) {
+ printk(KERN_WARNING "MM: not creating mapping for "
+ "0x%08lx at 0x%08lx in user region\n",
+ md->physical, md->virtual);
+ return;
+ }
+
prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
(md->prot_read ? L_PTE_USER : 0) |
(md->prot_write ? L_PTE_WRITE : 0) |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index f4a2ed50ba23..3e67f274c60a 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -663,8 +663,8 @@ cpu_manu_name:
cpu_80200_name:
.asciz "XScale-80200"
-cpu_cotulla_name:
- .asciz "XScale-Cotulla"
+cpu_pxa250_name:
+ .asciz "XScale-PXA250"
.align
@@ -734,11 +734,11 @@ cpu_80200_info:
.long cpu_80200_name
.size cpu_80200_info, . - cpu_80200_info
- .type cpu_cotulla_info, #object
-cpu_cotulla_info:
+ .type cpu_pxa250_info, #object
+cpu_pxa250_info:
.long cpu_manu_name
- .long cpu_cotulla_name
- .size cpu_cotulla_info, . - cpu_cotulla_info
+ .long cpu_pxa250_name
+ .size cpu_pxa250_info, . - cpu_pxa250_info
.type cpu_arch_name, #object
cpu_arch_name:
@@ -767,8 +767,8 @@ __80200_proc_info:
.long v4wbi_tlb_fns
.size __80200_proc_info, . - __80200_proc_info
- .type __cotulla_proc_info,#object
-__cotulla_proc_info:
+ .type __pxa250_proc_info,#object
+__pxa250_proc_info:
.long 0x69052100
.long 0xfffffff0
.long 0x00000c0e
@@ -776,8 +776,9 @@ __cotulla_proc_info:
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
- .long cpu_cotulla_info
+ .long cpu_pxa250_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
.size __cotulla_proc_info, . - __cotulla_proc_info
+ .size __pxa250_proc_info, . - __pxa250_proc_info
diff --git a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in
index 6556020c1231..ae5294fa23db 100644
--- a/drivers/pcmcia/Config.in
+++ b/drivers/pcmcia/Config.in
@@ -24,5 +24,6 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
dep_tristate ' HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
fi
fi
+dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
endmenu
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index f4c21c2ba25b..dda91ec562e0 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -62,22 +62,25 @@ endif
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
sa1100_cs-objs-y := sa1100_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
-sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
-sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
+sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
+sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
+sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
+sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o
-sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o
+sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
+sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o
-sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
-sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
-sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o
-sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
-sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
+sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o sa1111_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o sa1111_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
-sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o
-sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o
sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o
+sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
+sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
include $(TOPDIR)/Rules.make
@@ -85,7 +88,7 @@ pcmcia_core.o: $(pcmcia_core-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(pcmcia_core-objs)
sa1100_cs.o: $(sa1100_cs-objs-y)
- $(LD) -r -o $@ $(sa1100_cs-objs-y)
+ $(LD) -r -o $@ $(sort $(sa1100_cs-objs-y))
yenta_socket.o: $(yenta_socket-objs)
$(LD) $(LD_RFLAG) -r -o $@ $(yenta_socket-objs)
diff --git a/drivers/pcmcia/sa1100.h b/drivers/pcmcia/sa1100.h
index eda4f6d7d6db..8f45ca6e3aaf 100644
--- a/drivers/pcmcia/sa1100.h
+++ b/drivers/pcmcia/sa1100.h
@@ -38,9 +38,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
-
-#include <asm/arch/pcmcia.h>
-
+#include "sa1100_generic.h"
/* MECR: Expansion Memory Configuration Register
* (SA-1100 Developers Manual, p.10-13; SA-1110 Developers Manual, p.10-24)
@@ -157,15 +155,24 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,
* use when responding to a Card Services query of some kind.
*/
struct sa1100_pcmcia_socket {
+ /*
+ * Core PCMCIA state
+ */
socket_state_t cs_state;
- struct pcmcia_state k_state;
- unsigned int irq;
- void (*handler)(void *, unsigned int);
- void *handler_info;
pccard_io_map io_map[MAX_IO_WIN];
pccard_mem_map mem_map[MAX_WIN];
- ioaddr_t virt_io, phys_attr, phys_mem;
+ void (*handler)(void *, unsigned int);
+ void *handler_info;
+
+ struct pcmcia_state k_state;
+ ioaddr_t phys_attr, phys_mem;
+ void *virt_io;
unsigned short speed_io, speed_attr, speed_mem;
+
+ /*
+ * Info from low level handler
+ */
+ unsigned int irq;
};
@@ -180,23 +187,60 @@ struct sa1100_pcmcia_socket {
/*
- * Declaration for all implementation specific low_level operations.
+ * Declaration for all machine specific init/exit functions.
*/
-extern struct pcmcia_low_level assabet_pcmcia_ops;
-extern struct pcmcia_low_level neponset_pcmcia_ops;
-extern struct pcmcia_low_level h3600_pcmcia_ops;
-extern struct pcmcia_low_level cerf_pcmcia_ops;
-extern struct pcmcia_low_level gcplus_pcmcia_ops;
-extern struct pcmcia_low_level xp860_pcmcia_ops;
-extern struct pcmcia_low_level yopy_pcmcia_ops;
-extern struct pcmcia_low_level pangolin_pcmcia_ops;
-extern struct pcmcia_low_level freebird_pcmcia_ops;
-extern struct pcmcia_low_level pfs168_pcmcia_ops;
-extern struct pcmcia_low_level jornada720_pcmcia_ops;
-extern struct pcmcia_low_level flexanet_pcmcia_ops;
-extern struct pcmcia_low_level simpad_pcmcia_ops;
-extern struct pcmcia_low_level graphicsmaster_pcmcia_ops;
-extern struct pcmcia_low_level adsbitsy_pcmcia_ops;
-extern struct pcmcia_low_level stork_pcmcia_ops;
+extern int pcmcia_adsbitsy_init(void);
+extern void pcmcia_adsbitsy_exit(void);
+
+extern int pcmcia_assabet_init(void);
+extern void pcmcia_assabet_exit(void);
+
+extern int pcmcia_badge4_init(void);
+extern void pcmcia_badge4_exit(void);
+
+extern int pcmcia_cerf_init(void);
+extern void pcmcia_cerf_exit(void);
+
+extern int pcmcia_flexanet_init(void);
+extern void pcmcia_flexanet_exit(void);
+
+extern int pcmcia_freebird_init(void);
+extern void pcmcia_freebird_exit(void);
+
+extern int pcmcia_gcplus_init(void);
+extern void pcmcia_gcplus_exit(void);
+
+extern int pcmcia_graphicsmaster_init(void);
+extern void pcmcia_graphicsmaster_exit(void);
+
+extern int pcmcia_jornada720_init(void);
+extern void pcmcia_jornada720_exit(void);
+
+extern int pcmcia_neponset_init(void);
+extern void pcmcia_neponset_exit(void);
+
+extern int pcmcia_pangolin_init(void);
+extern void pcmcia_pangolin_exit(void);
+
+extern int pcmcia_pfs168_init(void);
+extern void pcmcia_pfs168_exit(void);
+
+extern int pcmcia_shannon_init(void);
+extern void pcmcia_shannon_exit(void);
+
+extern int pcmcia_simpad_init(void);
+extern void pcmcia_simpad_exit(void);
+
+extern int pcmcia_stork_init(void);
+extern void pcmcia_stork_exit(void);
+
+extern int pcmcia_system3_init(void);
+extern void pcmcia_system3_exit(void);
+
+extern int pcmcia_xp860_init(void);
+extern void pcmcia_xp860_exit(void);
+
+extern int pcmcia_yopy_init(void);
+extern void pcmcia_yopy_exit(void);
#endif /* !defined(_PCMCIA_SA1100_H) */
diff --git a/drivers/pcmcia/sa1100_adsbitsy.c b/drivers/pcmcia/sa1100_adsbitsy.c
index 1793f24faa70..17d87ab2e2a4 100644
--- a/drivers/pcmcia/sa1100_adsbitsy.c
+++ b/drivers/pcmcia/sa1100_adsbitsy.c
@@ -11,206 +11,97 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
-#include <asm/delay.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
static int adsbitsy_pcmcia_init(struct pcmcia_init *init)
{
- int return_val=0;
-
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* Disable Power 3.3V/5V for PCMCIA/CF */
PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
- INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "GC Master PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "GC Master CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "GC Master PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "GC Master CF (1) BVD1", NULL);
-
+ /* Why? */
MECR = 0x09430943;
- return (return_val<0) ? -1 : 2;
-}
-
-static int adsbitsy_pcmcia_shutdown(void)
-{
-
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
-
- INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
-
- return 0;
+ return sa1111_pcmcia_init(init);
}
-static int adsbitsy_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+static int
+adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- status=PCSR;
-
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
+ unsigned int pa_dwr_mask, pa_dwr_set;
+ int ret;
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-
- return return_val;
-}
-
-static int adsbitsy_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-{
-
- switch(info->sock){
+ switch (conf->sock) {
case 0:
- info->irq=S0_READY_NINT;
- break;
-
- case 1:
- info->irq=S1_READY_NINT;
- break;
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *configure)
-{
- unsigned long pccr=PCCR, gpio=PA_DWR;
-
- switch(configure->sock){
- case 0:
-
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S0_FLT);
- gpio |= GPIO_GPIO0 | GPIO_GPIO1;
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
- gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
- gpio &= ~GPIO_GPIO0;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
- gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
- gpio |= GPIO_GPIO0;
- break;
+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
+ case 33: pa_dwr_set = GPIO_GPIO1; break;
+ case 50: pa_dwr_set = GPIO_GPIO0; break;
}
-
- pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
-
break;
case 1:
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S1_FLT);
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
- gpio |= GPIO_GPIO2;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
- gpio |= GPIO_GPIO3;
- break;
+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO2; break;
+ case 50: pa_dwr_set = GPIO_GPIO3; break;
}
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
- }
-
- pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
-
- break;
-
default:
return -1;
}
- PCCR = pccr;
- PA_DWR = gpio;
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
+ __FUNCTION__, conf->vpp);
+ return -1;
+ }
+
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
- return 0;
+ local_irq_save(flags);
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ local_irq_restore(flags);
+ }
+
+ return ret;
}
-struct pcmcia_low_level adsbitsy_pcmcia_ops = {
- adsbitsy_pcmcia_init,
- adsbitsy_pcmcia_shutdown,
- adsbitsy_pcmcia_socket_state,
- adsbitsy_pcmcia_get_irq_info,
- adsbitsy_pcmcia_configure_socket
+static struct pcmcia_low_level adsbitsy_pcmcia_ops = {
+ init: adsbitsy_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: adsbitsy_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
};
+int __init pcmcia_adsbitsy_init(void)
+{
+ int ret = -ENODEV;
+ if (machine_is_adsbitsy())
+ ret = sa1100_register_pcmcia(&adsbitsy_pcmcia_ops);
+ return ret;
+}
+
+void __exit pcmcia_adsbitsy_exit(void)
+{
+ sa1100_unregister_pcmcia(&adsbitsy_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index 2dd8c9d03919..1a7cc433cf85 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -4,146 +4,221 @@
* PCMCIA implementation routines for Assabet
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
#include <asm/arch/assabet.h>
-static int assabet_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
+#include "sa1100_generic.h"
- /* Enable CF bus: */
- ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { ASSABET_IRQ_GPIO_CF_CD, "CF_CD" },
+ { ASSABET_IRQ_GPIO_CF_BVD2, "CF_BVD2" },
+ { ASSABET_IRQ_GPIO_CF_BVD1, "CF_BVD1" },
+};
+
+static int assabet_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, res;
+
+ /* Set transition detect */
+ set_irq_type(ASSABET_IRQ_GPIO_CF_IRQ, IRQT_FALLING);
- /* All those are inputs */
- GPDR &= ~(ASSABET_GPIO_CF_CD | ASSABET_GPIO_CF_BVD2 | ASSABET_GPIO_CF_BVD1 | ASSABET_GPIO_CF_IRQ);
+ /* Register interrupts */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
- /* Set transition detect */
- set_GPIO_IRQ_edge( ASSABET_GPIO_CF_CD|ASSABET_GPIO_CF_BVD2|ASSABET_GPIO_CF_BVD1, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( ASSABET_GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
- /* Register interrupts */
- irq = ASSABET_IRQ_GPIO_CF_CD;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
- if( res < 0 ) goto irq_err;
- irq = ASSABET_IRQ_GPIO_CF_BVD2;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
- if( res < 0 ) goto irq_err;
- irq = ASSABET_IRQ_GPIO_CF_BVD1;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
- if( res < 0 ) goto irq_err;
+ irq_err:
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
- /* There's only one slot, but it's "Slot 1": */
- return 2;
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
-irq_err:
- printk( KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__, irq );
- return -1;
+ return res;
}
+/*
+ * Release all resources.
+ */
static int assabet_pcmcia_shutdown(void)
{
- /* disable IRQs */
- free_irq( ASSABET_IRQ_GPIO_CF_CD, NULL );
- free_irq( ASSABET_IRQ_GPIO_CF_BVD2, NULL );
- free_irq( ASSABET_IRQ_GPIO_CF_BVD1, NULL );
-
- /* Disable CF bus: */
- ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF);
+ int i;
- return 0;
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
+
+ return 0;
}
-static int assabet_pcmcia_socket_state(struct pcmcia_state_array
- *state_array){
- unsigned long levels;
+static int
+assabet_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long levels;
- if(state_array->size<2) return -1;
+ if (state_array->size < 2)
+ return -1;
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
+ levels = GPLR;
- levels=GPLR;
+ state_array->state[1].detect = (levels & ASSABET_GPIO_CF_CD) ? 0 : 1;
+ state_array->state[1].ready = (levels & ASSABET_GPIO_CF_IRQ) ? 1 : 0;
+ state_array->state[1].bvd1 = (levels & ASSABET_GPIO_CF_BVD1) ? 1 : 0;
+ state_array->state[1].bvd2 = (levels & ASSABET_GPIO_CF_BVD2) ? 1 : 0;
+ state_array->state[1].wrprot = 0; /* Not available on Assabet. */
+ state_array->state[1].vs_3v = 1; /* Can only apply 3.3V on Assabet. */
+ state_array->state[1].vs_Xv = 0;
- state_array->state[1].detect=((levels & ASSABET_GPIO_CF_CD)==0)?1:0;
+ return 1;
+}
- state_array->state[1].ready=(levels & ASSABET_GPIO_CF_IRQ)?1:0;
+static int assabet_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ if (info->sock > 1)
+ return -1;
- state_array->state[1].bvd1=(levels & ASSABET_GPIO_CF_BVD1)?1:0;
+ if (info->sock == 1)
+ info->irq = ASSABET_IRQ_GPIO_CF_IRQ;
- state_array->state[1].bvd2=(levels & ASSABET_GPIO_CF_BVD2)?1:0;
+ return 0;
+}
- state_array->state[1].wrprot=0; /* Not available on Assabet. */
+static int
+assabet_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+ unsigned int mask;
- state_array->state[1].vs_3v=1; /* Can only apply 3.3V on Assabet. */
+ if (configure->sock > 1)
+ return -1;
- state_array->state[1].vs_Xv=0;
+ if (configure->sock == 0)
+ return 0;
- return 1;
-}
+ switch (configure->vcc) {
+ case 0:
+ mask = 0;
+ break;
-static int assabet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
- if(info->sock>1) return -1;
+ case 33: /* Can only apply 3.3V to the CF slot. */
+ mask = ASSABET_BCR_CF_PWR;
+ break;
- if(info->sock==1)
- info->irq=ASSABET_IRQ_GPIO_CF_IRQ;
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
- return 0;
-}
+ /* Silently ignore Vpp, output enable, speaker enable. */
-static int assabet_pcmcia_configure_socket(const struct pcmcia_configure
- *configure)
-{
- unsigned long value, flags;
+ if (configure->reset)
+ mask |= ASSABET_BCR_CF_RST;
- if(configure->sock>1) return -1;
+ ASSABET_BCR_frob(ASSABET_BCR_CF_RST | ASSABET_BCR_CF_PWR, mask);
- if(configure->sock==0) return 0;
+ /*
+ * Handle suspend mode properly. This prevents a
+ * flood of IRQs from the CF device.
+ */
+ if (configure->irq)
+ enable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
+ else
+ disable_irq(ASSABET_IRQ_GPIO_CF_IRQ);
- save_flags_cli(flags);
+ return 0;
+}
- value = BCR_value;
+/*
+ * Enable card status IRQs on (re-)initialisation. This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static int assabet_pcmcia_socket_init(int sock)
+{
+ int i;
- switch(configure->vcc){
- case 0:
- value &= ~ASSABET_BCR_CF_PWR;
- break;
+ if (sock == 1) {
+ /*
+ * Enable CF bus
+ */
+ ASSABET_BCR_clear(ASSABET_BCR_CF_BUS_OFF);
- case 50:
- printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
- __FUNCTION__);
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
+ }
- case 33: /* Can only apply 3.3V to the CF slot. */
- value |= ASSABET_BCR_CF_PWR;
- break;
+ return 0;
+}
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- restore_flags(flags);
- return -1;
- }
+/*
+ * Disable card status IRQs on suspend.
+ */
+static int assabet_pcmcia_socket_suspend(int sock)
+{
+ int i;
- value = (configure->reset) ? (value | ASSABET_BCR_CF_RST) : (value & ~ASSABET_BCR_CF_RST);
+ if (sock == 1) {
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
- /* Silently ignore Vpp, output enable, speaker enable. */
+ /*
+ * Tristate the CF bus signals. Also assert CF
+ * reset as per user guide page 4-11.
+ */
+ ASSABET_BCR_set(ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_CF_RST);
+ }
- ASSABET_BCR = BCR_value = value;
+ return 0;
+}
+
+static struct pcmcia_low_level assabet_pcmcia_ops = {
+ init: assabet_pcmcia_init,
+ shutdown: assabet_pcmcia_shutdown,
+ socket_state: assabet_pcmcia_socket_state,
+ get_irq_info: assabet_pcmcia_get_irq_info,
+ configure_socket: assabet_pcmcia_configure_socket,
- restore_flags(flags);
+ socket_init: assabet_pcmcia_socket_init,
+ socket_suspend: assabet_pcmcia_socket_suspend,
+};
- return 0;
+int __init pcmcia_assabet_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_assabet()) {
+ if (!machine_has_neponset())
+ ret = sa1100_register_pcmcia(&assabet_pcmcia_ops);
+#ifndef CONFIG_ASSABET_NEPONSET
+ else
+ printk(KERN_ERR "Card Services disabled: missing "
+ "Neponset support\n");
+#endif
+ }
+ return ret;
}
-struct pcmcia_low_level assabet_pcmcia_ops = {
- assabet_pcmcia_init,
- assabet_pcmcia_shutdown,
- assabet_pcmcia_socket_state,
- assabet_pcmcia_get_irq_info,
- assabet_pcmcia_configure_socket
-};
+void __exit pcmcia_assabet_exit(void)
+{
+ sa1100_unregister_pcmcia(&assabet_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
new file mode 100644
index 000000000000..41cba02b9944
--- /dev/null
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -0,0 +1,186 @@
+/*
+ * linux/drivers/pcmcia/sa1100_badge4.c
+ *
+ * BadgePAD 4 PCMCIA specific routines
+ *
+ * Christopher Hoover <ch@hpl.hp.com>
+ *
+ * Copyright (C) 2002 Hewlett-Packard Company
+ *
+ * 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/badge4.h>
+#include <asm/hardware/sa1111.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
+
+/*
+ * BadgePAD 4 Details
+ *
+ * PCM Vcc:
+ *
+ * PCM Vcc on BadgePAD 4 can be jumpered for 3.3V (short pins 1 and 3
+ * on JP6) or 5V (short pins 3 and 5 on JP6). N.B., 5V supply rail
+ * is enabled by the SA-1110's BADGE4_GPIO_PCMEN5V (GPIO 24).
+ *
+ * PCM Vpp:
+ *
+ * PCM Vpp on BadgePAD 4 can be jumpered for 12V (short pins 2 and 4
+ * on JP6) or tied to PCM Vcc (short pins 4 and 6 on JP6). N.B., 12V
+ * operation requires that the power supply actually supply 12V.
+ *
+ * CF Vcc:
+ *
+ * CF Vcc on BadgePAD 4 can be jumpered either for 3.3V (short pins 1
+ * and 2 on JP10) or 5V (short pins 2 and 3 on JP10). The note above
+ * about the 5V supply rail applies.
+ *
+ * There's no way programmatically to determine how a given board is
+ * jumpered. This code assumes a default jumpering: 5V PCM Vcc (pins
+ * 3 and 5 shorted) and PCM Vpp = PCM Vcc (pins 4 and 6 shorted) and
+ * no jumpering for CF Vcc. If this isn't correct, Override these
+ * defaults with a pcmv setup argument: pcmv=<pcm vcc>,<pcm vpp>,<cf
+ * vcc>. E.g. pcmv=33,120,50 indicates 3.3V PCM Vcc, 12.0V PCM Vpp,
+ * and 5.0V CF Vcc.
+ *
+ */
+
+static int badge4_pcmvcc = 50;
+static int badge4_pcmvpp = 50;
+static int badge4_cfvcc = 0;
+
+static int badge4_pcmcia_init(struct pcmcia_init *init)
+{
+ printk(KERN_INFO __FUNCTION__
+ ": badge4_pcmvcc=%d, badge4_pcmvpp=%d, badge4_cfvcc=%d\n",
+ badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc);
+
+ return sa1111_pcmcia_init(init);
+}
+
+static int badge4_pcmcia_shutdown(void)
+{
+ int rc = sa1111_pcmcia_shutdown();
+
+ /* be sure to disable 5V use */
+ badge4_set_5V(BADGE4_5V_PCMCIA_SOCK0, 0);
+ badge4_set_5V(BADGE4_5V_PCMCIA_SOCK1, 0);
+
+ return rc;
+}
+
+static void complain_about_jumpering(const char *whom,
+ const char *supply,
+ int given, int wanted)
+{
+ printk(KERN_ERR
+ "%s: %s %d.%dV wanted but board is jumpered for %s %d.%dV operation"
+ "; re-jumper the board and/or use pcmv=xx,xx,xx\n",
+ whom, supply,
+ wanted / 10, wanted % 10,
+ supply,
+ given / 10, given % 10);
+}
+
+static unsigned badge4_need_5V_bitmap = 0;
+
+static int
+badge4_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ int ret;
+
+ switch (conf->sock) {
+ case 0:
+ if ((conf->vcc != 0) &&
+ (conf->vcc != badge4_pcmvcc)) {
+ complain_about_jumpering(__FUNCTION__, "pcmvcc",
+ badge4_pcmvcc, conf->vcc);
+ return -1;
+ }
+ if ((conf->vpp != 0) &&
+ (conf->vpp != badge4_pcmvpp)) {
+ complain_about_jumpering(__FUNCTION__, "pcmvpp",
+ badge4_pcmvpp, conf->vpp);
+ return -1;
+ }
+ break;
+
+ case 1:
+ if ((conf->vcc != 0) &&
+ (conf->vcc != badge4_cfvcc)) {
+ complain_about_jumpering(__FUNCTION__, "cfvcc",
+ badge4_cfvcc, conf->vcc);
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+ int need5V;
+
+ local_irq_save(flags);
+
+ need5V = ((conf->vcc == 50) || (conf->vpp == 50));
+
+ badge4_set_5V(BADGE4_5V_PCMCIA_SOCK(conf->sock), need5V);
+
+ local_irq_restore(flags);
+ }
+
+ return 0;
+}
+
+static struct pcmcia_low_level badge4_pcmcia_ops = {
+ init: badge4_pcmcia_init,
+ shutdown: badge4_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: badge4_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
+};
+
+int __init pcmcia_badge4_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_badge4())
+ ret = sa1100_register_pcmcia(&badge4_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_badge4_exit(void)
+{
+ sa1100_unregister_pcmcia(&badge4_pcmcia_ops);
+}
+
+static int __init pcmv_setup(char *s)
+{
+ int v[4];
+
+ s = get_options(s, ARRAY_SIZE(v), v);
+
+ if (v[0] >= 1) badge4_pcmvcc = v[1];
+ if (v[0] >= 2) badge4_pcmvpp = v[2];
+ if (v[0] >= 3) badge4_cfvcc = v[3];
+
+ return 1;
+}
+
+__setup("pcmv=", pcmv_setup);
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index 3b19eeba5924..f3142cea6deb 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -5,45 +5,62 @@
* Based off the Assabet.
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
+#ifdef CONFIG_SA1100_CERF_CPLD
+#define CERF_SOCKET 0
+#else
+#define CERF_SOCKET 1
+#endif
-static int cerf_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { IRQ_GPIO_CF_CD, "CF_CD" },
+ { IRQ_GPIO_CF_BVD2, "CF_BVD2" },
+ { IRQ_GPIO_CF_BVD1, "CF_BVD1" }
+};
- GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
- GPDR |= (GPIO_CF_RESET);
+static int cerf_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, res;
- set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+ set_irq_type(IRQ_GPIO_CF_IRQ, IRQT_FALLING);
- irq = IRQ_GPIO_CF_CD;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
- if( res < 0 ) goto irq_err;
- irq = IRQ_GPIO_CF_BVD2;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL );
- if( res < 0 ) goto irq_err;
- irq = IRQ_GPIO_CF_BVD1;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
- if( res < 0 ) goto irq_err;
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
return 2;
-irq_err:
- printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
- return -1;
+ irq_err:
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ return res;
}
static int cerf_pcmcia_shutdown(void)
{
- free_irq( IRQ_GPIO_CF_CD, NULL );
- free_irq( IRQ_GPIO_CF_BVD2, NULL );
- free_irq( IRQ_GPIO_CF_BVD1, NULL );
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
return 0;
}
@@ -51,31 +68,18 @@ static int cerf_pcmcia_shutdown(void)
static int cerf_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
unsigned long levels;
-#ifdef CONFIG_SA1100_CERF_CPLD
- int i = 0;
-#else
- int i = 1;
-#endif
+ int i = CERF_SOCKET;
if(state_array->size<2) return -1;
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
levels=GPLR;
state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
-
state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
-
state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
-
state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
-
state_array->state[i].wrprot=0;
-
state_array->state[i].vs_3v=1;
-
state_array->state[i].vs_Xv=0;
return 1;
@@ -85,11 +89,7 @@ static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
if(info->sock>1) return -1;
-#ifdef CONFIG_SA1100_CERF_CPLD
- if(info->sock==0)
-#else
- if(info->sock==1)
-#endif
+ if (info->sock == CERF_SOCKET)
info->irq=IRQ_GPIO_CF_IRQ;
return 0;
@@ -98,20 +98,12 @@ static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
{
- unsigned long flags;
-
if(configure->sock>1)
return -1;
-#ifdef CONFIG_SA1100_CERF_CPLD
- if(configure->sock==1)
-#else
- if(configure->sock==0)
-#endif
+ if (configure->sock != CERF_SOCKET)
return 0;
- save_flags_cli(flags);
-
switch(configure->vcc){
case 0:
break;
@@ -119,43 +111,76 @@ static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
case 50:
case 33:
#ifdef CONFIG_SA1100_CERF_CPLD
- GPDR |= GPIO_PWR_SHUTDOWN;
- GPCR |= GPIO_PWR_SHUTDOWN;
+ GPCR = GPIO_PWR_SHUTDOWN;
#endif
break;
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
- restore_flags(flags);
return -1;
}
if(configure->reset)
{
#ifdef CONFIG_SA1100_CERF_CPLD
- GPDR |= GPIO_CF_RESET;
- GPSR |= GPIO_CF_RESET;
+ GPSR = GPIO_CF_RESET;
#endif
}
else
{
#ifdef CONFIG_SA1100_CERF_CPLD
- GPDR |= GPIO_CF_RESET;
- GPCR |= GPIO_CF_RESET;
+ GPCR = GPIO_CF_RESET;
#endif
}
- restore_flags(flags);
+ return 0;
+}
+
+static int cerf_pcmcia_socket_init(int sock)
+{
+ int i;
+
+ if (sock == CERF_SOCKET)
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
return 0;
}
-struct pcmcia_low_level cerf_pcmcia_ops = {
- cerf_pcmcia_init,
- cerf_pcmcia_shutdown,
- cerf_pcmcia_socket_state,
- cerf_pcmcia_get_irq_info,
- cerf_pcmcia_configure_socket
+static int cerf_pcmcia_socket_suspend(int sock)
+{
+ int i;
+
+ if (sock == CERF_SOCKET)
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+
+ return 0;
+}
+
+static struct pcmcia_low_level cerf_pcmcia_ops = {
+ init: cerf_pcmcia_init,
+ shutdown: cerf_pcmcia_shutdown,
+ socket_state: cerf_pcmcia_socket_state,
+ get_irq_info: cerf_pcmcia_get_irq_info,
+ configure_socket: cerf_pcmcia_configure_socket,
+
+ socket_init: cerf_pcmcia_socket_init,
+ socket_suspend: cerf_pcmcia_socket_suspend,
};
+int __init pcmcia_cerf_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_cerf())
+ ret = sa1100_register_pcmcia(&cerf_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_cerf_exit(void)
+{
+ sa1100_unregister_pcmcia(&cerf_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_flexanet.c b/drivers/pcmcia/sa1100_flexanet.c
index 14f94bc810fb..edb8c9c029cf 100644
--- a/drivers/pcmcia/sa1100_flexanet.c
+++ b/drivers/pcmcia/sa1100_flexanet.c
@@ -4,16 +4,25 @@
* PCMCIA implementation routines for Flexanet.
* by Jordi Colomer, 09/05/2001
*
- * Yet to be defined.
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
-
+#include "sa1100_generic.h"
+
+static struct {
+ int irq;
+ const char *name;
+} irqs[] = {
+ { IRQ_GPIO_CF1_CD, "CF1_CD" },
+ { IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
+ { IRQ_GPIO_CF2_CD, "CF2_CD" },
+ { IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
+};
/*
* Socket initialization.
@@ -22,9 +31,37 @@
* Must return the number of slots.
*
*/
-static int flexanet_pcmcia_init(struct pcmcia_init *init){
-
- return 0;
+static int flexanet_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, res;
+
+ /* Configure the GPIOs as inputs (BVD2 is not implemented) */
+ GPDR &= ~(GPIO_CF1_NCD | GPIO_CF1_BVD1 | GPIO_CF1_IRQ |
+ GPIO_CF2_NCD | GPIO_CF2_BVD1 | GPIO_CF2_IRQ );
+
+ /* Set IRQ edge */
+ set_irq_type(IRQ_GPIO_CF1_IRQ, IRQT_FALLING);
+ set_irq_type(IRQ_GPIO_CF2_IRQ, IRQT_FALLING);
+
+ /* Register the socket interrupts (not the card interrupts) */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].name, NULL);
+ if (res < 0)
+ break;
+ }
+
+ /* If we failed, then free all interrupts requested thus far. */
+ if (res < 0) {
+ printk(KERN_ERR "%s: request for IRQ%d failed: %d\n",
+ __FUNCTION__, irqs[i].irq, res);
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+ return res;
+ }
+
+ return 2;
}
@@ -34,6 +71,12 @@ static int flexanet_pcmcia_init(struct pcmcia_init *init){
*/
static int flexanet_pcmcia_shutdown(void)
{
+ int i;
+
+ /* disable IRQs */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
+
return 0;
}
@@ -46,7 +89,33 @@ static int flexanet_pcmcia_shutdown(void)
*/
static int flexanet_pcmcia_socket_state(struct pcmcia_state_array
*state_array){
- return -1;
+ unsigned long levels;
+
+ if (state_array->size < 2)
+ return -1;
+
+ /* Sense the GPIOs, asynchronously */
+ levels = GPLR;
+
+ /* Socket 0 */
+ state_array->state[0].detect = ((levels & GPIO_CF1_NCD)==0)?1:0;
+ state_array->state[0].ready = (levels & GPIO_CF1_IRQ)?1:0;
+ state_array->state[0].bvd1 = (levels & GPIO_CF1_BVD1)?1:0;
+ state_array->state[0].bvd2 = 1;
+ state_array->state[0].wrprot = 0;
+ state_array->state[0].vs_3v = 1;
+ state_array->state[0].vs_Xv = 0;
+
+ /* Socket 1 */
+ state_array->state[1].detect = ((levels & GPIO_CF2_NCD)==0)?1:0;
+ state_array->state[1].ready = (levels & GPIO_CF2_IRQ)?1:0;
+ state_array->state[1].bvd1 = (levels & GPIO_CF2_BVD1)?1:0;
+ state_array->state[1].bvd2 = 1;
+ state_array->state[1].wrprot = 0;
+ state_array->state[1].vs_3v = 1;
+ state_array->state[1].vs_Xv = 0;
+
+ return 1;
}
@@ -56,7 +125,16 @@ static int flexanet_pcmcia_socket_state(struct pcmcia_state_array
*/
static int flexanet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
- return -1;
+ /* check the socket index */
+ if (info->sock > 1)
+ return -1;
+
+ if (info->sock == 0)
+ info->irq = IRQ_GPIO_CF1_IRQ;
+ else if (info->sock == 1)
+ info->irq = IRQ_GPIO_CF2_IRQ;
+
+ return 0;
}
@@ -66,19 +144,105 @@ static int flexanet_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
static int flexanet_pcmcia_configure_socket(const struct pcmcia_configure
*configure)
{
- return -1;
+ unsigned long value, flags, mask;
+
+
+ if (configure->sock > 1)
+ return -1;
+
+ /* Ignore the VCC level since it is 3.3V and always on */
+ switch (configure->vcc)
+ {
+ case 0:
+ printk(KERN_WARNING "%s(): CS asked to power off.\n", __FUNCTION__);
+ break;
+
+ case 50:
+ printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
+ __FUNCTION__);
+
+ case 33:
+ break;
+
+ default:
+ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
+ configure->vcc);
+ return -1;
+ }
+
+ /* Reset the slot(s) using the controls in the BCR */
+ mask = 0;
+
+ switch (configure->sock)
+ {
+ case 0 : mask = FHH_BCR_CF1_RST; break;
+ case 1 : mask = FHH_BCR_CF2_RST; break;
+ }
+
+ local_irq_save(flags);
+
+ value = flexanet_BCR;
+ value = (configure->reset) ? (value | mask) : (value & ~mask);
+ FHH_BCR = flexanet_BCR = value;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static int flexanet_pcmcia_socket_init(int sock)
+{
+ if (sock == 0) {
+ set_irq_type(IRQ_GPIO_CF1_CD, IRQT_BOTHEDGE);
+ set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_BOTHEDGE);
+ } else if (sock == 1) {
+ set_irq_type(IRQ_GPIO_CF2_CD, IRQT_BOTHEDGE);
+ set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_BOTHEDGE);
+ }
+
+ return 0;
}
+static int flexanet_pcmcia_socket_suspend(int sock)
+{
+ if (sock == 0) {
+ set_irq_type(IRQ_GPIO_CF1_CD, IRQT_NOEDGE);
+ set_irq_type(IRQ_GPIO_CF1_BVD1, IRQT_NOEDGE);
+ } else if (sock == 1) {
+ set_irq_type(IRQ_GPIO_CF2_CD, IRQT_NOEDGE);
+ set_irq_type(IRQ_GPIO_CF2_BVD1, IRQT_NOEDGE);
+ }
+
+ return 0;
+}
/*
* The set of socket operations
*
*/
-struct pcmcia_low_level flexanet_pcmcia_ops = {
- flexanet_pcmcia_init,
- flexanet_pcmcia_shutdown,
- flexanet_pcmcia_socket_state,
- flexanet_pcmcia_get_irq_info,
- flexanet_pcmcia_configure_socket
+static struct pcmcia_low_level flexanet_pcmcia_ops = {
+ init: flexanet_pcmcia_init,
+ shutdown: flexanet_pcmcia_shutdown,
+ socket_state: flexanet_pcmcia_socket_state,
+ get_irq_info: flexanet_pcmcia_get_irq_info,
+ configure_socket: flexanet_pcmcia_configure_socket,
+
+ socket_init: flexanet_pcmcia_socket_init,
+ socket_suspend: flexanet_pcmcia_socket_suspend,
};
+int __init pcmcia_flexanet_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_flexanet())
+ ret = sa1100_register_pcmcia(&flexanet_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_flexanet_exit(void)
+{
+ sa1100_unregister_pcmcia(&flexanet_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_freebird.c b/drivers/pcmcia/sa1100_freebird.c
index f47bd57a5e7f..99cbb28a0e66 100644
--- a/drivers/pcmcia/sa1100_freebird.c
+++ b/drivers/pcmcia/sa1100_freebird.c
@@ -6,14 +6,22 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
-
+#include "sa1100_generic.h"
+
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { IRQ_GPIO_FREEBIRD_CF_CD, "CF_CD" },
+ { IRQ_GPIO_FREEBIRD_CF_BVD, "CF_BVD1" },
+};
static int freebird_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
+ int i, res;
/* Enable Linkup CF card */
LINKUP_PRC = 0xc0;
@@ -26,37 +34,38 @@ static int freebird_pcmcia_init(struct pcmcia_init *init){
mdelay(100);
LINKUP_PRC = 0xc0;
- /* All those are inputs */
- ////GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IRQ);
- GPDR &= ~(GPIO_FREEBIRD_CF_CD | GPIO_FREEBIRD_CF_IRQ | GPIO_FREEBIRD_CF_BVD);
-
/* Set transition detect */
- //set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1, GPIO_BOTH_EDGES );
- //set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
- set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_CD|GPIO_FREEBIRD_CF_BVD,GPIO_BOTH_EDGES);
- set_GPIO_IRQ_edge(GPIO_FREEBIRD_CF_IRQ, GPIO_FALLING_EDGE);
+ set_irq_type(IRQ_GPIO_FREEBIRD_CF_IRQ, IRQT_FALLING);
/* Register interrupts */
- irq = IRQ_GPIO_FREEBIRD_CF_CD;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_CD", NULL );
- if( res < 0 ) goto irq_err;
- irq = IRQ_GPIO_FREEBIRD_CF_BVD;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL );
- if( res < 0 ) goto irq_err;
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
/* There's only one slot, but it's "Slot 1": */
return 2;
irq_err:
- printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
- return -1;
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ return res;
}
static int freebird_pcmcia_shutdown(void)
{
+ int i;
+
/* disable IRQs */
- free_irq( IRQ_GPIO_FREEBIRD_CF_CD, NULL );
- free_irq( IRQ_GPIO_FREEBIRD_CF_BVD, NULL );
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
/* Disable CF card */
LINKUP_PRC = 0x40; /* SSP=1 SOE=0 */
@@ -75,7 +84,7 @@ static int freebird_pcmcia_socket_state(struct pcmcia_state_array
(state_array->size)*sizeof(struct pcmcia_state));
levels = LINKUP_PRS;
-//printk("LINKUP_PRS=%x \n",levels);
+//printk("LINKUP_PRS=%x\n",levels);
state_array->state[0].detect=
((levels & (LINKUP_CD1 | LINKUP_CD2))==0)?1:0;
@@ -114,7 +123,7 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock==1) return 0;
- save_flags_cli(flags);
+ local_irq_save(flags);
value = 0xc0; /* SSP=1 SOE=1 CFE=1 */
@@ -134,7 +143,7 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -145,16 +154,51 @@ static int freebird_pcmcia_configure_socket(const struct pcmcia_configure
LINKUP_PRC = value;
//printk("LINKUP_PRC=%x\n",value);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
-struct pcmcia_low_level freebird_pcmcia_ops = {
- freebird_pcmcia_init,
- freebird_pcmcia_shutdown,
- freebird_pcmcia_socket_state,
- freebird_pcmcia_get_irq_info,
- freebird_pcmcia_configure_socket
+static int freebird_pcmcia_socket_init(int sock)
+{
+ if (sock == 1) {
+ set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_BOTHEDGE);
+ set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_BOTHEDGE);
+ }
+ return 0;
+}
+
+static int freebird_pcmcia_socket_suspend(int sock)
+{
+ if (sock == 1) {
+ set_irq_type(IRQ_GPIO_FREEBIRD_CF_CD, IRQT_NOEDGE);
+ set_irq_type(IRQ_GPIO_FREEBIRD_CF_BVD, IRQT_NOEDGE);
+ }
+ return 0;
+}
+
+static struct pcmcia_low_level freebird_pcmcia_ops = {
+ init: freebird_pcmcia_init,
+ shutdown: freebird_pcmcia_shutdown,
+ socket_state: freebird_pcmcia_socket_state,
+ get_irq_info: freebird_pcmcia_get_irq_info,
+ configure_socket: freebird_pcmcia_configure_socket,
+
+ socket_init: freebird_pcmcia_socket_init,
+ socket_suspend: freebird_pcmcia_socket_suspend,
};
+int __init pcmcia_freebird_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_freebird())
+ ret = sa1100_register_pcmcia(&freebird_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_freebird_exit(void)
+{
+ sa1100_unregister_pcmcia(&freebird_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index 5b73df88e510..a70ac75a0047 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -29,6 +29,10 @@
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/init.h>
@@ -43,6 +47,7 @@
#include <linux/notifier.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
+#include <linux/cpufreq.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -62,338 +67,94 @@
static int pc_debug;
#endif
-MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
-MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-1100 Socket Controller");
-
/* This structure maintains housekeeping state for each socket, such
* as the last known values of the card detect pins, or the Card Services
* callback value associated with the socket:
*/
-static struct sa1100_pcmcia_socket
-sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK];
-
static int sa1100_pcmcia_socket_count;
+static struct sa1100_pcmcia_socket sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK];
+#define PCMCIA_SOCKET(x) (sa1100_pcmcia_socket + (x))
/* Returned by the low-level PCMCIA interface: */
static struct pcmcia_low_level *pcmcia_low_level;
-/* Event poll timer structure */
static struct timer_list poll_timer;
-
-
-/* Prototypes for routines which are used internally: */
-
-static int sa1100_pcmcia_driver_init(void);
-static void sa1100_pcmcia_driver_shutdown(void);
-static void sa1100_pcmcia_task_handler(void *data);
-static void sa1100_pcmcia_poll_event(unsigned long data);
-static void sa1100_pcmcia_interrupt(int irq, void *dev,
- struct pt_regs *regs);
static struct tq_struct sa1100_pcmcia_task;
-#ifdef CONFIG_PROC_FS
-static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
- int count, int *eof, void *data);
-#endif
-
-
-/* Prototypes for operations which are exported to the
- * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core:
+/*
+ * sa1100_pcmcia_state_to_config
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * Convert PCMCIA socket state to our socket configure structure.
*/
+static struct pcmcia_configure
+sa1100_pcmcia_state_to_config(unsigned int sock, socket_state_t *state)
+{
+ struct pcmcia_configure conf;
-static int sa1100_pcmcia_init(unsigned int sock);
-static int sa1100_pcmcia_suspend(unsigned int sock);
-static int sa1100_pcmcia_register_callback(unsigned int sock,
- void (*handler)(void *,
- unsigned int),
- void *info);
-static int sa1100_pcmcia_inquire_socket(unsigned int sock,
- socket_cap_t *cap);
-static int sa1100_pcmcia_get_status(unsigned int sock, u_int *value);
-static int sa1100_pcmcia_get_socket(unsigned int sock,
- socket_state_t *state);
-static int sa1100_pcmcia_set_socket(unsigned int sock,
- socket_state_t *state);
-static int sa1100_pcmcia_get_io_map(unsigned int sock,
- struct pccard_io_map *io);
-static int sa1100_pcmcia_set_io_map(unsigned int sock,
- struct pccard_io_map *io);
-static int sa1100_pcmcia_get_mem_map(unsigned int sock,
- struct pccard_mem_map *mem);
-static int sa1100_pcmcia_set_mem_map(unsigned int sock,
- struct pccard_mem_map *mem);
-#ifdef CONFIG_PROC_FS
-static void sa1100_pcmcia_proc_setup(unsigned int sock,
- struct proc_dir_entry *base);
-#endif
-
-static struct pccard_operations sa1100_pcmcia_operations = {
- sa1100_pcmcia_init,
- sa1100_pcmcia_suspend,
- sa1100_pcmcia_register_callback,
- sa1100_pcmcia_inquire_socket,
- sa1100_pcmcia_get_status,
- sa1100_pcmcia_get_socket,
- sa1100_pcmcia_set_socket,
- sa1100_pcmcia_get_io_map,
- sa1100_pcmcia_set_io_map,
- sa1100_pcmcia_get_mem_map,
- sa1100_pcmcia_set_mem_map,
-#ifdef CONFIG_PROC_FS
- sa1100_pcmcia_proc_setup
-#endif
-};
-
-#ifdef CONFIG_CPU_FREQ
-/* forward declaration */
-static struct notifier_block sa1100_pcmcia_notifier_block;
-#endif
+ conf.sock = sock;
+ conf.vcc = state->Vcc;
+ conf.vpp = state->Vpp;
+ conf.output = state->flags & SS_OUTPUT_ENA ? 1 : 0;
+ conf.speaker = state->flags & SS_SPKR_ENA ? 1 : 0;
+ conf.reset = state->flags & SS_RESET ? 1 : 0;
+ conf.irq = state->io_irq != 0;
+ return conf;
+}
-/* sa1100_pcmcia_driver_init()
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- *
- * This routine performs a basic sanity check to ensure that this
- * kernel has been built with the appropriate board-specific low-level
- * PCMCIA support, performs low-level PCMCIA initialization, registers
- * this socket driver with Card Services, and then spawns the daemon
- * thread which is the real workhorse of the socket driver.
+/* sa1100_pcmcia_sock_init()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
*
- * Please see linux/Documentation/arm/SA1100/PCMCIA for more information
- * on the low-level kernel interface.
+ * (Re-)Initialise the socket, turning on status interrupts
+ * and PCMCIA bus. This must wait for power to stabilise
+ * so that the card status signals report correctly.
*
- * Returns: 0 on success, -1 on error
- */
-static int __init sa1100_pcmcia_driver_init(void){
- servinfo_t info;
- struct pcmcia_init pcmcia_init;
- struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
- struct pcmcia_state_array state_array;
- unsigned int i, clock;
- unsigned long mecr;
-
- printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE);
-
- CardServices(GetCardServicesInfo, &info);
-
- if(info.Revision!=CS_RELEASE_CODE){
- printk(KERN_ERR "Card Services release codes do not match\n");
- return -1;
- }
-
- if(machine_is_assabet()){
-#ifdef CONFIG_SA1100_ASSABET
- if(machine_has_neponset()){
-#ifdef CONFIG_ASSABET_NEPONSET
- pcmcia_low_level=&neponset_pcmcia_ops;
-#else
- printk(KERN_ERR "Card Services disabled: missing Neponset support\n");
- return -1;
-#endif
- }else{
- pcmcia_low_level=&assabet_pcmcia_ops;
- }
-#endif
- } else if (machine_is_freebird()) {
-#ifdef CONFIG_SA1100_FREEBIRD
- pcmcia_low_level = &freebird_pcmcia_ops;
-#endif
- } else if (machine_is_h3600()) {
-#ifdef CONFIG_SA1100_H3600
- pcmcia_low_level = &h3600_pcmcia_ops;
-#endif
- } else if (machine_is_cerf()) {
-#ifdef CONFIG_SA1100_CERF
- pcmcia_low_level = &cerf_pcmcia_ops;
-#endif
- } else if (machine_is_graphicsclient()) {
-#ifdef CONFIG_SA1100_GRAPHICSCLIENT
- pcmcia_low_level = &gcplus_pcmcia_ops;
-#endif
- } else if (machine_is_xp860()) {
-#ifdef CONFIG_SA1100_XP860
- pcmcia_low_level = &xp860_pcmcia_ops;
-#endif
- } else if (machine_is_yopy()) {
-#ifdef CONFIG_SA1100_YOPY
- pcmcia_low_level = &yopy_pcmcia_ops;
-#endif
- } else if (machine_is_pangolin()) {
-#ifdef CONFIG_SA1100_PANGOLIN
- pcmcia_low_level = &pangolin_pcmcia_ops;
-#endif
- } else if (machine_is_jornada720()) {
-#ifdef CONFIG_SA1100_JORNADA720
- pcmcia_low_level = &jornada720_pcmcia_ops;
-#endif
- } else if(machine_is_pfs168()){
-#ifdef CONFIG_SA1100_PFS168
- pcmcia_low_level=&pfs168_pcmcia_ops;
-#endif
- } else if(machine_is_flexanet()){
-#ifdef CONFIG_SA1100_FLEXANET
- pcmcia_low_level=&flexanet_pcmcia_ops;
-#endif
- } else if(machine_is_simpad()){
-#ifdef CONFIG_SA1100_SIMPAD
- pcmcia_low_level=&simpad_pcmcia_ops;
-#endif
- } else if(machine_is_graphicsmaster()) {
-#ifdef CONFIG_SA1100_GRAPHICSMASTER
- pcmcia_low_level=&graphicsmaster_pcmcia_ops;
-#endif
- } else if(machine_is_adsbitsy()) {
-#ifdef CONFIG_SA1100_ADSBITSY
- pcmcia_low_level=&adsbitsy_pcmcia_ops;
-#endif
- } else if(machine_is_stork()) {
-#ifdef CONFIG_SA1100_STORK
- pcmcia_low_level=&stork_pcmcia_ops;
-#endif
- }
-
- if (!pcmcia_low_level) {
- printk(KERN_ERR "This hardware is not supported by the SA1100 Card Service driver\n");
- return -ENODEV;
- }
-
- pcmcia_init.handler=sa1100_pcmcia_interrupt;
-
- if((sa1100_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){
- printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n");
- return -EIO;
- }
-
- state_array.size=sa1100_pcmcia_socket_count;
- state_array.state=state;
-
- if(pcmcia_low_level->socket_state(&state_array)<0){
- printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
- return -EIO;
- }
-
- /* We initialize the MECR to default values here, because we are
- * not guaranteed to see a SetIOMap operation at runtime.
- */
- mecr=0;
-
- clock = get_cclk_frequency() * 100;
-
- for(i=0; i<sa1100_pcmcia_socket_count; ++i){
- sa1100_pcmcia_socket[i].k_state=state[i];
-
- /* This is an interim fix. Apparently, SetSocket is no longer
- * called to initialize each socket (prior to the first detect
- * event). For now, we'll just manually set up the mask.
- */
- sa1100_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT;
-
- sa1100_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE;
- sa1100_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i);
- sa1100_pcmcia_socket[i].phys_mem=_PCMCIAMem(i);
-
- MECR_FAST_SET(mecr, i, 0);
- MECR_BSIO_SET(mecr, i,
- sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_IO_ACCESS, clock));
- MECR_BSA_SET(mecr, i,
- sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock));
- MECR_BSM_SET(mecr, i,
- sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock));
-
- sa1100_pcmcia_socket[i].speed_io=SA1100_PCMCIA_IO_ACCESS;
- sa1100_pcmcia_socket[i].speed_attr=SA1100_PCMCIA_5V_MEM_ACCESS;
- sa1100_pcmcia_socket[i].speed_mem=SA1100_PCMCIA_5V_MEM_ACCESS;
- }
-
- MECR=mecr;
-
-#ifdef CONFIG_CPU_FREQ
- if(cpufreq_register_notifier(&sa1100_pcmcia_notifier_block) < 0){
- printk(KERN_ERR "Unable to register CPU frequency change notifier\n");
- return -ENXIO;
- }
-#endif
-
- /* Only advertise as many sockets as we can detect: */
- if(register_ss_entry(sa1100_pcmcia_socket_count,
- &sa1100_pcmcia_operations)<0){
- printk(KERN_ERR "Unable to register socket service routine\n");
- return -ENXIO;
- }
-
- /* Start the event poll timer. It will reschedule by itself afterwards. */
- sa1100_pcmcia_poll_event(0);
-
- DEBUG(1, "sa1100: initialization complete\n");
-
- return 0;
-
-} /* sa1100_pcmcia_driver_init() */
-
-module_init(sa1100_pcmcia_driver_init);
-
-
-/* sa1100_pcmcia_driver_shutdown()
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Invokes the low-level kernel service to free IRQs associated with this
- * socket controller and reset GPIO edge detection.
+ * Returns: 0
*/
-static void __exit sa1100_pcmcia_driver_shutdown(void){
+static int sa1100_pcmcia_sock_init(unsigned int sock)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct pcmcia_configure conf;
- del_timer_sync(&poll_timer);
- unregister_ss_entry(&sa1100_pcmcia_operations);
-#ifdef CONFIG_CPU_FREQ
- cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block);
-#endif
- pcmcia_low_level->shutdown();
- flush_scheduled_tasks();
+ DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
- DEBUG(1, "sa1100: shutdown complete\n");
-}
+ skt->cs_state = dead_socket;
-module_exit(sa1100_pcmcia_driver_shutdown);
+ conf = sa1100_pcmcia_state_to_config(sock, &dead_socket);
+ pcmcia_low_level->configure_socket(&conf);
-/* sa1100_pcmcia_init()
- * ^^^^^^^^^^^^^^^^^^^^
- * We perform all of the interesting initialization tasks in
- * sa1100_pcmcia_driver_init().
- *
- * Returns: 0
- */
-static int sa1100_pcmcia_init(unsigned int sock){
-
- DEBUG(2, "%s(): initializing socket %u\n", __FUNCTION__, sock);
-
- return 0;
+ return pcmcia_low_level->socket_init(sock);
}
-/* sa1100_pcmcia_suspend()
+/*
+ * sa1100_pcmcia_suspend()
* ^^^^^^^^^^^^^^^^^^^^^^^
- * We don't currently perform any actions on a 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(unsigned int sock)
{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
struct pcmcia_configure conf;
int ret;
DEBUG(2, "%s(): suspending socket %u\n", __FUNCTION__, sock);
- conf.sock = sock;
- conf.vcc = 0;
- conf.vpp = 0;
- conf.output = 0;
- conf.speaker = 0;
- conf.reset = 1;
+ conf = sa1100_pcmcia_state_to_config(sock, &dead_socket);
ret = pcmcia_low_level->configure_socket(&conf);
- if (ret == 0)
- sa1100_pcmcia_socket[sock].cs_state = dead_socket;
+ if (ret == 0) {
+ skt->cs_state = dead_socket;
+ ret = pcmcia_low_level->socket_suspend(sock);
+ }
return ret;
}
@@ -407,52 +168,50 @@ static int sa1100_pcmcia_suspend(unsigned int sock)
*
* Returns: an event mask for the given socket state.
*/
-static inline unsigned sa1100_pcmcia_events(struct pcmcia_state *state,
- struct pcmcia_state *prev_state,
- unsigned int mask,
- unsigned int flags){
- unsigned int events=0;
-
- if(state->detect!=prev_state->detect){
+static inline unsigned int
+sa1100_pcmcia_events(struct pcmcia_state *state,
+ struct pcmcia_state *prev_state,
+ unsigned int mask, unsigned int flags)
+{
+ unsigned int events = 0;
- DEBUG(2, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
+ if (state->detect != prev_state->detect) {
+ DEBUG(3, "%s(): card detect value %u\n", __FUNCTION__, state->detect);
- events|=mask&SS_DETECT;
+ events |= SS_DETECT;
}
- if(state->ready!=prev_state->ready){
-
- DEBUG(2, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
+ if (state->ready != prev_state->ready) {
+ DEBUG(3, "%s(): card ready value %u\n", __FUNCTION__, state->ready);
- events|=mask&((flags&SS_IOCARD)?0:SS_READY);
+ events |= flags & SS_IOCARD ? 0 : SS_READY;
}
- if(state->bvd1!=prev_state->bvd1){
-
- DEBUG(2, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
+ if (state->bvd1 != prev_state->bvd1) {
+ DEBUG(3, "%s(): card BVD1 value %u\n", __FUNCTION__, state->bvd1);
- events|=mask&(flags&SS_IOCARD)?SS_STSCHG:SS_BATDEAD;
+ events |= flags & SS_IOCARD ? SS_STSCHG : SS_BATDEAD;
}
- if(state->bvd2!=prev_state->bvd2){
+ if (state->bvd2 != prev_state->bvd2) {
+ DEBUG(3, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
- DEBUG(2, "%s(): card BVD2 value %u\n", __FUNCTION__, state->bvd2);
-
- events|=mask&(flags&SS_IOCARD)?0:SS_BATWARN;
+ events |= flags & SS_IOCARD ? 0 : SS_BATWARN;
}
- DEBUG(2, "events: %s%s%s%s%s%s\n",
- (events==0)?"<NONE>":"",
- (events&SS_DETECT)?"DETECT ":"",
- (events&SS_READY)?"READY ":"",
- (events&SS_BATDEAD)?"BATDEAD ":"",
- (events&SS_BATWARN)?"BATWARN ":"",
- (events&SS_STSCHG)?"STSCHG ":"");
+ *prev_state = *state;
- *prev_state=*state;
+ events &= mask;
- return events;
+ DEBUG(2, "events: %s%s%s%s%s%s\n",
+ events == 0 ? "<NONE>" : "",
+ events & SS_DETECT ? "DETECT " : "",
+ events & SS_READY ? "READY " : "",
+ events & SS_BATDEAD ? "BATDEAD " : "",
+ events & SS_BATWARN ? "BATWARN " : "",
+ events & SS_STSCHG ? "STSCHG " : "");
+ return events;
} /* sa1100_pcmcia_events() */
@@ -464,38 +223,43 @@ static inline unsigned sa1100_pcmcia_events(struct pcmcia_state *state,
* callback) occurs in this thread rather than in the actual interrupt
* handler due to the use of scheduling operations in the PCMCIA core.
*/
-static void sa1100_pcmcia_task_handler(void *data) {
+static void sa1100_pcmcia_task_handler(void *data)
+{
struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
struct pcmcia_state_array state_array;
- int i, events, all_events, irq_status;
+ unsigned int all_events;
- DEBUG(2, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
+ DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__);
- state_array.size=sa1100_pcmcia_socket_count;
- state_array.state=state;
+ state_array.size = sa1100_pcmcia_socket_count;
+ state_array.state = state;
do {
+ unsigned int events;
+ int ret, i;
- DEBUG(3, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
+ memset(state, 0, sizeof(state));
- if((irq_status=pcmcia_low_level->socket_state(&state_array))<0)
- printk(KERN_ERR "Error in kernel low-level PCMCIA service.\n");
+ DEBUG(4, "%s(): interrogating low-level PCMCIA service\n", __FUNCTION__);
- all_events=0;
+ ret = pcmcia_low_level->socket_state(&state_array);
+ if (ret < 0) {
+ printk(KERN_ERR "sa1100_pcmcia: unable to read socket status\n");
+ break;
+ }
- if(irq_status>0){
+ all_events = 0;
- for(i=0; i<state_array.size; ++i, all_events|=events)
- if((events=
- sa1100_pcmcia_events(&state[i],
- &sa1100_pcmcia_socket[i].k_state,
- sa1100_pcmcia_socket[i].cs_state.csc_mask,
- sa1100_pcmcia_socket[i].cs_state.flags)))
- if(sa1100_pcmcia_socket[i].handler!=NULL)
- sa1100_pcmcia_socket[i].handler(sa1100_pcmcia_socket[i].handler_info,
- events);
- }
+ for (i = 0; i < state_array.size; i++, all_events |= events) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
+
+ events = sa1100_pcmcia_events(&state[i], &skt->k_state,
+ skt->cs_state.csc_mask,
+ skt->cs_state.flags);
+ if (events && sa1100_pcmcia_socket[i].handler != NULL)
+ skt->handler(skt->handler_info, events);
+ }
} while(all_events);
} /* sa1100_pcmcia_task_handler() */
@@ -510,7 +274,7 @@ static struct tq_struct sa1100_pcmcia_task = {
*/
static void sa1100_pcmcia_poll_event(unsigned long dummy)
{
- DEBUG(3, "%s(): polling for events\n", __FUNCTION__);
+ DEBUG(4, "%s(): polling for events\n", __FUNCTION__);
poll_timer.function = sa1100_pcmcia_poll_event;
poll_timer.expires = jiffies + SA1100_PCMCIA_POLL_PERIOD;
add_timer(&poll_timer);
@@ -527,7 +291,8 @@ static void sa1100_pcmcia_poll_event(unsigned long dummy)
* handling code performs scheduling operations which cannot be
* executed from within an interrupt context.
*/
-static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
+static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq);
schedule_task(&sa1100_pcmcia_task);
}
@@ -546,17 +311,20 @@ static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs){
*
* Returns: 0
*/
-static int sa1100_pcmcia_register_callback(unsigned int sock,
- void (*handler)(void *,
- unsigned int),
- void *info){
- if(handler==NULL){
- sa1100_pcmcia_socket[sock].handler=NULL;
+static int
+sa1100_pcmcia_register_callback(unsigned int sock,
+ void (*handler)(void *, unsigned int),
+ void *info)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+
+ if (handler == NULL) {
+ skt->handler = NULL;
MOD_DEC_USE_COUNT;
} else {
MOD_INC_USE_COUNT;
- sa1100_pcmcia_socket[sock].handler=handler;
- sa1100_pcmcia_socket[sock].handler_info=info;
+ skt->handler_info = info;
+ skt->handler = handler;
}
return 0;
@@ -580,51 +348,41 @@ static int sa1100_pcmcia_register_callback(unsigned int sock,
* an offset which is applied to client-requested base I/O addresses
* in alloc_io_space().
*
- * Returns: 0 on success, -1 if no pin has been configured for `sock'
+ * SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
+ * force_low argument to validate_mem() in rsrc_mgr.c -- since in
+ * general, the mapped * addresses of the PCMCIA memory regions
+ * will not be within 0xffff, setting force_low would be
+ * undesirable.
+ *
+ * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
+ * resource database; we instead pass up physical address ranges
+ * and allow other parts of Card Services to deal with remapping.
+ *
+ * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
+ * not 32-bit CardBus devices.
+ *
+ * Return value is irrelevant; the pcmcia subsystem ignores it.
*/
-static int sa1100_pcmcia_inquire_socket(unsigned int sock,
- socket_cap_t *cap){
- struct pcmcia_irq_info irq_info;
-
- DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
-
- if(sock>=sa1100_pcmcia_socket_count){
- printk(KERN_ERR "sa1100: socket %u not configured\n", sock);
- return -1;
- }
+static int
+sa1100_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ int ret = -1;
- /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the
- * force_low argument to validate_mem() in rsrc_mgr.c -- since in
- * general, the mapped * addresses of the PCMCIA memory regions
- * will not be within 0xffff, setting force_low would be
- * undesirable.
- *
- * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory
- * resource database; we instead pass up physical address ranges
- * and allow other parts of Card Services to deal with remapping.
- *
- * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but
- * not 32-bit CardBus devices.
- */
- cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- irq_info.sock=sock;
- irq_info.irq=-1;
+ if (sock < sa1100_pcmcia_socket_count) {
+ cap->features = SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
+ cap->irq_mask = 0;
+ cap->map_size = PAGE_SIZE;
+ cap->pci_irq = skt->irq;
+ cap->io_offset = (unsigned long)skt->virt_io;
- if(pcmcia_low_level->get_irq_info(&irq_info)<0){
- printk(KERN_ERR "Error obtaining IRQ info from kernel for socket %u\n",
- sock);
- return -1;
+ ret = 0;
}
- cap->irq_mask=0;
- cap->map_size=PAGE_SIZE;
- cap->pci_irq=irq_info.irq;
- cap->io_offset=sa1100_pcmcia_socket[sock].virt_io;
-
- return 0;
-
-} /* sa1100_pcmcia_inquire_socket() */
+ return ret;
+}
/* sa1100_pcmcia_get_status()
@@ -643,58 +401,61 @@ static int sa1100_pcmcia_inquire_socket(unsigned int sock,
*
* Returns: 0
*/
-static int sa1100_pcmcia_get_status(unsigned int sock,
- unsigned int *status){
+static int
+sa1100_pcmcia_get_status(unsigned int sock, unsigned int *status)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
struct pcmcia_state_array state_array;
+ unsigned int stat;
+
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+ state_array.size = sa1100_pcmcia_socket_count;
+ state_array.state = state;
- state_array.size=sa1100_pcmcia_socket_count;
- state_array.state=state;
+ memset(state, 0, sizeof(state));
- if((pcmcia_low_level->socket_state(&state_array))<0){
- printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n");
+ if ((pcmcia_low_level->socket_state(&state_array)) < 0) {
+ printk(KERN_ERR "sa1100_pcmcia: unable to get socket status\n");
return -1;
}
- sa1100_pcmcia_socket[sock].k_state=state[sock];
+ skt->k_state = state[sock];
- *status=state[sock].detect?SS_DETECT:0;
-
- *status|=state[sock].ready?SS_READY:0;
+ stat = state[sock].detect ? SS_DETECT : 0;
+ stat |= state[sock].ready ? SS_READY : 0;
+ stat |= state[sock].vs_3v ? SS_3VCARD : 0;
+ stat |= state[sock].vs_Xv ? SS_XVCARD : 0;
/* The power status of individual sockets is not available
* explicitly from the hardware, so we just remember the state
* and regurgitate it upon request:
*/
- *status|=sa1100_pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0;
+ stat |= skt->cs_state.Vcc ? SS_POWERON : 0;
- if(sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)
- *status|=state[sock].bvd1?SS_STSCHG:0;
+ if (skt->cs_state.flags & SS_IOCARD)
+ stat |= state[sock].bvd1 ? SS_STSCHG : 0;
else {
- if(state[sock].bvd1==0)
- *status|=SS_BATDEAD;
- else if(state[sock].bvd2==0)
- *status|=SS_BATWARN;
+ if (state[sock].bvd1 == 0)
+ stat |= SS_BATDEAD;
+ else if (state[sock].bvd2 == 0)
+ stat |= SS_BATWARN;
}
- *status|=state[sock].vs_3v?SS_3VCARD:0;
-
- *status|=state[sock].vs_Xv?SS_XVCARD:0;
-
DEBUG(3, "\tstatus: %s%s%s%s%s%s%s%s\n",
- (*status&SS_DETECT)?"DETECT ":"",
- (*status&SS_READY)?"READY ":"",
- (*status&SS_BATDEAD)?"BATDEAD ":"",
- (*status&SS_BATWARN)?"BATWARN ":"",
- (*status&SS_POWERON)?"POWERON ":"",
- (*status&SS_STSCHG)?"STSCHG ":"",
- (*status&SS_3VCARD)?"3VCARD ":"",
- (*status&SS_XVCARD)?"XVCARD ":"");
+ stat & SS_DETECT ? "DETECT " : "",
+ stat & SS_READY ? "READY " : "",
+ stat & SS_BATDEAD ? "BATDEAD " : "",
+ stat & SS_BATWARN ? "BATWARN " : "",
+ stat & SS_POWERON ? "POWERON " : "",
+ stat & SS_STSCHG ? "STSCHG " : "",
+ stat & SS_3VCARD ? "3VCARD " : "",
+ stat & SS_XVCARD ? "XVCARD " : "");
- return 0;
+ *status = stat;
+ return 0;
} /* sa1100_pcmcia_get_status() */
@@ -706,20 +467,18 @@ static int sa1100_pcmcia_get_status(unsigned int sock,
*
* Returns: 0
*/
-static int sa1100_pcmcia_get_socket(unsigned int sock,
- socket_state_t *state){
+static int
+sa1100_pcmcia_get_socket(unsigned int sock, socket_state_t *state)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
- DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- /* This information was given to us in an earlier call to set_socket(),
- * so we're just regurgitating it here:
- */
- *state=sa1100_pcmcia_socket[sock].cs_state;
+ *state = skt->cs_state;
return 0;
}
-
/* sa1100_pcmcia_set_socket()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^
* Implements the set_socket() operation for the in-kernel PCMCIA
@@ -730,14 +489,15 @@ static int sa1100_pcmcia_get_socket(unsigned int sock,
*
* Returns: 0
*/
-static int sa1100_pcmcia_set_socket(unsigned int sock,
- socket_state_t *state){
- struct pcmcia_configure configure;
+static int
+sa1100_pcmcia_set_socket(unsigned int sock, socket_state_t *state)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ struct pcmcia_configure conf;
- DEBUG(3, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n"
- "\tVcc %d Vpp %d irq %d\n",
+ DEBUG(3, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n",
(state->csc_mask==0)?"<NONE>":"",
(state->csc_mask&SS_DETECT)?"DETECT ":"",
(state->csc_mask&SS_READY)?"READY ":"",
@@ -749,25 +509,20 @@ static int sa1100_pcmcia_set_socket(unsigned int sock,
(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->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"");
+ DEBUG(3, "\tVcc %d Vpp %d irq %d\n",
state->Vcc, state->Vpp, state->io_irq);
- configure.sock=sock;
- configure.vcc=state->Vcc;
- configure.vpp=state->Vpp;
- configure.output=(state->flags&SS_OUTPUT_ENA)?1:0;
- configure.speaker=(state->flags&SS_SPKR_ENA)?1:0;
- configure.reset=(state->flags&SS_RESET)?1:0;
+ conf = sa1100_pcmcia_state_to_config(sock, state);
- if(pcmcia_low_level->configure_socket(&configure)<0){
- printk(KERN_ERR "Unable to configure socket %u\n", sock);
+ if (pcmcia_low_level->configure_socket(&conf) < 0) {
+ printk(KERN_ERR "sa1100_pcmcia: unable to configure socket %d\n", sock);
return -1;
}
- sa1100_pcmcia_socket[sock].cs_state=*state;
+ skt->cs_state = *state;
return 0;
-
} /* sa1100_pcmcia_set_socket() */
@@ -779,20 +534,20 @@ static int sa1100_pcmcia_set_socket(unsigned int sock,
*
* Returns: 0 on success, -1 if the map index was out of range
*/
-static int sa1100_pcmcia_get_io_map(unsigned int sock,
- struct pccard_io_map *map){
+static int
+sa1100_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ int ret = -1;
- DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- if(map->map>=MAX_IO_WIN){
- printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
- map->map);
- return -1;
+ if (map->map < MAX_IO_WIN) {
+ *map = skt->io_map[map->map];
+ ret = 0;
}
- *map=sa1100_pcmcia_socket[sock].io_map[map->map];
-
- return 0;
+ return ret;
}
@@ -805,16 +560,16 @@ static int sa1100_pcmcia_get_io_map(unsigned int sock,
*
* Returns: 0 on success, -1 on error
*/
-static int sa1100_pcmcia_set_io_map(unsigned int sock,
- struct pccard_io_map *map){
- unsigned int clock, speed;
- unsigned long mecr, start;
+static int
+sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
- DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- DEBUG(4, "\tmap %u speed %u\n\tstart 0x%08lx stop 0x%08lx\n"
- "\tflags: %s%s%s%s%s%s%s%s\n",
- map->map, map->speed, map->start, map->stop,
+ DEBUG(3, "\tmap %u speed %u\n\tstart 0x%08x stop 0x%08x\n",
+ map->map, map->speed, map->start, map->stop);
+ DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
(map->flags==0)?"<NONE>":"",
(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
(map->flags&MAP_16BIT)?"16BIT ":"",
@@ -824,45 +579,45 @@ static int sa1100_pcmcia_set_io_map(unsigned int sock,
(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
(map->flags&MAP_PREFETCH)?"PREFETCH ":"");
- if(map->map>=MAX_IO_WIN){
+ if (map->map >= MAX_IO_WIN) {
printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
map->map);
return -1;
}
- if(map->flags&MAP_ACTIVE){
+ if (map->flags & MAP_ACTIVE) {
+ unsigned int clock, speed = map->speed;
+ unsigned long mecr;
- speed=(map->speed>0)?map->speed:SA1100_PCMCIA_IO_ACCESS;
+ if (speed == 0)
+ speed = SA1100_PCMCIA_IO_ACCESS;
- clock = get_cclk_frequency() * 100;
+ clock = cpufreq_get(0);
- mecr=MECR;
+ mecr = MECR;
MECR_BSIO_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
- sa1100_pcmcia_socket[sock].speed_io=speed;
+ skt->speed_io = speed;
DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
__FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
sock, MECR_BSIO_GET(mecr, sock));
- MECR=mecr;
-
+ MECR = mecr;
}
- start=map->start;
-
- if(map->stop==1)
- map->stop=PAGE_SIZE-1;
+ if (map->stop == 1)
+ map->stop = PAGE_SIZE-1;
- map->start=sa1100_pcmcia_socket[sock].virt_io;
- map->stop=map->start+(map->stop-start);
+ map->stop -= map->start;
+ map->stop += (unsigned long)skt->virt_io;
+ map->start = (unsigned long)skt->virt_io;
- sa1100_pcmcia_socket[sock].io_map[map->map]=*map;
+ skt->io_map[map->map] = *map;
return 0;
-
} /* sa1100_pcmcia_set_io_map() */
@@ -875,20 +630,20 @@ static int sa1100_pcmcia_set_io_map(unsigned int sock,
*
* Returns: 0 on success, -1 if the map index was out of range
*/
-static int sa1100_pcmcia_get_mem_map(unsigned int sock,
- struct pccard_mem_map *map){
+static int
+sa1100_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ int ret = -1;
- DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- if(map->map>=MAX_WIN){
- printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
- map->map);
- return -1;
+ if (map->map < MAX_WIN) {
+ *map = skt->mem_map[map->map];
+ ret = 0;
}
- *map=sa1100_pcmcia_socket[sock].mem_map[map->map];
-
- return 0;
+ return ret;
}
@@ -901,18 +656,18 @@ static int sa1100_pcmcia_get_mem_map(unsigned int sock,
*
* Returns: 0 on success, -1 on error
*/
-static int sa1100_pcmcia_set_mem_map(unsigned int sock,
- struct pccard_mem_map *map){
- unsigned int clock, speed;
- unsigned long mecr, start;
+static int
+sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
+{
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
+ unsigned long start;
- DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+ DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);
- DEBUG(4, "\tmap %u speed %u\n\tsys_start %#lx\n"
- "\tsys_stop %#lx\n\tcard_start %#x\n"
- "\tflags: %s%s%s%s%s%s%s%s\n",
- map->map, map->speed, map->sys_start, map->sys_stop,
- map->card_start, (map->flags==0)?"<NONE>":"",
+ DEBUG(3, "\tmap %u speed %u sys_start %08lx sys_stop %08lx card_start %08x\n",
+ map->map, map->speed, map->sys_start, map->sys_stop, map->card_start);
+ DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
+ (map->flags==0)?"<NONE>":"",
(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
(map->flags&MAP_16BIT)?"16BIT ":"",
(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
@@ -921,177 +676,175 @@ static int sa1100_pcmcia_set_mem_map(unsigned int sock,
(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
- if(map->map>=MAX_WIN){
+ if (map->map >= MAX_WIN){
printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
map->map);
return -1;
}
- if(map->flags&MAP_ACTIVE){
+ if (map->flags & MAP_ACTIVE) {
+ unsigned int clock, speed = map->speed;
+ unsigned long mecr;
- /* When clients issue RequestMap, the access speed is not always
- * properly configured:
+ /*
+ * When clients issue RequestMap, the access speed is not always
+ * properly configured. Choose some sensible defaults.
*/
- if(map->speed > 0)
- speed = map->speed;
- else
- switch(sa1100_pcmcia_socket[sock].cs_state.Vcc){
- case 33:
+ if (speed == 0) {
+ if (skt->cs_state.Vcc == 33)
speed = SA1100_PCMCIA_3V_MEM_ACCESS;
- break;
- default:
+ else
speed = SA1100_PCMCIA_5V_MEM_ACCESS;
- }
+ }
- clock = get_cclk_frequency() * 100;
-
- mecr=MECR;
-
- if(map->flags&MAP_ATTRIB){
+ clock = cpufreq_get(0);
- MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
- sa1100_pcmcia_socket[sock].speed_attr=speed;
+ /* Fixme: MECR is not pre-empt safe. */
+ mecr = MECR;
+ if (map->flags & MAP_ATTRIB) {
+ MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
+ skt->speed_attr = speed;
} else {
-
MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
- sa1100_pcmcia_socket[sock].speed_mem=speed;
-
+ skt->speed_mem = speed;
}
-
+
DEBUG(4, "%s(): FAST%u %lx BSM%u %lx BSA%u %lx BSIO%u %lx\n",
__FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock),
sock, MECR_BSIO_GET(mecr, sock));
-
- MECR=mecr;
+ MECR = mecr;
}
- start=map->sys_start;
-
- if(map->sys_stop==0)
- map->sys_stop=PAGE_SIZE-1;
+ start = (map->flags & MAP_ATTRIB) ? skt->phys_attr : skt->phys_mem;
- map->sys_start=(map->flags & MAP_ATTRIB)?\
- sa1100_pcmcia_socket[sock].phys_attr:\
- sa1100_pcmcia_socket[sock].phys_mem;
+ if (map->sys_stop == 0)
+ map->sys_stop = PAGE_SIZE-1;
- map->sys_stop=map->sys_start+(map->sys_stop-start);
+ map->sys_stop -= map->sys_start;
+ map->sys_stop += start;
+ map->sys_start = start;
- sa1100_pcmcia_socket[sock].mem_map[map->map]=*map;
+ skt->mem_map[map->map] = *map;
return 0;
-
} /* sa1100_pcmcia_set_mem_map() */
#if defined(CONFIG_PROC_FS)
-/* sa1100_pcmcia_proc_setup()
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^
- * Implements the proc_setup() operation for the in-kernel PCMCIA
- * service (formerly SS_ProcSetup in Card Services).
- *
- * Returns: 0 on success, -1 on error
- */
-static void sa1100_pcmcia_proc_setup(unsigned int sock,
- struct proc_dir_entry *base){
- struct proc_dir_entry *entry;
-
- DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
-
- if((entry=create_proc_entry("status", 0, base))==NULL){
- printk(KERN_ERR "Unable to install \"status\" procfs entry\n");
- return;
- }
-
- entry->read_proc=sa1100_pcmcia_proc_status;
- entry->data=(void *)sock;
-}
-
-
/* sa1100_pcmcia_proc_status()
* ^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Implements the /proc/bus/pccard/??/status file.
*
* Returns: the number of characters added to the buffer
*/
-static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
- int count, int *eof, void *data){
- char *p=buf;
- unsigned int sock=(unsigned int)data;
- unsigned int clock = get_cclk_frequency() * 100;
+static int
+sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
+ int count, int *eof, void *data)
+{
+ unsigned int sock = (unsigned int)data;
+ unsigned int clock = cpufreq_get(0);
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
unsigned long mecr = MECR;
+ char *p = buf;
- p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n",
- sa1100_pcmcia_socket[sock].k_state.detect?"detect ":"",
- sa1100_pcmcia_socket[sock].k_state.ready?"ready ":"",
- sa1100_pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"",
- sa1100_pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"",
- sa1100_pcmcia_socket[sock].k_state.wrprot?"wrprot ":"",
- sa1100_pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"",
- sa1100_pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":"");
+ p+=sprintf(p, "k_state : %s%s%s%s%s%s%s\n",
+ skt->k_state.detect ? "detect " : "",
+ skt->k_state.ready ? "ready " : "",
+ skt->k_state.bvd1 ? "bvd1 " : "",
+ skt->k_state.bvd2 ? "bvd2 " : "",
+ skt->k_state.wrprot ? "wrprot " : "",
+ skt->k_state.vs_3v ? "vs_3v " : "",
+ skt->k_state.vs_Xv ? "vs_Xv " : "");
p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n",
- sa1100_pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"",
- sa1100_pcmcia_socket[sock].k_state.ready?"SS_READY ":"",
- sa1100_pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
- "SS_IOCARD ":"",
- (sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD &&
- sa1100_pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"",
- ((sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
- (sa1100_pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"",
- ((sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 &&
- (sa1100_pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"",
- sa1100_pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"",
- sa1100_pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":"");
+ skt->k_state.detect ? "SS_DETECT " : "",
+ skt->k_state.ready ? "SS_READY " : "",
+ skt->cs_state.Vcc ? "SS_POWERON " : "",
+ skt->cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "",
+ (skt->cs_state.flags & SS_IOCARD &&
+ skt->k_state.bvd1) ? "SS_STSCHG " : "",
+ ((skt->cs_state.flags & SS_IOCARD)==0 &&
+ (skt->k_state.bvd1==0)) ? "SS_BATDEAD " : "",
+ ((skt->cs_state.flags & SS_IOCARD)==0 &&
+ (skt->k_state.bvd2==0)) ? "SS_BATWARN " : "",
+ skt->k_state.vs_3v ? "SS_3VCARD " : "",
+ skt->k_state.vs_Xv ? "SS_XVCARD " : "");
p+=sprintf(p, "mask : %s%s%s%s%s\n",
- sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\
- "SS_DETECT ":"",
- sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\
- "SS_READY ":"",
- sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\
- "SS_BATDEAD ":"",
- sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\
- "SS_BATWARN ":"",
- sa1100_pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\
- "SS_STSCHG ":"");
+ skt->cs_state.csc_mask & SS_DETECT ? "SS_DETECT " : "",
+ skt->cs_state.csc_mask & SS_READY ? "SS_READY " : "",
+ skt->cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "",
+ skt->cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "",
+ skt->cs_state.csc_mask & SS_STSCHG ? "SS_STSCHG " : "");
p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\
- "SS_PWR_AUTO ":"",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\
- "SS_IOCARD ":"",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_RESET?\
- "SS_RESET ":"",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\
- "SS_SPKR_ENA ":"",
- sa1100_pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\
- "SS_OUTPUT_ENA ":"");
-
- p+=sprintf(p, "Vcc : %d\n", sa1100_pcmcia_socket[sock].cs_state.Vcc);
-
- p+=sprintf(p, "Vpp : %d\n", sa1100_pcmcia_socket[sock].cs_state.Vpp);
+ skt->cs_state.flags & SS_PWR_AUTO ? "SS_PWR_AUTO " : "",
+ skt->cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "",
+ skt->cs_state.flags & SS_RESET ? "SS_RESET " : "",
+ skt->cs_state.flags & SS_SPKR_ENA ? "SS_SPKR_ENA " : "",
+ skt->cs_state.flags & SS_OUTPUT_ENA ? "SS_OUTPUT_ENA " : "");
- p+=sprintf(p, "irq : %d\n", sa1100_pcmcia_socket[sock].cs_state.io_irq);
+ 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\n", skt->cs_state.io_irq);
- p+=sprintf(p, "I/O : %u (%u)\n", sa1100_pcmcia_socket[sock].speed_io,
+ p+=sprintf(p, "I/O : %u (%u)\n", skt->speed_io,
sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, sock)));
- p+=sprintf(p, "attribute: %u (%u)\n", sa1100_pcmcia_socket[sock].speed_attr,
+ p+=sprintf(p, "attribute: %u (%u)\n", skt->speed_attr,
sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, sock)));
- p+=sprintf(p, "common : %u (%u)\n", sa1100_pcmcia_socket[sock].speed_mem,
+ p+=sprintf(p, "common : %u (%u)\n", skt->speed_mem,
sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, sock)));
return p-buf;
}
+/* sa1100_pcmcia_proc_setup()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Implements the proc_setup() operation for the in-kernel PCMCIA
+ * service (formerly SS_ProcSetup in Card Services).
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static void
+sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+ struct proc_dir_entry *entry;
+
+ DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);
+
+ if ((entry = create_proc_entry("status", 0, base)) == NULL){
+ printk(KERN_ERR "unable to install \"status\" procfs entry\n");
+ return;
+ }
+
+ entry->read_proc = sa1100_pcmcia_proc_status;
+ entry->data = (void *)sock;
+}
+
#endif /* defined(CONFIG_PROC_FS) */
+static struct pccard_operations sa1100_pcmcia_operations = {
+ init: sa1100_pcmcia_sock_init,
+ suspend: sa1100_pcmcia_suspend,
+ register_callback: sa1100_pcmcia_register_callback,
+ inquire_socket: sa1100_pcmcia_inquire_socket,
+ get_status: sa1100_pcmcia_get_status,
+ get_socket: sa1100_pcmcia_get_socket,
+ set_socket: sa1100_pcmcia_set_socket,
+ get_io_map: sa1100_pcmcia_get_io_map,
+ set_io_map: sa1100_pcmcia_set_io_map,
+ get_mem_map: sa1100_pcmcia_get_mem_map,
+ set_mem_map: sa1100_pcmcia_set_mem_map,
+#ifdef CONFIG_PROC_FS
+ proc_setup: sa1100_pcmcia_proc_setup
+#endif
+};
#ifdef CONFIG_CPU_FREQ
@@ -1101,25 +854,23 @@ static int sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
* 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){
+static void sa1100_pcmcia_update_mecr(unsigned int clock)
+{
unsigned int sock;
unsigned long mecr = MECR;
for(sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock){
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
MECR_BSIO_SET(mecr, sock,
- sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_io,
- clock));
+ sa1100_pcmcia_mecr_bs(skt->speed_io, clock));
MECR_BSA_SET(mecr, sock,
- sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_attr,
- clock));
+ sa1100_pcmcia_mecr_bs(skt->speed_attr, clock));
MECR_BSM_SET(mecr, sock,
- sa1100_pcmcia_mecr_bs(sa1100_pcmcia_socket[sock].speed_mem,
- clock));
+ sa1100_pcmcia_mecr_bs(skt->speed_mem, clock));
}
MECR = mecr;
-
}
/* sa1100_pcmcia_notifier()
@@ -1132,53 +883,371 @@ static void sa1100_pcmcia_update_mecr(unsigned int clock){
*
* Returns: 0 on success, -1 on error
*/
-static int sa1100_pcmcia_notifier(struct notifier_block *nb,
- unsigned long val, void *data){
+static int
+sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
struct cpufreq_info *ci = data;
- switch(val){
- case CPUFREQ_MINMAX:
-
- break;
-
+ switch (val) {
case CPUFREQ_PRECHANGE:
-
- if(ci->new_freq > ci->old_freq){
+ if (ci->new_freq > ci->old_freq) {
DEBUG(2, "%s(): new frequency %u.%uMHz > %u.%uMHz, pre-updating\n",
__FUNCTION__,
ci->new_freq / 1000, (ci->new_freq / 100) % 10,
ci->old_freq / 1000, (ci->old_freq / 100) % 10);
sa1100_pcmcia_update_mecr(ci->new_freq);
}
-
break;
case CPUFREQ_POSTCHANGE:
-
- if(ci->new_freq < ci->old_freq){
+ if (ci->new_freq < ci->old_freq) {
DEBUG(2, "%s(): new frequency %u.%uMHz < %u.%uMHz, post-updating\n",
__FUNCTION__,
ci->new_freq / 1000, (ci->new_freq / 100) % 10,
ci->old_freq / 1000, (ci->old_freq / 100) % 10);
sa1100_pcmcia_update_mecr(ci->new_freq);
}
-
break;
-
- default:
- printk(KERN_ERR "%s(): unknown CPU frequency event %lx\n", __FUNCTION__,
- val);
- return -1;
-
}
return 0;
-
}
static struct notifier_block sa1100_pcmcia_notifier_block = {
- notifier_call: sa1100_pcmcia_notifier
+ notifier_call: sa1100_pcmcia_notifier
};
+#endif
+
+/* sa1100_register_pcmcia()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * Register an SA1100 PCMCIA low level driver with the SA1100 core.
+ */
+int sa1100_register_pcmcia(struct pcmcia_low_level *ops)
+{
+ struct pcmcia_init pcmcia_init;
+ struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK];
+ struct pcmcia_state_array state_array;
+ unsigned int i, clock;
+ unsigned long mecr;
+ int ret;
+
+ /*
+ * Refuse to replace an existing driver.
+ */
+ if (pcmcia_low_level)
+ return -EBUSY;
+
+ pcmcia_low_level = ops;
+
+ pcmcia_init.handler = sa1100_pcmcia_interrupt;
+ ret = ops->init(&pcmcia_init);
+ if (ret < 0) {
+ printk(KERN_ERR "Unable to initialize kernel PCMCIA service (%d).\n", ret);
+ if (ret == -1)
+ ret = -EIO;
+ goto out;
+ }
+
+ sa1100_pcmcia_socket_count = ret;
+
+ state_array.size = ret;
+ state_array.state = state;
+
+ memset(state, 0, sizeof(state));
+
+ if (ops->socket_state(&state_array) < 0) {
+ printk(KERN_ERR "Unable to get PCMCIA status driver.\n");
+ ret = -EIO;
+ goto shutdown;
+ }
+
+ /*
+ * We initialize the MECR to default values here, because we are
+ * not guaranteed to see a SetIOMap operation at runtime.
+ */
+ mecr = 0;
+
+ clock = cpufreq_get(0);
+
+ for (i = 0; i < sa1100_pcmcia_socket_count; i++) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
+ struct pcmcia_irq_info irq_info;
+
+ if (!request_mem_region(_PCMCIA(i), PCMCIASp, "PCMCIA")) {
+ ret = -EBUSY;
+ goto out_err;
+ }
+
+ irq_info.sock = i;
+ irq_info.irq = -1;
+ ret = ops->get_irq_info(&irq_info);
+ if (ret < 0)
+ printk(KERN_ERR "Unable to get IRQ for socket %u (%d)\n", i, ret);
+
+ skt->irq = irq_info.irq;
+ skt->k_state = state[i];
+ skt->speed_io = SA1100_PCMCIA_IO_ACCESS;
+ skt->speed_attr = SA1100_PCMCIA_5V_MEM_ACCESS;
+ skt->speed_mem = SA1100_PCMCIA_5V_MEM_ACCESS;
+ skt->phys_attr = _PCMCIAAttr(i);
+ skt->phys_mem = _PCMCIAMem(i);
+ skt->virt_io = ioremap(_PCMCIAIO(i), 0x10000);
+
+ if (skt->virt_io == NULL) {
+ ret = -ENOMEM;
+ goto out_err;
+ }
+
+ MECR_FAST_SET(mecr, i, 0);
+ MECR_BSIO_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_io, clock));
+ MECR_BSA_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_attr, clock));
+ MECR_BSM_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_mem, clock));
+ }
+
+ MECR = mecr;
+
+ /* Only advertise as many sockets as we can detect */
+ ret = register_ss_entry(sa1100_pcmcia_socket_count,
+ &sa1100_pcmcia_operations);
+ if (ret < 0) {
+ printk(KERN_ERR "Unable to register sockets\n");
+ goto out_err;
+ }
+
+ /*
+ * Start the event poll timer. It will reschedule by itself afterwards.
+ */
+ sa1100_pcmcia_poll_event(0);
+ return 0;
+
+ out_err:
+ for (i = 0; i < sa1100_pcmcia_socket_count; i++) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
+ iounmap(skt->virt_io);
+ skt->virt_io = NULL;
+ release_mem_region(_PCMCIA(i), PCMCIASp);
+ }
+
+ shutdown:
+ ops->shutdown();
+
+ out:
+ pcmcia_low_level = NULL;
+ return ret;
+}
+
+/* sa1100_unregister_pcmcia()
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * Unregister a previously registered pcmcia driver
+ */
+void sa1100_unregister_pcmcia(struct pcmcia_low_level *ops)
+{
+ int i;
+
+ if (!ops)
+ return;
+
+ if (ops != pcmcia_low_level) {
+ printk(KERN_DEBUG "PCMCIA: Trying to unregister wrong "
+ "low-level driver (%p != %p)", ops,
+ pcmcia_low_level);
+ return;
+ }
+
+ del_timer_sync(&poll_timer);
+
+ unregister_ss_entry(&sa1100_pcmcia_operations);
+
+ for (i = 0; i < sa1100_pcmcia_socket_count; i++) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
+
+ iounmap(skt->virt_io);
+ skt->virt_io = NULL;
+
+ release_mem_region(_PCMCIA(i), PCMCIASp);
+ }
+
+ ops->shutdown();
+
+ flush_scheduled_tasks();
+
+ pcmcia_low_level = NULL;
+}
+
+/* sa1100_pcmcia_init()
+ * ^^^^^^^^^^^^^^^^^^^^
+ *
+ * This routine performs a basic sanity check to ensure that this
+ * kernel has been built with the appropriate board-specific low-level
+ * PCMCIA support, performs low-level PCMCIA initialization, registers
+ * this socket driver with Card Services, and then spawns the daemon
+ * thread which is the real workhorse of the socket driver.
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int __init sa1100_pcmcia_init(void)
+{
+ servinfo_t info;
+ int ret, i;
+
+ printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE);
+
+ CardServices(GetCardServicesInfo, &info);
+ if (info.Revision != CS_RELEASE_CODE) {
+ printk(KERN_ERR "Card Services release codes do not match\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < SA1100_PCMCIA_MAX_SOCK; i++) {
+ struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i);
+ skt->speed_io = SA1100_PCMCIA_IO_ACCESS;
+ skt->speed_attr = SA1100_PCMCIA_5V_MEM_ACCESS;
+ skt->speed_mem = SA1100_PCMCIA_5V_MEM_ACCESS;
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block);
+ if (ret < 0) {
+ printk(KERN_ERR "Unable to register CPU frequency change "
+ "notifier (%d)\n", ret);
+ return ret;
+ }
+#endif
+
+#ifdef CONFIG_SA1100_ADSBITSY
+ pcmcia_adsbitsy_init();
+#endif
+#ifdef CONFIG_SA1100_ASSABET
+ pcmcia_assabet_init();
+#endif
+#ifdef CONFIG_SA1100_BADGE4
+ pcmcia_badge4_init();
+#endif
+#ifdef CONFIG_SA1100_CERF
+ pcmcia_cerf_init();
+#endif
+#ifdef CONFIG_SA1100_FLEXANET
+ pcmcia_flexanet_init();
+#endif
+#ifdef CONFIG_SA1100_FREEBIRD
+ pcmcia_freebird_init();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+ pcmcia_gcplus_init();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+ pcmcia_graphicsmaster_init();
+#endif
+#ifdef CONFIG_SA1100_JORNADA720
+ pcmcia_jornada720_init();
+#endif
+#ifdef CONFIG_ASSABET_NEPONSET
+ pcmcia_neponset_init();
+#endif
+#ifdef CONFIG_SA1100_PANGOLIN
+ pcmcia_pangolin_init();
+#endif
+#ifdef CONFIG_SA1100_PFS168
+ pcmcia_pfs_init();
+#endif
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+ pcmcia_system3_init();
+#endif
+#ifdef CONFIG_SA1100_SHANNON
+ pcmcia_shannon_init();
+#endif
+#ifdef CONFIG_SA1100_SIMPAD
+ pcmcia_simpad_init();
+#endif
+#ifdef CONFIG_SA1100_STORK
+ pcmcia_stork_init();
+#endif
+#ifdef CONFIG_SA1100_XP860
+ pcmcia_xp860_init();
+#endif
+#ifdef CONFIG_SA1100_YOPY
+ pcmcia_yopy_init();
#endif
+ return 0;
+}
+
+/* sa1100_pcmcia_exit()
+ * ^^^^^^^^^^^^^^^^^^^^
+ * Invokes the low-level kernel service to free IRQs associated with this
+ * socket controller and reset GPIO edge detection.
+ */
+static void __exit sa1100_pcmcia_exit(void)
+{
+#ifdef CONFIG_SA1100_ADSBITSY
+ pcmcia_adsbitsy_exit();
+#endif
+#ifdef CONFIG_SA1100_ASSABET
+ pcmcia_assabet_exit();
+#endif
+#ifdef CONFIG_SA1100_BADGE4
+ pcmcia_badge4_exit();
+#endif
+#ifdef CONFIG_SA1100_CERF
+ pcmcia_cerf_exit();
+#endif
+#ifdef CONFIG_SA1100_FLEXANET
+ pcmcia_flexanet_exit();
+#endif
+#ifdef CONFIG_SA1100_FREEBIRD
+ pcmcia_freebird_exit();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+ pcmcia_gcplus_exit();
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+ pcmcia_graphicsmaster_exit();
+#endif
+#ifdef CONFIG_SA1100_JORNADA720
+ pcmcia_jornada720_exit();
+#endif
+#ifdef CONFIG_ASSABET_NEPONSET
+ pcmcia_neponset_exit();
+#endif
+#ifdef CONFIG_SA1100_PANGOLIN
+ pcmcia_pangolin_exit();
+#endif
+#ifdef CONFIG_SA1100_PFS168
+ pcmcia_pfs_exit();
+#endif
+#ifdef CONFIG_SA1100_SHANNON
+ pcmcia_shannon_exit();
+#endif
+#ifdef CONFIG_SA1100_SIMPAD
+ pcmcia_simpad_exit();
+#endif
+#ifdef CONFIG_SA1100_STORK
+ pcmcia_stork_exit();
+#endif
+#ifdef CONFIG_SA1100_XP860
+ pcmcia_xp860_exit();
+#endif
+#ifdef CONFIG_SA1100_YOPY
+ pcmcia_yopy_exit();
+#endif
+
+ if (pcmcia_low_level) {
+ printk(KERN_ERR "PCMCIA: low level driver still registered\n");
+ sa1100_unregister_pcmcia(pcmcia_low_level);
+ }
+
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_unregister_notifier(&sa1100_pcmcia_notifier_block);
+#endif
+}
+
+MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services: SA-1100 Socket Controller");
+MODULE_LICENSE("Dual MPL/GPL");
+
+module_init(sa1100_pcmcia_init);
+module_exit(sa1100_pcmcia_exit);
diff --git a/drivers/pcmcia/sa1100_generic.h b/drivers/pcmcia/sa1100_generic.h
new file mode 100644
index 000000000000..ae44461a8bb4
--- /dev/null
+++ b/drivers/pcmcia/sa1100_generic.h
@@ -0,0 +1,77 @@
+/*
+ * linux/include/asm/arch/pcmcia.h
+ *
+ * Copyright (C) 2000 John G Dorsey <john+@cs.cmu.edu>
+ *
+ * This file contains definitions for the low-level SA-1100 kernel PCMCIA
+ * interface. Please see linux/Documentation/arm/SA1100/PCMCIA for details.
+ */
+#ifndef _ASM_ARCH_PCMCIA
+#define _ASM_ARCH_PCMCIA
+
+/* 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_init {
+ void (*handler)(int irq, void *dev, struct pt_regs *regs);
+};
+
+struct pcmcia_state {
+ unsigned detect: 1,
+ ready: 1,
+ bvd1: 1,
+ bvd2: 1,
+ wrprot: 1,
+ vs_3v: 1,
+ vs_Xv: 1;
+};
+
+struct pcmcia_state_array {
+ unsigned int size;
+ struct pcmcia_state *state;
+};
+
+struct pcmcia_configure {
+ unsigned sock: 8,
+ vcc: 8,
+ vpp: 8,
+ output: 1,
+ speaker: 1,
+ reset: 1,
+ irq: 1;
+};
+
+struct pcmcia_irq_info {
+ unsigned int sock;
+ unsigned int irq;
+};
+
+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 *);
+
+ /*
+ * Enable card status IRQs on (re-)initialisation. This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+ int (*socket_init)(int sock);
+
+ /*
+ * Disable card status IRQs and PCMCIA bus on suspend.
+ */
+ int (*socket_suspend)(int sock);
+};
+
+extern int sa1100_register_pcmcia(struct pcmcia_low_level *);
+extern void sa1100_unregister_pcmcia(struct pcmcia_low_level *);
+
+#endif
diff --git a/drivers/pcmcia/sa1100_graphicsclient.c b/drivers/pcmcia/sa1100_graphicsclient.c
index 0320d5cf4c10..6a3691df82ef 100644
--- a/drivers/pcmcia/sa1100_graphicsclient.c
+++ b/drivers/pcmcia/sa1100_graphicsclient.c
@@ -14,10 +14,13 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
+
+#error This is broken!
#define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
#define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
@@ -47,8 +50,9 @@ static int gcplus_pcmcia_init(struct pcmcia_init *init)
irq = S0_CD_IRQ;
res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA 0 CD", NULL);
if (res < 0) {
- printk(KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq);
- return -1;
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irq, res);
+ return res;
}
return 1; // 1 PCMCIA Slot
@@ -106,7 +110,7 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock>1) return -1;
- save_flags_cli(flags);
+ local_irq_save(flags);
switch (configure->vcc) {
case 0:
@@ -126,7 +130,7 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -139,16 +143,44 @@ static int gcplus_pcmcia_configure_socket(const struct pcmcia_configure
*PCMCIA_Power |= ADS_CS_PR_A_RESET;
mdelay(30);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
-struct pcmcia_low_level gcplus_pcmcia_ops = {
- gcplus_pcmcia_init,
- gcplus_pcmcia_shutdown,
- gcplus_pcmcia_socket_state,
- gcplus_pcmcia_get_irq_info,
- gcplus_pcmcia_configure_socket
+static int gcplus_pcmcia_socket_init(int sock)
+{
+ return 0;
+}
+
+static int gcplus_pcmcia_socket_suspend(int sock)
+{
+ return 0;
+}
+
+static struct pcmcia_low_level gcplus_pcmcia_ops = {
+ init: gcplus_pcmcia_init,
+ shutdown: gcplus_pcmcia_shutdown,
+ socket_state: gcplus_pcmcia_socket_state,
+ get_irq_info: gcplus_pcmcia_get_irq_info,
+ configure_socket: gcplus_pcmcia_configure_socket,
+
+ socket_init: gcplus_pcmcia_socket_init,
+ socket_suspend: gcplus_pcmcia_socket_suspend,
};
+int __init pcmcia_gcplus_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_gcplus())
+ ret = sa1100_register_pcmcia(&gcplus_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_gcplus_exit(void)
+{
+ sa1100_unregister_pcmcia(&gcplus_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_graphicsmaster.c b/drivers/pcmcia/sa1100_graphicsmaster.c
index 637be9d44ff1..8aeafa167cff 100644
--- a/drivers/pcmcia/sa1100_graphicsmaster.c
+++ b/drivers/pcmcia/sa1100_graphicsmaster.c
@@ -10,11 +10,12 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
-#include <asm/delay.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
{
@@ -26,190 +27,82 @@ static int graphicsmaster_pcmcia_init(struct pcmcia_init *init)
/* Disable Power 3.3V/5V for PCMCIA/CF */
PA_DWR |= GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
- INTPOL1 |= (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "GC Master PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "GC Master CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "GC Master PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "GC Master CF (1) BVD1", NULL);
-
+ /* why? */
MECR = 0x09430943;
- return (return_val<0) ? -1 : 2;
-}
-
-static int graphicsmaster_pcmcia_shutdown(void)
-{
-
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
-
- INTPOL1 &= ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
-
- return 0;
-}
-
-static int graphicsmaster_pcmcia_socket_state(struct pcmcia_state_array *state_array)
-{
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- status=PCSR;
-
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-
- return return_val;
-}
-
-static int graphicsmaster_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-{
-
- switch(info->sock){
- case 0:
- info->irq=S0_READY_NINT;
- break;
-
- case 1:
- info->irq=S1_READY_NINT;
- break;
-
- default:
- return -1;
- }
-
- return 0;
+ return sa1111_pcmcia_init(init);
}
-static int graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+static int
+graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
- unsigned long pccr=PCCR, gpio=PA_DWR;
+ unsigned int pa_dwr_mask, pa_dwr_set;
+ int ret;
- switch(configure->sock){
+ switch (conf->sock) {
case 0:
+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S0_FLT);
- gpio |= GPIO_GPIO0 | GPIO_GPIO1;
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
- gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
- gpio &= ~GPIO_GPIO0;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
- gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
- gpio |= GPIO_GPIO0;
- break;
-
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = GPIO_GPIO0 | GPIO_GPIO1; break;
+ case 33: pa_dwr_set = GPIO_GPIO1; break;
+ case 50: pa_dwr_set = GPIO_GPIO0; break;
}
-
- pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
-
break;
case 1:
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S1_FLT);
- gpio |= GPIO_GPIO2 | GPIO_GPIO3;
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
- gpio &= ~GPIO_GPIO2;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
- gpio |= GPIO_GPIO2;
- break;
+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
- }
-
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
+ case 0: pa_dwr_set = GPIO_GPIO2 | GPIO_GPIO3; break;
+ case 33: pa_dwr_set = GPIO_GPIO3; break;
+ case 50: pa_dwr_set = GPIO_GPIO2; break;
}
+ }
- pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
-
- break;
-
- default:
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
+ conf->vpp);
return -1;
}
- PCCR = pccr;
- PA_DWR = gpio;
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ local_irq_restore(flags);
+ }
- return 0;
+ return ret;
}
-struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
- graphicsmaster_pcmcia_init,
- graphicsmaster_pcmcia_shutdown,
- graphicsmaster_pcmcia_socket_state,
- graphicsmaster_pcmcia_get_irq_info,
- graphicsmaster_pcmcia_configure_socket
+static struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
+ init: graphicsmaster_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: graphicsmaster_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
};
+int __init pcmcia_graphicsmaster_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_graphicsmaster())
+ ret = sa1100_register_pcmcia(&graphicsmaster_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_graphicsmaster_exit(void)
+{
+ sa1100_unregister_pcmcia(&graphicsmaster_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index b8977769ea46..b9310ea18e51 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -6,142 +6,192 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
-
-
-static int h3600_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
-
- /* Enable CF bus: */
- set_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON);
- clr_h3600_egpio(EGPIO_H3600_OPT_RESET);
-
- /* All those are inputs */
- GPDR &= ~(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1 | GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1);
-
- /* Set transition detect */
- set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_H3600_PCMCIA_IRQ0| GPIO_H3600_PCMCIA_IRQ1, GPIO_FALLING_EDGE );
-
- /* Register interrupts */
- irq = IRQ_GPIO_H3600_PCMCIA_CD0;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
- if( res < 0 ) goto irq_err;
- irq = IRQ_GPIO_H3600_PCMCIA_CD1;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
- if( res < 0 ) goto irq_err;
-
- return 2;
+#include "sa1100_generic.h"
+
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" },
+ { IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" }
+};
-irq_err:
- printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
- return -1;
+static int h3600_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, res;
+
+ /*
+ * Set transition detect
+ */
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ0, IRQT_FALLING);
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_IRQ1, IRQT_FALLING);
+
+ /*
+ * Register interrupts
+ */
+ for (i = res = 0; i < ARRAY_SIZE(irqs); i++) {
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ break;
+ }
+
+ if (res) {
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+ }
+
+ return res ? res : 2;
}
static int h3600_pcmcia_shutdown(void)
{
- /* disable IRQs */
- free_irq( IRQ_GPIO_H3600_PCMCIA_CD0, NULL );
- free_irq( IRQ_GPIO_H3600_PCMCIA_CD1, NULL );
+ int i;
+
+ /*
+ * disable IRQs
+ */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
- /* Disable CF bus: */
- clr_h3600_egpio(EGPIO_H3600_OPT_NVRAM_ON|EGPIO_H3600_OPT_ON);
- set_h3600_egpio(EGPIO_H3600_OPT_RESET);
+ /* Disable CF bus: */
+ clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
+ clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
+ set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
- return 0;
+ return 0;
}
-static int h3600_pcmcia_socket_state(struct pcmcia_state_array
- *state_array){
- unsigned long levels;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- levels=GPLR;
-
- state_array->state[0].detect=((levels & GPIO_H3600_PCMCIA_CD0)==0)?1:0;
- state_array->state[0].ready=(levels & GPIO_H3600_PCMCIA_IRQ0)?1:0;
- state_array->state[0].bvd1= 0;
- state_array->state[0].bvd2= 0;
- state_array->state[0].wrprot=0; /* Not available on H3600. */
- state_array->state[0].vs_3v=0;
- state_array->state[0].vs_Xv=0;
-
- state_array->state[1].detect=((levels & GPIO_H3600_PCMCIA_CD1)==0)?1:0;
- state_array->state[1].ready=(levels & GPIO_H3600_PCMCIA_IRQ1)?1:0;
- state_array->state[1].bvd1=0;
- state_array->state[1].bvd2=0;
- state_array->state[1].wrprot=0; /* Not available on H3600. */
- state_array->state[1].vs_3v=0;
- state_array->state[1].vs_Xv=0;
-
- return 1;
+static int
+h3600_pcmcia_socket_state(struct pcmcia_state_array *state)
+{
+ unsigned long levels;
+
+ if (state->size < 2)
+ return -1;
+
+ levels = GPLR;
+
+ state->state[0].detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1;
+ state->state[0].ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0;
+ state->state[0].bvd1 = 0;
+ state->state[0].bvd2 = 0;
+ state->state[0].wrprot = 0; /* Not available on H3600. */
+ state->state[0].vs_3v = 0;
+ state->state[0].vs_Xv = 0;
+
+ state->state[1].detect = levels & GPIO_H3600_PCMCIA_CD1 ? 0 : 1;
+ state->state[1].ready = levels & GPIO_H3600_PCMCIA_IRQ1 ? 1 : 0;
+ state->state[1].bvd1 = 0;
+ state->state[1].bvd2 = 0;
+ state->state[1].wrprot = 0; /* Not available on H3600. */
+ state->state[1].vs_3v = 0;
+ state->state[1].vs_Xv = 0;
+
+ return 1;
}
-static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-
- switch (info->sock) {
- case 0:
- info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ0;
- break;
- case 1:
- info->irq=IRQ_GPIO_H3600_PCMCIA_IRQ1;
- break;
- default:
- return -1;
- }
- return 0;
+static int h3600_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ switch (info->sock) {
+ case 0:
+ info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ0;
+ break;
+ case 1:
+ info->irq = IRQ_GPIO_H3600_PCMCIA_IRQ1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
}
-static int h3600_pcmcia_configure_socket(const struct pcmcia_configure
- *configure)
+static int
+h3600_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
- unsigned long flags;
-
- if(configure->sock>1) return -1;
+ if (conf->sock > 1)
+ return -1;
- save_flags_cli(flags);
+ if (conf->vcc != 0 && conf->vcc != 33 && conf->vcc != 50) {
+ printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
+ conf->vcc / 10, conf->vcc % 10);
+ return -1;
+ }
- switch (configure->vcc) {
- case 0:
- clr_h3600_egpio(EGPIO_H3600_OPT_ON);
- break;
+ if (conf->reset)
+ set_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
+ else
+ clr_h3600_egpio(IPAQ_EGPIO_CARD_RESET);
- case 33:
- case 50:
- set_h3600_egpio(EGPIO_H3600_OPT_ON);
- break;
+ /* Silently ignore Vpp, output enable, speaker enable. */
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- restore_flags(flags);
- return -1;
- }
-
- if (configure->reset)
- set_h3600_egpio(EGPIO_H3600_CARD_RESET);
- else
- clr_h3600_egpio(EGPIO_H3600_CARD_RESET);
-
- /* Silently ignore Vpp, output enable, speaker enable. */
+ return 0;
+}
- restore_flags(flags);
+static int h3600_pcmcia_socket_init(int sock)
+{
+ /* Enable CF bus: */
+ set_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
+ set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
+ clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
+
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(10*HZ / 1000);
+
+ switch (sock) {
+ case 0:
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_BOTHEDGE);
+ break;
+ case 1:
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_BOTHEDGE);
+ break;
+ }
+
+ return 0;
+}
- return 0;
+static int h3600_pcmcia_socket_suspend(int sock)
+{
+ switch (sock) {
+ case 0:
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD0, IRQT_NOEDGE);
+ break;
+ case 1:
+ set_irq_type(IRQ_GPIO_H3600_PCMCIA_CD1, IRQT_NOEDGE);
+ break;
+ }
+
+ /*
+ * FIXME: This doesn't fit well. We don't have the mechanism in
+ * the generic PCMCIA layer to deal with the idea of two sockets
+ * on one bus. We rely on the cs.c behaviour shutting down
+ * socket 0 then socket 1.
+ */
+ if (sock == 1) {
+ clr_h3600_egpio(IPAQ_EGPIO_OPT_ON);
+ clr_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON);
+ /* hmm, does this suck power? */
+ set_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
+ }
+
+ return 0;
}
struct pcmcia_low_level h3600_pcmcia_ops = {
- h3600_pcmcia_init,
- h3600_pcmcia_shutdown,
- h3600_pcmcia_socket_state,
- h3600_pcmcia_get_irq_info,
- h3600_pcmcia_configure_socket
+ init: h3600_pcmcia_init,
+ shutdown: h3600_pcmcia_shutdown,
+ socket_state: h3600_pcmcia_socket_state,
+ get_irq_info: h3600_pcmcia_get_irq_info,
+ configure_socket: h3600_pcmcia_configure_socket,
+
+ socket_init: h3600_pcmcia_socket_init,
+ socket_suspend: h3600_pcmcia_socket_suspend,
};
diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
index 071f550f2394..a5d07781929a 100644
--- a/drivers/pcmcia/sa1100_jornada720.c
+++ b/drivers/pcmcia/sa1100_jornada720.c
@@ -6,21 +6,24 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
-#include <asm/delay.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
#define SOCKET0_POWER GPIO_GPIO0
#define SOCKET0_3V GPIO_GPIO2
#define SOCKET1_POWER (GPIO_GPIO1 | GPIO_GPIO3)
-#define SOCKET1_3V GPIO_GPIO3
+#warning *** Does SOCKET1_3V actually do anything?
+#define SOCKET1_3V GPIO_GPIO3
static int jornada720_pcmcia_init(struct pcmcia_init *init)
{
- int return_val=0;
-
+ /*
+ * What is all this crap for?
+ */
GRER |= 0x00000002;
/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */
PA_DDR = 0;
@@ -38,178 +41,82 @@ static int jornada720_pcmcia_init(struct pcmcia_init *init)
PC_SDR = 0;
PC_SSR = 0;
- INTPOL1 |=
- (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "Jornada720 PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "Jornada720 CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "Jornada720 PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "Jornada720 CF (1) BVD1", NULL);
-
- return (return_val<0) ? -1 : 2;
-}
-
-static int jornada720_pcmcia_shutdown(void)
-{
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
-
- INTPOL1 &=
- ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
-
- return 0;
-}
-
-static int jornada720_pcmcia_socket_state(struct pcmcia_state_array
- *state_array)
-{
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
- status=PCSR;
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
- return return_val;
-}
-
-static int jornada720_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
-{
- switch(info->sock){
- case 0:
- info->irq=S0_READY_NINT;
- break;
-
- case 1:
- info->irq=S1_READY_NINT;
- break;
-
- default:
- return -1;
- }
- return 0;
+ return sa1111_pcmcia_init(init);
}
-static int jornada720_pcmcia_configure_socket(const struct pcmcia_configure
- *configure)
+static int
+jornada720_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{
- unsigned long pccr=PCCR, gpio=PA_DWR;
+ unsigned int pa_dwr_mask, pa_dwr_set;
+ int ret;
printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
- configure->sock, configure->vcc, configure->vpp);
- switch(configure->sock){
+ conf->sock, conf->vcc, conf->vpp);
+
+ switch (conf->sock) {
case 0:
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S0_FLT);
- gpio&=~(SOCKET0_POWER | SOCKET0_3V);
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
- gpio |= SOCKET0_POWER | SOCKET0_3V;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
- gpio = (gpio & ~SOCKET0_3V) | SOCKET0_POWER;
- break;
+ pa_dwr_mask = SOCKET0_POWER | SOCKET0_3V;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
- }
- switch(configure->vpp){
- case 0:
- break;
- case 50:
- printk(KERN_ERR "%s(): 5.0 Vpp %u\n", __FUNCTION__,
- configure->vpp);
- break;
- case 120:
- printk(KERN_ERR "%s(): 12 Vpp %u\n", __FUNCTION__,
- configure->vpp);
- break;
- default:
- printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = SOCKET0_POWER | SOCKET0_3V; break;
+ case 50: pa_dwr_set = SOCKET0_POWER; break;
}
- pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
break;
case 1:
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S1_FLT);
- gpio &= ~(SOCKET1_POWER);
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
- gpio |= SOCKET1_POWER;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
- gpio = (gpio & ~(SOCKET1_POWER)) | SOCKET1_POWER;
- break;
+ pa_dwr_mask = SOCKET1_POWER;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = SOCKET1_POWER; break;
+ case 50: pa_dwr_set = SOCKET1_POWER; break;
}
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
- }
- pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
break;
- default:
+ }
+
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): slot cannot support VPP %u\n",
+ __FUNCTION__, conf->vpp);
return -1;
}
- PCCR = pccr;
- PA_DWR = gpio;
- return 0;
+
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ locla_irq_restore(flags);
+ }
+
+ return ret;
}
-struct pcmcia_low_level jornada720_pcmcia_ops = {
- jornada720_pcmcia_init,
- jornada720_pcmcia_shutdown,
- jornada720_pcmcia_socket_state,
- jornada720_pcmcia_get_irq_info,
- jornada720_pcmcia_configure_socket
+static struct pcmcia_low_level jornada720_pcmcia_ops = {
+ init: jornada720_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: jornada720_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
};
+int __init pcmcia_jornada720_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_jornada720())
+ ret = sa1100_register_pcmcia(&jornada720_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_jornada720_exit(void)
+{
+ sa1100_unregister_pcmcia(&jornada720_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index 9a556c3bec09..12408343d653 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -1,249 +1,145 @@
/*
- * drivers/pcmcia/sa1100_neponset.c
+ * linux/drivers/pcmcia/sa1100_neponset.c
*
* Neponset PCMCIA specific routines
- *
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
-#include <asm/delay.h>
#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
#include <asm/arch/assabet.h>
+#include <asm/hardware/sa1111.h>
-static int neponset_pcmcia_init(struct pcmcia_init *init){
- int return_val=0;
-
- /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
- PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
-
- /* MAX1600 to standby mode: */
- PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
- NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
-
- INTPOL1 |=
- (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "Neponset PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "Neponset CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "Neponset PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "Neponset CF (1) BVD1", NULL);
-
- return (return_val<0) ? -1 : 2;
-}
-
-static int neponset_pcmcia_shutdown(void){
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
+static int neponset_pcmcia_init(struct pcmcia_init *init)
+{
+ /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
+ PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
- INTPOL1 &=
- ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
+ /* MAX1600 to standby mode: */
+ PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+ NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
- return 0;
+ return sa1111_pcmcia_init(init);
}
-static int neponset_pcmcia_socket_state(struct pcmcia_state_array
- *state_array){
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- status=PCSR;
-
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-
- return return_val;
+static int
+neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ unsigned int ncr_mask, pa_dwr_mask;
+ unsigned int ncr_set, pa_dwr_set;
+ int ret;
+
+ /* Neponset uses the Maxim MAX1600, with the following connections:
+
+ * MAX1600 Neponset
+ *
+ * A0VCC SA-1111 GPIO A<1>
+ * A1VCC SA-1111 GPIO A<0>
+ * A0VPP CPLD NCR A0VPP
+ * A1VPP CPLD NCR A1VPP
+ * B0VCC SA-1111 GPIO A<2>
+ * B1VCC SA-1111 GPIO A<3>
+ * B0VPP ground (slot B is CF)
+ * B1VPP ground (slot B is CF)
+ *
+ * VX VCC (5V)
+ * VY VCC3_3 (3.3V)
+ * 12INA 12V
+ * 12INB ground (slot B is CF)
+ *
+ * The MAX1600 CODE pin is tied to ground, placing the device in
+ * "Standard Intel code" mode. Refer to the Maxim data sheet for
+ * the corresponding truth table.
+ */
+
+ switch (conf->sock) {
+ case 0:
+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
+ ncr_mask = NCR_A0VPP | NCR_A1VPP;
+
+ switch (conf->vcc) {
+ default:
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO1; break;
+ case 50: pa_dwr_set = GPIO_GPIO0; break;
+ }
+
+ switch (conf->vpp) {
+ case 0: ncr_set = 0; break;
+ case 120: ncr_set = NCR_A1VPP; break;
+ default:
+ if (conf->vpp == conf->vcc)
+ ncr_set = NCR_A0VPP;
+ else {
+ printk(KERN_ERR "%s(): unrecognized VPP %u\n",
+ __FUNCTION__, conf->vpp);
+ return -1;
+ }
+ }
+ break;
+
+ case 1:
+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
+ ncr_mask = 0;
+ ncr_set = 0;
+
+ switch (conf->vcc) {
+ default:
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO2; break;
+ case 50: pa_dwr_set = GPIO_GPIO3; break;
+ }
+
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
+ __FUNCTION__, conf->vpp);
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ local_irq_restore(flags);
+ }
+
+ return 0;
}
-static int neponset_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
+static struct pcmcia_low_level neponset_pcmcia_ops = {
+ init: neponset_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: neponset_pcmcia_configure_socket,
- switch(info->sock){
- case 0:
- info->irq=S0_READY_NINT;
- break;
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
+};
- case 1:
- info->irq=S1_READY_NINT;
- break;
+int __init pcmcia_neponset_init(void)
+{
+ int ret = -ENODEV;
- default:
- return -1;
- }
+ if (machine_is_assabet() && machine_has_neponset())
+ ret = sa1100_register_pcmcia(&neponset_pcmcia_ops);
- return 0;
+ return ret;
}
-static int neponset_pcmcia_configure_socket(const struct pcmcia_configure
- *configure){
- unsigned long pccr=PCCR, ncr=NCR_0, gpio=PA_DWR;
-
- /* Neponset uses the Maxim MAX1600, with the following connections:
- *
- * MAX1600 Neponset
- *
- * A0VCC SA-1111 GPIO A<1>
- * A1VCC SA-1111 GPIO A<0>
- * A0VPP CPLD NCR A0VPP
- * A1VPP CPLD NCR A1VPP
- * B0VCC SA-1111 GPIO A<2>
- * B1VCC SA-1111 GPIO A<3>
- * B0VPP ground (slot B is CF)
- * B1VPP ground (slot B is CF)
- *
- * VX VCC (5V)
- * VY VCC3_3 (3.3V)
- * 12INA 12V
- * 12INB ground (slot B is CF)
- *
- * The MAX1600 CODE pin is tied to ground, placing the device in
- * "Standard Intel code" mode. Refer to the Maxim data sheet for
- * the corresponding truth table.
- */
-
- switch(configure->sock){
- case 0:
-
- switch(configure->vcc){
- case 0:
- pccr=(pccr & ~PCCR_S0_FLT);
- gpio&=~(GPIO_GPIO0 | GPIO_GPIO1);
- break;
-
- case 33:
- pccr=(pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
- gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
- break;
-
- case 50:
- pccr=(pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
- gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
- break;
-
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
- }
-
- switch(configure->vpp){
- case 0:
- ncr&=~(NCR_A0VPP | NCR_A1VPP);
- break;
-
- case 120:
- ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A1VPP;
- break;
-
- default:
- if(configure->vpp == configure->vcc)
- ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A0VPP;
- else {
- printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
- }
- }
-
- pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
-
- break;
-
- case 1:
- switch(configure->vcc){
- case 0:
- pccr=(pccr & ~PCCR_S1_FLT);
- gpio&=~(GPIO_GPIO2 | GPIO_GPIO3);
- break;
-
- case 33:
- pccr=(pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
- gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO2;
- break;
-
- case 50:
- pccr=(pccr | PCCR_S1_PSE | PCCR_S1_FLT | PCCR_S1_PWAITEN);
- gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
- break;
-
- default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
- }
-
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
- configure->vpp);
- return -1;
- }
-
- pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
-
- break;
-
- default:
- return -1;
- }
-
- PCCR = pccr;
- NCR_0 = ncr;
- PA_DWR = gpio;
-
- return 0;
+void __exit pcmcia_neponset_exit(void)
+{
+ sa1100_unregister_pcmcia(&neponset_pcmcia_ops);
}
-
-struct pcmcia_low_level neponset_pcmcia_ops = {
- neponset_pcmcia_init,
- neponset_pcmcia_shutdown,
- neponset_pcmcia_socket_state,
- neponset_pcmcia_get_irq_info,
- neponset_pcmcia_configure_socket
-};
-
diff --git a/drivers/pcmcia/sa1100_pangolin.c b/drivers/pcmcia/sa1100_pangolin.c
index 9e68e50dc066..35455466f8f7 100644
--- a/drivers/pcmcia/sa1100_pangolin.c
+++ b/drivers/pcmcia/sa1100_pangolin.c
@@ -4,48 +4,45 @@
* PCMCIA implementation routines for Pangolin
*
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
static int pangolin_pcmcia_init(struct pcmcia_init *init){
- int irq, res;
+ int res;
- /* set GPIO_PCMCIA_CD & GPIO_PCMCIA_IRQ as inputs */
- GPDR &= ~(GPIO_PCMCIA_CD|GPIO_PCMCIA_IRQ);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
- /* set GPIO pins GPIO_PCMCIA_BUS_ON & GPIO_PCMCIA_RESET as output */
- GPDR |= (GPIO_PCMCIA_BUS_ON|GPIO_PCMCIA_RESET);
/* Enable PCMCIA bus: */
GPCR = GPIO_PCMCIA_BUS_ON;
-#else
- /* set GPIO pin GPIO_PCMCIA_RESET as output */
- GPDR |= GPIO_PCMCIA_RESET;
#endif
+
/* Set transition detect */
- set_GPIO_IRQ_edge( GPIO_PCMCIA_CD, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_PCMCIA_IRQ, GPIO_FALLING_EDGE );
+ set_irq_type(IRQ_PCMCIA_CD, IRQT_NOEDGE);
+ set_irq_type(IRQ_PCMCIA_IRQ, IRQT_FALLING);
/* Register interrupts */
- irq = IRQ_PCMCIA_CD;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD", NULL );
- if( res < 0 ) goto irq_err;
-
- /* There's only one slot, but it's "Slot 1": */
- return 2;
+ res = request_irq(IRQ_PCMCIA_CD, init->handler, SA_INTERRUPT,
+ "PCMCIA_CD", NULL);
+ if (res >= 0)
+ /* There's only one slot, but it's "Slot 1": */
+ return 2;
irq_err:
- printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
- return -1;
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, IRQ_PCMCIA_CD, res);
+
+ return res;
}
static int pangolin_pcmcia_shutdown(void)
{
/* disable IRQs */
- free_irq( IRQ_PCMCIA_CD, NULL );
+ free_irq(IRQ_PCMCIA_CD, NULL);
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
/* Disable PCMCIA bus: */
GPSR = GPIO_PCMCIA_BUS_ON;
@@ -105,7 +102,7 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
#ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
if(configure->sock==0) return 0;
#endif
- save_flags_cli(flags);
+ local_irq_save(flags);
/* Murphy: BUS_ON different from POWER ? */
@@ -129,7 +126,7 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
#ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
@@ -143,15 +140,47 @@ static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
}
#endif
/* Silently ignore Vpp, output enable, speaker enable. */
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
-struct pcmcia_low_level pangolin_pcmcia_ops = {
- pangolin_pcmcia_init,
- pangolin_pcmcia_shutdown,
- pangolin_pcmcia_socket_state,
- pangolin_pcmcia_get_irq_info,
- pangolin_pcmcia_configure_socket
+static int pangolin_pcmcia_socket_init(int sock)
+{
+ if (sock == 1)
+ set_irq_type(IRQ_PCmCIA_CD, IRQT_BOTHEDGE);
+ return 0;
+}
+
+static int pangolin_pcmcia_socket_suspend(int sock)
+{
+ if (sock == 1)
+ set_irq_type(IRQ_PCmCIA_CD, IRQT_NOEDGE);
+ return 0;
+}
+
+static struct pcmcia_low_level pangolin_pcmcia_ops = {
+ init: pangolin_pcmcia_init,
+ shutdown: pangolin_pcmcia_shutdown,
+ socket_state: pangolin_pcmcia_socket_state,
+ get_irq_info: pangolin_pcmcia_get_irq_info,
+ configure_socket: pangolin_pcmcia_configure_socket,
+
+ socket_init: pangolin_pcmcia_socket_init,
+ socket_suspend, pangolin_pcmcia_socket_suspend,
};
+int __init pcmcia_pangolin_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_pangolin())
+ ret = sa1100_register_pcmcia(&pangolin_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_pangolin_exit(void)
+{
+ sa1100_unregister_pcmcia(&pangolin_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_pfs168.c b/drivers/pcmcia/sa1100_pfs168.c
index ce9128c46a73..af028d61b682 100644
--- a/drivers/pcmcia/sa1100_pfs168.c
+++ b/drivers/pcmcia/sa1100_pfs168.c
@@ -7,121 +7,31 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/delay.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
-static int pfs168_pcmcia_init(struct pcmcia_init *init){
- int return_val=0;
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
+static int pfs168_pcmcia_init(struct pcmcia_init *init)
+{
/* TPS2211 to standby mode: */
PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* Set GPIO_A<3:0> to be outputs for PCMCIA (socket 0) power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
- INTPOL1 |=
- (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "PFS168 PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "PFS168 CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "PFS168 PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "PFS168 CF (1) BVD1", NULL);
-
- return (return_val<0) ? -1 : 2;
+ return sa1111_pcmcia_init(init);
}
-static int pfs168_pcmcia_shutdown(void){
-
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
-
- INTPOL1 &=
- ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
-
- return 0;
-}
-
-static int pfs168_pcmcia_socket_state(struct pcmcia_state_array
- *state_array){
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- status=PCSR;
-
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-
- return return_val;
-}
-
-static int pfs168_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-
- switch(info->sock){
- case 0:
- info->irq=S0_READY_NINT;
- break;
-
- case 1:
- info->irq=S1_READY_NINT;
- break;
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int pfs168_pcmcia_configure_socket(const struct pcmcia_configure
- *configure){
- unsigned long pccr=PCCR, gpio=PA_DWR;
+static int
+pfs168_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ unsigned int pa_dwr_mask = 0, pa_dwr_set = 0;
+ int ret;
/* PFS168 uses the Texas Instruments TPS2211 for PCMCIA (socket 0) voltage control only,
* with the following connections:
@@ -135,103 +45,100 @@ static int pfs168_pcmcia_configure_socket(const struct pcmcia_configure
*
*/
- switch(configure->sock){
+ switch (conf->sock) {
case 0:
+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3;
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S0_FLT);
- gpio &= ~(GPIO_GPIO0 | GPIO_GPIO1);
- break;
-
- case 33:
- pccr = (pccr & ~PCCR_S0_PSE) | PCCR_S0_FLT | PCCR_S0_PWAITEN;
- gpio = (gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
- break;
-
- case 50:
- pccr = (pccr | PCCR_S0_PSE | PCCR_S0_FLT | PCCR_S0_PWAITEN);
- gpio = (gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
- break;
-
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO0; break;
+ case 50: pa_dwr_set = GPIO_GPIO1; break;
}
- switch(configure->vpp){
+ switch (conf->vpp) {
case 0:
- gpio &= ~(GPIO_GPIO2 | GPIO_GPIO3);
break;
case 120:
- printk(KERN_ERR "%s(): PFS-168 does not support Vpp %uV\n", __FUNCTION__,
- configure->vpp/10);
+ printk(KERN_ERR "%s(): PFS-168 does not support VPP %uV\n",
+ __FUNCTION__, conf->vpp / 10);
return -1;
break;
default:
- if(configure->vpp == configure->vcc)
- gpio = (gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
+ if (conf->vpp == conf->vcc)
+ pa_dwr_set |= GPIO_GPIO3;
else {
- printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
- configure->vpp);
+ printk(KERN_ERR "%s(): unrecognized VPP %u\n", __FUNCTION__,
+ conf->vpp);
return -1;
}
}
-
- pccr = (configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
-
- PA_DWR = gpio;
-
break;
case 1:
- switch(configure->vcc){
- case 0:
- pccr = (pccr & ~PCCR_S1_FLT);
- break;
+ pa_dwr_mask = 0;
+ pa_dwr_set = 0;
+ switch (conf->vcc) {
+ case 0:
case 33:
- pccr = (pccr & ~PCCR_S1_PSE) | PCCR_S1_FLT | PCCR_S1_PWAITEN;
break;
case 50:
- printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support Vcc %uV\n", __FUNCTION__,
- configure->vcc/10);
+ printk(KERN_ERR "%s(): PFS-168 CompactFlash socket does not support VCC %uV\n",
+ __FUNCTION__, conf->vcc / 10);
return -1;
- break;
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
+ printk(KERN_ERR "%s(): unrecognized VCC %u\n", __FUNCTION__,
+ conf->vcc);
return -1;
}
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CompactFlash socket does not support Vpp %uV\n", __FUNCTION__,
- configure->vpp/10);
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): CompactFlash socket does not support VPP %uV\n"
+ __FUNCTION__, conf->vpp / 10);
return -1;
}
-
- pccr = (configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
-
break;
-
- default:
- return -1;
}
- PCCR = pccr;
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ local_irq_restore(flags);
+ }
return 0;
}
-struct pcmcia_low_level pfs168_pcmcia_ops = {
- pfs168_pcmcia_init,
- pfs168_pcmcia_shutdown,
- pfs168_pcmcia_socket_state,
- pfs168_pcmcia_get_irq_info,
- pfs168_pcmcia_configure_socket
+static struct pcmcia_low_level pfs168_pcmcia_ops = {
+ init: pfs168_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: pfs168_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
};
+
+int __init pcmcia_pfs168_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_pfs168())
+ ret = sa1100_register_pcmcia(&pfs168_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_pfs168_exit(void)
+{
+ sa1100_unregister_pcmcia(&pfs168_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
new file mode 100644
index 000000000000..7cfe0105a225
--- /dev/null
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -0,0 +1,177 @@
+/*
+ * drivers/pcmcia/sa1100_shannon.c
+ *
+ * PCMCIA implementation routines for Shannon
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/shannon.h>
+#include <asm/irq.h>
+#include "sa1100_generic.h"
+
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { SHANNON_IRQ_GPIO_EJECT_0, "PCMCIA_CD_0" },
+ { SHANNON_IRQ_GPIO_EJECT_1, "PCMCIA_CD_1" },
+};
+
+static int shannon_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, res;
+
+ /* All those are inputs */
+ GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
+ SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
+ GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |
+ SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1);
+
+ /* Set transition detect */
+ set_irq_type(SHANNON_IRQ_GPIO_RDY_0, IRQT_FALLING);
+ set_irq_type(SHANNON_IRQ_GPIO_RDY_1, IRQT_FALLING);
+
+ /* Register interrupts */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
+
+ return 2;
+
+ irq_err:
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ return res;
+}
+
+static int shannon_pcmcia_shutdown(void)
+{
+ int i;
+
+ /* disable IRQs */
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
+
+ return 0;
+}
+
+static int shannon_pcmcia_socket_state(struct pcmcia_state_array *state_array)
+{
+ unsigned long levels;
+
+ memset(state_array->state, 0,
+ state_array->size * sizeof(struct pcmcia_state));
+
+ levels = GPLR;
+
+ state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1;
+ state_array->state[0].ready = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0;
+ state_array->state[0].wrprot = 0; /* Not available on Shannon. */
+ state_array->state[0].bvd1 = 1;
+ state_array->state[0].bvd2 = 1;
+ state_array->state[0].vs_3v = 1; /* FIXME Can only apply 3.3V on Shannon. */
+ state_array->state[0].vs_Xv = 0;
+
+ state_array->state[1].detect = (levels & SHANNON_GPIO_EJECT_1) ? 0 : 1;
+ state_array->state[1].ready = (levels & SHANNON_GPIO_RDY_1) ? 1 : 0;
+ state_array->state[1].wrprot = 0; /* Not available on Shannon. */
+ state_array->state[1].bvd1 = 1;
+ state_array->state[1].bvd2 = 1;
+ state_array->state[1].vs_3v = 1; /* FIXME Can only apply 3.3V on Shannon. */
+ state_array->state[1].vs_Xv = 0;
+
+ return 1;
+}
+
+static int shannon_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ if (info->sock == 0)
+ info->irq = SHANNON_IRQ_GPIO_RDY_0;
+ else if (info->sock == 1)
+ info->irq = SHANNON_IRQ_GPIO_RDY_1;
+ else return -1;
+
+ return 0;
+}
+
+static int shannon_pcmcia_configure_socket(const struct pcmcia_configure *configure)
+{
+
+ switch (configure->vcc) {
+ case 0: /* power off */
+ printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n");
+ break;
+ case 50:
+ printk(KERN_WARNING __FUNCTION__"(): CS asked for 5V, applying 3.3V..\n");
+ case 33:
+ break;
+ default:
+ printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n",
+ configure->vcc);
+ return -1;
+ }
+
+ printk(KERN_WARNING __FUNCTION__"(): Warning, Can't perform reset\n");
+
+ /* Silently ignore Vpp, output enable, speaker enable. */
+
+ return 0;
+}
+
+static int shannon_pcmcia_socket_init(int sock)
+{
+ if (sock == 0)
+ set_irq_type(SHANNON_IRQ_GPIO_EJECT_0, IRQT_BOTHEDGE);
+ else if (sock == 1)
+ set_irq_Type(SHANNON_IRQ_GPIO_EJECT_1, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+static int shannon_pcmcia_socket_suspend(int sock)
+{
+ if (sock == 0)
+ set_irq_type(SHANNON_IRQ_GPIO_EJECT_0, IRQT_NOEDGE);
+ else if (sock == 1)
+ set_irq_type(SHANNON_IRQ_GPIO_EJECT_1, IRQT_NOEDGE);
+
+ return 0;
+}
+
+static struct pcmcia_low_level shannon_pcmcia_ops = {
+ init: shannon_pcmcia_init,
+ shutdown: shannon_pcmcia_shutdown,
+ socket_state: shannon_pcmcia_socket_state,
+ get_irq_info: shannon_pcmcia_get_irq_info,
+ configure_socket: shannon_pcmcia_configure_socket,
+
+ socket_init: shannon_pcmcia_socket_init,
+ socket_suspend: shannon_pcmcia_socket_suspend,
+};
+
+int __init pcmcia_shannon_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_shannon())
+ ret = sa1100_register_pcmcia(&shannon_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_shannon_exit(void)
+{
+ sa1100_unregister_pcmcia(&shannon_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index 0da5af015751..bbe79bdf8fc1 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -6,10 +6,11 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
extern long get_cs3_shadow(void);
extern void set_cs3_bit(int value);
@@ -19,9 +20,6 @@ extern void clear_cs3_bit(int value);
static int simpad_pcmcia_init(struct pcmcia_init *init){
int irq, res;
- /* set GPIO_CF_CD & GPIO_CF_IRQ as inputs */
- GPDR &= ~(GPIO_CF_CD|GPIO_CF_IRQ);
-
set_cs3_bit(PCMCIA_RESET);
clear_cs3_bit(PCMCIA_BUFF_DIS);
clear_cs3_bit(PCMCIA_RESET);
@@ -29,8 +27,8 @@ static int simpad_pcmcia_init(struct pcmcia_init *init){
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
/* Set transition detect */
- set_GPIO_IRQ_edge( GPIO_CF_CD, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
+ set_irq_type( IRQ_GPIO_CF_CD, IRQT_NOEDGE );
+ set_irq_type( IRQ_GPIO_CF_IRQ, IRQT_FALLING );
/* Register interrupts */
irq = IRQ_GPIO_CF_CD;
@@ -41,8 +39,9 @@ static int simpad_pcmcia_init(struct pcmcia_init *init){
return 2;
irq_err:
- printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
- return -1;
+ printk( KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irq, res);
+ return res;
}
static int simpad_pcmcia_shutdown(void)
@@ -112,7 +111,7 @@ static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
if(configure->sock==0) return 0;
- save_flags_cli(flags);
+ local_irq_save(flags);
/* Murphy: see table of MIC2562a-1 */
@@ -135,22 +134,51 @@ static int simpad_pcmcia_configure_socket(const struct pcmcia_configure
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
/* Silently ignore Vpp, output enable, speaker enable. */
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
-struct pcmcia_low_level simpad_pcmcia_ops = {
- simpad_pcmcia_init,
- simpad_pcmcia_shutdown,
- simpad_pcmcia_socket_state,
- simpad_pcmcia_get_irq_info,
- simpad_pcmcia_configure_socket
+static int simpad_pcmcia_socket_init(int sock)
+{
+ set_irq_type(IRQ_GPIO_CF_CD, IRQT_BOTHEDGE);
+ return 0;
+}
+
+static int simpad_pcmcia_socket_suspend(int sock)
+{
+ set_irq_type(IRQ_GPIO_CF_CD, IRQT_NOEDGE);
+ return 0;
+}
+
+static struct pcmcia_low_level simpad_pcmcia_ops = {
+ init: simpad_pcmcia_init,
+ shutdown: simpad_pcmcia_shutdown,
+ socket_state: simpad_pcmcia_socket_state,
+ get_irq_info: simpad_pcmcia_get_irq_info,
+ configure_socket: simpad_pcmcia_configure_socket,
+
+ socket_init: simpad_pcmcia_socket_init,
+ socket_suspend: simpad_pcmcia_socket_suspend,
};
+int __init pcmcia_simpad_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_simpad())
+ ret = sa1100_register_pcmcia(&simpad_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_simpad_exit(void)
+{
+ sa1100_unregister_pcmcia(&simpad_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_stork.c b/drivers/pcmcia/sa1100_stork.c
index 3ca0ea808de7..c172acce8305 100644
--- a/drivers/pcmcia/sa1100_stork.c
+++ b/drivers/pcmcia/sa1100_stork.c
@@ -18,8 +18,6 @@
* PCMCIA implementation routines for stork
*
*/
-
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -28,50 +26,58 @@
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
static int debug = 0;
-static struct pcmcia_init sa1100_stork_pcmcia_init;
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
+ { IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
+};
static int stork_pcmcia_init(struct pcmcia_init *init)
{
- int irq, res;
- printk("in stork_pcmcia_init\n");
-
- sa1100_stork_pcmcia_init = *init;
-
- /* Enable CF bus: */
- storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+ int irq, res;
- /* All those are inputs */
- GPDR &= ~(GPIO_STORK_PCMCIA_A_CARD_DETECT | GPIO_STORK_PCMCIA_B_CARD_DETECT | GPIO_STORK_PCMCIA_A_RDY| GPIO_STORK_PCMCIA_B_RDY);
+ printk("in stork_pcmcia_init\n");
/* Set transition detect */
- set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_CARD_DETECT | GPIO_STORK_PCMCIA_B_CARD_DETECT, GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_RDY| GPIO_STORK_PCMCIA_B_RDY, GPIO_FALLING_EDGE );
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_RDY, IRQT_FALLING);
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_RDY, IRQT_FALLING);
/* Register interrupts */
- irq = IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
- if( res < 0 ) goto irq_err;
- irq = IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT;
- res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
- if( res < 0 ) goto irq_err;
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
return 2;
irq_err:
- printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
- return -1;
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ return res;
}
static int stork_pcmcia_shutdown(void)
{
+ int i;
+
printk(__FUNCTION__ "\n");
+
/* disable IRQs */
- free_irq( IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, NULL );
- free_irq( IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, NULL );
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
/* Disable CF bus: */
storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
@@ -140,7 +146,7 @@ static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configur
printk(__FUNCTION__ ": socket=%d vcc=%d vpp=%d reset=%d\n",
card, configure->vcc, configure->vpp, configure->reset);
- save_flags_cli(flags);
+ local_irq_save(flags);
if (card == 0) {
DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
@@ -174,7 +180,7 @@ static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configur
default:
printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
configure->vcc);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -183,7 +189,7 @@ static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configur
else
storkClearLatchB(RESET);
- restore_flags(flags);
+ local_irq_restore(flags);
/* silently ignore vpp and speaker enables. */
@@ -192,11 +198,57 @@ static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configur
return 0;
}
-struct pcmcia_low_level stork_pcmcia_ops = {
- stork_pcmcia_init,
- stork_pcmcia_shutdown,
- stork_pcmcia_socket_state,
- stork_pcmcia_get_irq_info,
- stork_pcmcia_configure_socket
+static int stork_pcmcia_socket_init(int sock)
+{
+ storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+
+ if (sock == 0)
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, IRQT_BOTHEDGE);
+ else if (sock == 1)
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+static int stork_pcmcia_socket_suspend(int sock)
+{
+ if (sock == 0)
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, IRQT_NOEDGE);
+ else if (sock == 1) {
+ set_irq_type(IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, IRQT_NOEDGE);
+
+ /*
+ * Hack!
+ */
+ storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
+ }
+
+ return 0;
+}
+
+static struct pcmcia_low_level stork_pcmcia_ops = {
+ init: stork_pcmcia_init,
+ shutdown: stork_pcmcia_shutdown,
+ socket_state: stork_pcmcia_socket_state,
+ get_irq_info: stork_pcmcia_get_irq_info,
+ configure_socket: stork_pcmcia_configure_socket,
+
+ socket_init: stork_pcmcia_socket_init,
+ socket_suspend: stork_pcmcia_socket_suspend,
};
+int __init pcmcia_stork_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_stork())
+ ret = sa1100_register_pcmcia(&stork_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_stork_exit(void)
+{
+ sa1100_unregister_pcmcia(&stork_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_system3.c b/drivers/pcmcia/sa1100_system3.c
new file mode 100644
index 000000000000..fc4bed07c4a3
--- /dev/null
+++ b/drivers/pcmcia/sa1100_system3.c
@@ -0,0 +1,131 @@
+/*
+ * drivers/pcmcia/sa1100_system3.c
+ *
+ * PT Diagital Board PCMCIA specific routines
+ *
+ * Copyright (C) 2001 Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
+ *
+ * $Id: sa1100_system3.c,v 1.1.4.2 2002/02/25 13:56:45 seletz Exp $
+ *
+ * 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.
+ *
+ * $Log: sa1100_system3.c,v $
+ * Revision 1.1.4.2 2002/02/25 13:56:45 seletz
+ * - more cleanups
+ * - setup interrupts for CF card only ATM
+ *
+ * Revision 1.1.4.1 2002/02/14 02:23:27 seletz
+ * - 2.5.2-rmk6 PCMCIA changes
+ *
+ * Revision 1.1.2.1 2002/02/13 23:49:33 seletz
+ * - added from 2.4.16-rmk2
+ * - cleanups
+ *
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/hardware/sa1111.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
+
+#define DEBUG 0
+
+#ifdef DEBUG
+# define DPRINTK( x, args... ) printk( "%s: line %d: "x, __FUNCTION__, __LINE__, ## args );
+#else
+# define DPRINTK( x, args... ) /* nix */
+#endif
+
+int system3_pcmcia_init(struct pcmcia_init *init)
+{
+ /* Don't need no CD and BVD* interrupts */
+ return 2;
+}
+
+int system3_pcmcia_shutdown(void)
+{
+ return 0;
+}
+
+int system3_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ if (!conf)
+ return -1;
+
+ /* only CF ATM */
+ if (conf->sock == 0)
+ return -1;
+
+ return sa1111_pcmcia_configure_socket( conf );
+}
+
+static int system3_pcmcia_socket_state(struct pcmcia_state_array
+ *state)
+{
+ unsigned long status = 0;
+
+ if(state->size<2) return -1;
+
+ memset(state->state, 0,
+ (state->size)*sizeof(struct pcmcia_state));
+
+ status=PCSR;
+
+#if 0 /* PCMCIA socket not yet connected */
+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
+ state->state[0].bvd2 = 1;
+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
+ state->state[0].vs_3v = 1;
+ state->state[0].vs_Xv = 0;
+#endif
+
+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
+ state->state[1].bvd2 = 1;
+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
+ state->state[1].vs_3v = 1;
+ state->state[1].vs_Xv = 0;
+
+ DPRINTK( "PCSR=0x%08lx, S1_RDY_nIREQ=%d\n", status,
+ state->state[1].ready );
+
+ return 1;
+}
+
+struct pcmcia_low_level system3_pcmcia_ops = {
+ init: system3_pcmcia_init,
+ shutdown: system3_pcmcia_shutdown,
+ socket_state: system3_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: system3_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
+};
+
+int __init pcmcia_system3_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_pt_system3())
+ ret = sa1100_register_pcmcia(&system3_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_system3_exit(void)
+{
+ sa1100_unregister_pcmcia(&system3_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_xp860.c b/drivers/pcmcia/sa1100_xp860.c
index cd92680dbe4e..84c315a97cdd 100644
--- a/drivers/pcmcia/sa1100_xp860.c
+++ b/drivers/pcmcia/sa1100_xp860.c
@@ -7,128 +7,46 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
#define NCR_A0VPP (1<<16)
#define NCR_A1VPP (1<<17)
-static int xp860_pcmcia_init(struct pcmcia_init *init){
- int return_val=0;
-
+static int xp860_pcmcia_init(struct pcmcia_init *init)
+{
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* MAX1600 to standby mode: */
PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
+
+#error Consider the following comment
+ /*
+ * 1- Please move GPDR initialisation where it is interrupt or preemption
+ * safe (like from xp860_map_io).
+ * 2- The GPCR line is bogus i.e. it will simply have absolutely no effect.
+ * Please see its definition in the SA1110 manual.
+ * 3- Please do not use NCR_* values!
+ */
GPDR |= (NCR_A0VPP | NCR_A1VPP);
GPCR &= ~(NCR_A0VPP | NCR_A1VPP);
- INTPOL1 |=
- (1 << (S0_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S1_READY_NINT - SA1111_IRQ(32))) |
- (1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32)));
-
- return_val+=request_irq(S0_CD_VALID, init->handler, SA_INTERRUPT,
- "XP860 PCMCIA (0) CD", NULL);
- return_val+=request_irq(S1_CD_VALID, init->handler, SA_INTERRUPT,
- "XP860 CF (1) CD", NULL);
- return_val+=request_irq(S0_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "XP860 PCMCIA (0) BVD1", NULL);
- return_val+=request_irq(S1_BVD1_STSCHG, init->handler, SA_INTERRUPT,
- "XP860 CF (1) BVD1", NULL);
-
- return (return_val<0) ? -1 : 2;
-}
-
-static int xp860_pcmcia_shutdown(void){
-
- free_irq(S0_CD_VALID, NULL);
- free_irq(S1_CD_VALID, NULL);
- free_irq(S0_BVD1_STSCHG, NULL);
- free_irq(S1_BVD1_STSCHG, NULL);
-
- INTPOL1 &=
- ~((1 << (S0_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S1_CD_VALID - SA1111_IRQ(32))) |
- (1 << (S0_BVD1_STSCHG - SA1111_IRQ(32))) |
- (1 << (S1_BVD1_STSCHG - SA1111_IRQ(32))));
-
- return 0;
-}
-
-static int xp860_pcmcia_socket_state(struct pcmcia_state_array
- *state_array){
- unsigned long status;
- int return_val=1;
-
- if(state_array->size<2) return -1;
-
- memset(state_array->state, 0,
- (state_array->size)*sizeof(struct pcmcia_state));
-
- status=PCSR;
-
- state_array->state[0].detect=((status & PCSR_S0_DETECT)==0)?1:0;
-
- state_array->state[0].ready=((status & PCSR_S0_READY)==0)?0:1;
-
- state_array->state[0].bvd1=((status & PCSR_S0_BVD1)==0)?0:1;
-
- state_array->state[0].bvd2=((status & PCSR_S0_BVD2)==0)?0:1;
-
- state_array->state[0].wrprot=((status & PCSR_S0_WP)==0)?0:1;
-
- state_array->state[0].vs_3v=((status & PCSR_S0_VS1)==0)?1:0;
-
- state_array->state[0].vs_Xv=((status & PCSR_S0_VS2)==0)?1:0;
-
- state_array->state[1].detect=((status & PCSR_S1_DETECT)==0)?1:0;
-
- state_array->state[1].ready=((status & PCSR_S1_READY)==0)?0:1;
-
- state_array->state[1].bvd1=((status & PCSR_S1_BVD1)==0)?0:1;
-
- state_array->state[1].bvd2=((status & PCSR_S1_BVD2)==0)?0:1;
-
- state_array->state[1].wrprot=((status & PCSR_S1_WP)==0)?0:1;
-
- state_array->state[1].vs_3v=((status & PCSR_S1_VS1)==0)?1:0;
-
- state_array->state[1].vs_Xv=((status & PCSR_S1_VS2)==0)?1:0;
-
- return return_val;
+ return sa1111_pcmcia_init(init);
}
-static int xp860_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
-
- switch(info->sock){
- case 0:
- info->irq=S0_READY_NINT;
- break;
-
- case 1:
- info->irq=S1_READY_NINT;
- break;
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int xp860_pcmcia_configure_socket(const struct pcmcia_configure
- *configure){
- unsigned long pccr=PCCR, ncr=GPLR, gpio=PA_DWR;
-
+static int
+xp860_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ unsigned int gpio_mask, pa_dwr_mask;
+ unsigned int gpio_set, pa_dwr_set;
+ int ret;
/* Neponset uses the Maxim MAX1600, with the following connections:
+#warning ^^^ This isn't a neponset!
*
* MAX1600 Neponset
*
@@ -151,105 +69,90 @@ static int xp860_pcmcia_configure_socket(const struct pcmcia_configure
* the corresponding truth table.
*/
- switch(configure->sock){
+ switch (conf->sock) {
case 0:
-
- switch(configure->vcc){
- case 0:
- gpio&=~(GPIO_GPIO0 | GPIO_GPIO1);
- break;
-
- case 33:
- pccr=(pccr & ~PCCR_S0_PSE);
- gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO1;
- break;
-
- case 50:
- pccr=(pccr | PCCR_S0_PSE);
- gpio=(gpio & ~(GPIO_GPIO0 | GPIO_GPIO1)) | GPIO_GPIO0;
- break;
+ pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
+ gpio_mask = NCR_A0VPP | NCR_A1VPP;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO1; break;
+ case 50: pa_dwr_set = GPIO_GPIO0; break;
}
- switch(configure->vpp){
- case 0:
- ncr&=~(NCR_A0VPP | NCR_A1VPP);
- break;
-
- case 120:
- ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A1VPP;
- break;
+ switch (conf->vpp) {
+ case 0: gpio_set = 0; break;
+ case 120: gpio_set = NCR_A1VPP; break;
default:
- if(configure->vpp == configure->vcc)
- ncr=(ncr & ~(NCR_A0VPP | NCR_A1VPP)) | NCR_A0VPP;
+ if (conf->vpp == conf->vcc)
+ gpio_set = NCR_A0VPP;
else {
- printk(KERN_ERR "%s(): unrecognized Vpp %u\n", __FUNCTION__,
- configure->vpp);
+ printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
+ __FUNCTION__, conf->vpp);
return -1;
}
}
-
- pccr=(configure->reset)?(pccr | PCCR_S0_RST):(pccr & ~PCCR_S0_RST);
- pccr=(configure->output)?(pccr | PCCR_S0_FLT):(pccr & ~PCCR_S0_FLT);
-
break;
case 1:
- switch(configure->vcc){
- case 0:
- gpio&=~(GPIO_GPIO2 | GPIO_GPIO3);
- break;
-
- case 33:
- pccr=(pccr & ~PCCR_S1_PSE);
- gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO2;
- break;
-
- case 50:
- pccr=(pccr | PCCR_S1_PSE);
- gpio=(gpio & ~(GPIO_GPIO2 | GPIO_GPIO3)) | GPIO_GPIO3;
- break;
+ pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
+ gpio_mask = 0;
+ gpio_set = 0;
+ switch (conf->vcc) {
default:
- printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
- configure->vcc);
- return -1;
+ case 0: pa_dwr_set = 0; break;
+ case 33: pa_dwr_set = GPIO_GPIO2; break;
+ case 50: pa_dwr_set = GPIO_GPIO3; break;
}
- if(configure->vpp!=configure->vcc && configure->vpp!=0){
- printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n", __FUNCTION__,
- configure->vpp);
+ if (conf->vpp != conf->vcc && conf->vpp != 0) {
+ printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
+ __FUNCTION__, conf->vpp);
return -1;
}
-
- pccr=(configure->reset)?(pccr | PCCR_S1_RST):(pccr & ~PCCR_S1_RST);
- pccr=(configure->output)?(pccr | PCCR_S1_FLT):(pccr & ~PCCR_S1_FLT);
-
break;
-
- default:
- return -1;
}
- PCCR = pccr;
- ncr &= NCR_A0VPP|NCR_A1VPP;
- GPSR = ncr;
- GPCR = (~ncr)&(NCR_A0VPP|NCR_A1VPP);
- PA_DWR = gpio;
+ ret = sa1111_pcmcia_configure_socket(conf);
+ if (ret == 0) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
+ GPSR = gpio_set;
+ GPCR = gpio_set ^ gpio_mask;
+ local_irq_restore(flags);
+ }
- return 0;
+ return ret;
}
-struct pcmcia_low_level xp860_pcmcia_ops = {
- xp860_pcmcia_init,
- xp860_pcmcia_shutdown,
- xp860_pcmcia_socket_state,
- xp860_pcmcia_get_irq_info,
- xp860_pcmcia_configure_socket
+static struct pcmcia_low_level xp860_pcmcia_ops = {
+ init: xp860_pcmcia_init,
+ shutdown: sa1111_pcmcia_shutdown,
+ socket_state: sa1111_pcmcia_socket_state,
+ get_irq_info: sa1111_pcmcia_get_irq_info,
+ configure_socket: xp860_pcmcia_configure_socket,
+
+ socket_init: sa1111_pcmcia_socket_init,
+ socket_suspend: sa1111_pcmcia_socket_suspend,
};
+int __init pcmcia_xp860_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_xp860())
+ ret = sa1100_register_pcmcia(&xp860_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_xp860_exit(void)
+{
+ sa1100_unregister_pcmcia(&xp860_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1100_yopy.c b/drivers/pcmcia/sa1100_yopy.c
index 25d502d3d2c1..4bdb837cd6f1 100644
--- a/drivers/pcmcia/sa1100_yopy.c
+++ b/drivers/pcmcia/sa1100_yopy.c
@@ -6,10 +6,11 @@
*/
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
-#include <asm/arch/pcmcia.h>
+#include "sa1100_generic.h"
static inline void pcmcia_power(int on) {
@@ -23,45 +24,53 @@ static inline void pcmcia_reset(int reset)
yopy_gpio_set(GPIO_CF_RESET, reset);
}
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { IRQ_CF_CD, "CF_CD" },
+ { IRQ_CF_BVD2, "CF_BVD2" },
+ { IRQ_CF_BVD1, "CF_BVD1" },
+};
+
static int yopy_pcmcia_init(struct pcmcia_init *init)
{
- int irq, res;
+ int i, res;
pcmcia_power(0);
pcmcia_reset(1);
- /* All those are inputs */
- GPDR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IREQ);
- GAFR &= ~(GPIO_CF_CD | GPIO_CF_BVD2 | GPIO_CF_BVD1 | GPIO_CF_IREQ);
-
/* Set transition detect */
- set_GPIO_IRQ_edge( GPIO_CF_CD|GPIO_CF_BVD2|GPIO_CF_BVD1,
- GPIO_BOTH_EDGES );
- set_GPIO_IRQ_edge( GPIO_CF_IREQ, GPIO_FALLING_EDGE );
+ set_irq_type(IRQ_CF_IREQ, IRQT_FALLING);
/* Register interrupts */
- irq = IRQ_CF_CD;
- res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_CD", NULL);
- if (res < 0) goto irq_err;
- irq = IRQ_CF_BVD2;
- res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_BVD2", NULL);
- if (res < 0) goto irq_err;
- irq = IRQ_CF_BVD1;
- res = request_irq(irq, init->handler, SA_INTERRUPT, "CF_BVD1", NULL);
- if (res < 0) goto irq_err;
+ for (i = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+ res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (res)
+ goto irq_err;
+ }
return 1;
-irq_err:
- printk(KERN_ERR "%s: Request for IRQ %d failed\n", __FUNCTION__, irq);
- return -1;
+
+ irq_err:
+ printk(KERN_ERR "%s: request for IRQ%d failed (%d)\n",
+ __FUNCTION__, irqs[i].irq, res);
+
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ return res;
}
static int yopy_pcmcia_shutdown(void)
{
+ int i;
+
/* disable IRQs */
- free_irq( IRQ_CF_CD, NULL );
- free_irq( IRQ_CF_BVD2, NULL );
- free_irq( IRQ_CF_BVD1, NULL );
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
/* Disable CF */
pcmcia_reset(1);
@@ -109,7 +118,7 @@ static int yopy_pcmcia_configure_socket(const struct pcmcia_configure *configure
return -1;
switch (configure->vcc) {
- case 0: /* power off */;
+ case 0: /* power off */
pcmcia_power(0);
break;
case 50:
@@ -130,10 +139,49 @@ static int yopy_pcmcia_configure_socket(const struct pcmcia_configure *configure
return 0;
}
-struct pcmcia_low_level yopy_pcmcia_ops = {
- yopy_pcmcia_init,
- yopy_pcmcia_shutdown,
- yopy_pcmcia_socket_state,
- yopy_pcmcia_get_irq_info,
- yopy_pcmcia_configure_socket
+static int yopy_pcmcia_socket_init(int sock)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_BOTHEDGE);
+
+ return 0;
+}
+
+static int yopy_pcmcia_socket_suspend(int sock)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ set_irq_type(irqs[i].irq, IRQT_NOEDGE);
+
+ return 0;
+}
+
+static struct pcmcia_low_level yopy_pcmcia_ops = {
+ init: yopy_pcmcia_init,
+ shutdown: yopy_pcmcia_shutdown,
+ socket_state: yopy_pcmcia_socket_state,
+ get_irq_info: yopy_pcmcia_get_irq_info,
+ configure_socket: yopy_pcmcia_configure_socket,
+
+ socket_init: yopy_pcmcia_socket_init,
+ socket_suspend: yopy_pcmcia_socket_suspend,
};
+
+int __init pcmcia_yopy_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_yopy())
+ ret = sa1100_register_pcmcia(&yopy_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_yopy_exit(void)
+{
+ sa1100_unregister_pcmcia(&yopy_pcmcia_ops);
+}
+
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
new file mode 100644
index 000000000000..bd2b7fb28afd
--- /dev/null
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -0,0 +1,180 @@
+/*
+ * linux/drivers/pcmcia/sa1100_sa1111.c
+ *
+ * We implement the generic parts of a SA1111 PCMCIA driver. This
+ * basically means we handle everything except controlling the
+ * power. Power is machine specific...
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/sa1111.h>
+#include <asm/irq.h>
+
+#include "sa1100_generic.h"
+#include "sa1111_generic.h"
+
+static struct irqs {
+ int irq;
+ const char *str;
+} irqs[] = {
+ { S0_CD_VALID, "SA1111 PCMCIA card detect" },
+ { S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
+ { S1_CD_VALID, "SA1111 CF card detect" },
+ { S1_BVD1_STSCHG, "SA1111 CF BVD1" },
+};
+
+int sa1111_pcmcia_init(struct pcmcia_init *init)
+{
+ int i, ret;
+
+ if (!request_mem_region(_PCCR, 512, "PCMCIA"))
+ return -1;
+
+ for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
+ set_irq_type(irqs[i].irq, IRQT_FALLING);
+ ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
+ irqs[i].str, NULL);
+ if (ret)
+ break;
+ }
+
+ if (i < ARRAY_SIZE(irqs)) {
+ printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
+ irqs[i].irq, ret);
+ while (i--)
+ free_irq(irqs[i].irq, NULL);
+
+ release_mem_region(_PCCR, 16);
+ }
+
+ return ret ? -1 : 2;
+}
+
+int sa1111_pcmcia_shutdown(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irqs); i++)
+ free_irq(irqs[i].irq, NULL);
+
+ release_mem_region(_PCCR, 512);
+
+ return 0;
+}
+
+int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state)
+{
+ unsigned long status;
+
+ if (state->size < 2)
+ return -1;
+
+ status = PCSR;
+
+ state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
+ state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
+ state->state[0].bvd1 = status & PCSR_S0_BVD1 ? 1 : 0;
+ state->state[0].bvd2 = status & PCSR_S0_BVD2 ? 1 : 0;
+ state->state[0].wrprot = status & PCSR_S0_WP ? 1 : 0;
+ state->state[0].vs_3v = status & PCSR_S0_VS1 ? 0 : 1;
+ state->state[0].vs_Xv = status & PCSR_S0_VS2 ? 0 : 1;
+
+ state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
+ state->state[1].ready = status & PCSR_S1_READY ? 1 : 0;
+ state->state[1].bvd1 = status & PCSR_S1_BVD1 ? 1 : 0;
+ state->state[1].bvd2 = status & PCSR_S1_BVD2 ? 1 : 0;
+ state->state[1].wrprot = status & PCSR_S1_WP ? 1 : 0;
+ state->state[1].vs_3v = status & PCSR_S1_VS1 ? 0 : 1;
+ state->state[1].vs_Xv = status & PCSR_S1_VS2 ? 0 : 1;
+
+ return 1;
+}
+
+int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
+{
+ int ret = 0;
+
+ switch (info->sock) {
+ case 0: info->irq = S0_READY_NINT; break;
+ case 1: info->irq = S1_READY_NINT; break;
+ default: ret = 1;
+ }
+
+ return ret;
+}
+
+int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
+{
+ unsigned int rst, flt, wait, pse, irq, pccr_mask;
+ unsigned long flags;
+
+ switch (conf->sock) {
+ case 0:
+ rst = PCCR_S0_RST;
+ flt = PCCR_S0_FLT;
+ wait = PCCR_S0_PWAITEN;
+ pse = PCCR_S0_PSE;
+ irq = S0_READY_NINT;
+ break;
+
+ case 1:
+ rst = PCCR_S1_RST;
+ flt = PCCR_S1_FLT;
+ wait = PCCR_S1_PWAITEN;
+ pse = PCCR_S1_PSE;
+ irq = S1_READY_NINT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ switch (conf->vcc) {
+ case 0:
+ pccr_mask = 0;
+ break;
+
+ case 33:
+ pccr_mask = wait;
+ break;
+
+ case 50:
+ pccr_mask = pse | wait;
+ break;
+
+ default:
+ printk(KERN_ERR "sa1111_pcmcia: unrecognised VCC %u\n",
+ conf->vcc);
+ return -1;
+ }
+
+ if (conf->reset)
+ pccr_mask |= rst;
+
+ if (conf->output)
+ pccr_mask |= flt;
+
+ local_irq_save(flags);
+ PCCR = (PCCR & ~(pse | flt | wait | rst)) | pccr_mask;
+ local_irq_restore(flags);
+
+ if (conf->irq)
+ enable_irq(irq);
+ else
+ disable_irq(irq);
+
+ return 0;
+}
+
+int sa1111_pcmcia_socket_init(int sock)
+{
+ return 0;
+}
+
+int sa1111_pcmcia_socket_suspend(int sock)
+{
+ return 0;
+}
diff --git a/drivers/pcmcia/sa1111_generic.h b/drivers/pcmcia/sa1111_generic.h
new file mode 100644
index 000000000000..90e4e28dbd20
--- /dev/null
+++ b/drivers/pcmcia/sa1111_generic.h
@@ -0,0 +1,7 @@
+extern int sa1111_pcmcia_init(struct pcmcia_init *);
+extern int sa1111_pcmcia_shutdown(void);
+extern int sa1111_pcmcia_socket_state(struct pcmcia_state_array *);
+extern int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *);
+extern int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *);
+extern int sa1111_pcmcia_socket_init(int);
+extern int sa1111_pcmcia_socket_suspend(int);
diff --git a/fs/partitions/Config.in b/fs/partitions/Config.in
index faaee4ed11d6..83b3a60a65db 100644
--- a/fs/partitions/Config.in
+++ b/fs/partitions/Config.in
@@ -38,7 +38,7 @@ else
fi
if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
"$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
- "$CONFIG_SGI_IP27" != "y" ]; then
+ "$CONFIG_ARM" != "y" -a "$CONFIG_SGI_IP27" != "y" ]; then
define_bool CONFIG_MSDOS_PARTITION y
fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_AFFS_FS" = "y" ]; then
diff --git a/include/asm-arm/arch-sa1100/graphicsclient.h b/include/asm-arm/arch-sa1100/graphicsclient.h
index 794cbfe675bd..024e38709f1b 100644
--- a/include/asm-arm/arch-sa1100/graphicsclient.h
+++ b/include/asm-arm/arch-sa1100/graphicsclient.h
@@ -76,15 +76,6 @@
#define IRQ_GC_UART1_CTS IRQ_GPIO16
#define IRQ_GC_UART2_CTS IRQ_GPIO17
-#ifndef __ASSEMBLY__
-struct gc_uart_ctrl_data_t {
- int cts_gpio;
- int cts_prev_state;
- struct uart_info *info;
- struct uart_port *port;
-};
-#endif /* __ASSEMBLY__ */
-
/* LEDs */
#define ADS_LED0 GPIO_GPIO20 /* on-board D22 */
diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h
index 3105834da48c..d8caa5c836b4 100644
--- a/include/asm-arm/arch-sa1100/irqs.h
+++ b/include/asm-arm/arch-sa1100/irqs.h
@@ -151,4 +151,5 @@
#define IRQ_NEPONSET_SA1111 (IRQ_BOARD_START + 2)
/* PT Digital Board Interrupts (CONFIG_SA1100_PT_SYSTEM3) */
-#define IRQ_SYSTEM3_SMC9196 (IRQ_BOARD_START + 0)
+#define IRQ_SYSTEM3_SA1111 (IRQ_BOARD_START + 0)
+#define IRQ_SYSTEM3_SMC9196 (IRQ_BOARD_START + 1)
diff --git a/include/asm-arm/arch-sa1100/system3.h b/include/asm-arm/arch-sa1100/system3.h
index 11d24a5c1dfa..b83a41e0c88f 100644
--- a/include/asm-arm/arch-sa1100/system3.h
+++ b/include/asm-arm/arch-sa1100/system3.h
@@ -67,17 +67,17 @@
/* System ID register */
/* IRQ Source Register */
-#define PT_IRQ_LAN ( 1<<0 )
-#define PT_IRQ_X ( 1<<1 )
-#define PT_IRQ_SA1111 ( 1<<2 )
-#define PT_IRQ_RS1 ( 1<<3 )
-#define PT_IRQ_RS1_RING ( 1<<4 )
-#define PT_IRQ_RS1_DCD ( 1<<5 )
-#define PT_IRQ_RS1_DSR ( 1<<6 )
-#define PT_IRQ_RS2 ( 1<<7 )
+#define PT_IRR_LAN ( 1<<0 )
+#define PT_IRR_X ( 1<<1 )
+#define PT_IRR_SA1111 ( 1<<2 )
+#define PT_IRR_RS1 ( 1<<3 )
+#define PT_IRR_RS1_RING ( 1<<4 )
+#define PT_IRR_RS1_DCD ( 1<<5 )
+#define PT_IRR_RS1_DSR ( 1<<6 )
+#define PT_IRR_RS2 ( 1<<7 )
/* FIXME */
-#define PT_IRQ_USAR ( 1<<1 )
+#define PT_IRR_USAR ( 1<<1 )
/* CTRL 0 */
#define PT_CTRL0_USBSLAVE ( 1<<0 )
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index 3e154ed38f7f..0945e2e4d280 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -14,136 +14,20 @@
#include <asm/processor.h>
-/*
- * Get the cache handling stuff now.
- */
#include <asm/proc/cache.h>
-
-/*
- * ARM processors do not cache TLB tables in RAM.
- */
-#define flush_tlb_pgtables(mm,start,end) do { } while (0)
-
-/*
- * Processor specific parts...
- */
#include <asm/proc/pgalloc.h>
/*
- * Page table cache stuff
- */
-#ifndef CONFIG_NO_PGT_CACHE
-
-#ifdef CONFIG_SMP
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif /* CONFIG_SMP */
-
-extern struct pgtable_cache_struct {
- unsigned long *pgd_cache;
- unsigned long *pte_cache;
- unsigned long pgtable_cache_sz;
-} quicklists;
-
-#define pgd_quicklist (quicklists.pgd_cache)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist (quicklists.pte_cache)
-#define pgtable_cache_size (quicklists.pgtable_cache_sz)
-
-/* used for quicklists */
-#define __pgd_next(pgd) (((unsigned long *)pgd)[1])
-#define __pte_next(pte) (((unsigned long *)pte)[0])
-
-static inline pgd_t *get_pgd_fast(void)
-{
- unsigned long *ret;
-
- preempt_disable();
- if ((ret = pgd_quicklist) != NULL) {
- pgd_quicklist = (unsigned long *)__pgd_next(ret);
- ret[1] = ret[2];
- clean_dcache_entry(ret + 1);
- pgtable_cache_size--;
- }
- preempt_enable();
- return (pgd_t *)ret;
-}
-
-static inline void free_pgd_fast(pgd_t *pgd)
-{
- preempt_disable();
- __pgd_next(pgd) = (unsigned long) pgd_quicklist;
- pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
- preempt_enable();
-}
-
-static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
-{
- unsigned long *ret;
-
- preempt_disable();
- if((ret = pte_quicklist) != NULL) {
- pte_quicklist = (unsigned long *)__pte_next(ret);
- ret[0] = 0;
- clean_dcache_entry(ret);
- pgtable_cache_size--;
- }
- preempt_enable();
- return (pte_t *)ret;
-}
-
-static inline void free_pte_fast(pte_t *pte)
-{
- preempt_disable();
- __pte_next(pte) = (unsigned long) pte_quicklist;
- pte_quicklist = (unsigned long *) pte;
- pgtable_cache_size++;
- preempt_enable();
-}
-
-#else /* CONFIG_NO_PGT_CACHE */
-
-#define pgd_quicklist ((unsigned long *)0)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist ((unsigned long *)0)
-
-#define get_pgd_fast() ((pgd_t *)0)
-#define pte_alloc_one_fast(mm,addr) ((pte_t *)0)
-
-#define free_pgd_fast(pgd) free_pgd_slow(pgd)
-#define free_pte_fast(pte) pte_free_slow(pte)
-
-#endif /* CONFIG_NO_PGT_CACHE */
-
-#define pte_free(pte) free_pte_fast(pte)
-
-
-/*
* Since we have only two-level page tables, these are trivial
*/
-#define pmd_alloc_one_fast(mm,addr) ({ BUG(); ((pmd_t *)1); })
#define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
-#define pmd_free_slow(pmd) do { } while (0)
-#define pmd_free_fast(pmd) do { } while (0)
#define pmd_free(pmd) do { } while (0)
#define pgd_populate(mm,pmd,pte) BUG()
extern pgd_t *get_pgd_slow(struct mm_struct *mm);
extern void free_pgd_slow(pgd_t *pgd);
-static inline pgd_t *pgd_alloc(struct mm_struct *mm)
-{
- pgd_t *pgd;
-
- pgd = get_pgd_fast();
- if (!pgd)
- pgd = get_pgd_slow(mm);
-
- return pgd;
-}
-
-#define pgd_free(pgd) free_pgd_fast(pgd)
-
-extern int do_check_pgt_cache(int, int);
+#define pgd_alloc(mm) get_pgd_slow(mm)
+#define pgd_free(pgd) free_pgd_slow(pgd)
#endif
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index 1a19ac6a2f7f..4d468743909e 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -13,7 +13,6 @@
#include <linux/config.h>
#include <asm/arch/memory.h>
#include <asm/arch/vmalloc.h>
-#include <asm/proc-fns.h>
/*
* PMD_SHIFT determines the size of the area a second-level page table can map
@@ -146,8 +145,16 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
#define pmd_offset(dir, addr) ((pmd_t *)(dir))
/* Find an entry in the third-level page table.. */
-#define __pte_offset(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset(dir, addr) ((pte_t *)pmd_page(*(dir)) + __pte_offset(addr))
+#define __pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+#define pmd_page(dir) ((struct page *)__pmd_page(dir))
+
+#define __pte_offset(dir, addr) ((pte_t *)__pmd_page(*(dir)) + __pte_index(addr))
+#define pte_offset_kernel __pte_offset
+#define pte_offset_map __pte_offset
+#define pte_offset_map_nested __pte_offset
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
#include <asm/proc/pgtable.h>
diff --git a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h
index f5db111e1e78..d1d35bf9650b 100644
--- a/include/asm-arm/proc-armv/pgalloc.h
+++ b/include/asm-arm/proc-armv/pgalloc.h
@@ -18,7 +18,8 @@ extern kmem_cache_t *pte_cache;
* from the Linux copy. The processor copies are offset by -PTRS_PER_PTE
* words from the Linux copy.
*/
-static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
{
pte_t *pte;
@@ -28,10 +29,21 @@ static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
return pte;
}
+static inline struct page *
+pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ pte_t *pte;
+
+ pte = kmem_cache_alloc(pte_cache, GFP_KERNEL);
+ if (pte)
+ pte += PTRS_PER_PTE;
+ return (struct page *)pte;
+}
+
/*
* Free one PTE table.
*/
-static inline void pte_free_slow(pte_t *pte)
+static inline void pte_free_kernel(pte_t *pte)
{
if (pte) {
pte -= PTRS_PER_PTE;
@@ -39,6 +51,15 @@ static inline void pte_free_slow(pte_t *pte)
}
}
+static inline void pte_free(struct page *pte)
+{
+ pte_t *_pte = (pte_t *)pte;
+ if (pte) {
+ _pte -= PTRS_PER_PTE;
+ kmem_cache_free(pte_cache, _pte);
+ }
+}
+
/*
* Populate the pmdp entry with a pointer to the pte. This pmd is part
* of the mm address space.
@@ -46,12 +67,14 @@ static inline void pte_free_slow(pte_t *pte)
* If 'mm' is the init tasks mm, then we are doing a vmalloc, and we
* need to set stuff up correctly for it.
*/
+#define pmd_populate_kernel(mm,pmdp,pte) \
+ do { \
+ BUG_ON(mm != &init_mm); \
+ set_pmd(pmdp, __mk_pmd(pte, _PAGE_KERNEL_TABLE));\
+ } while (0)
+
#define pmd_populate(mm,pmdp,pte) \
do { \
- unsigned long __prot; \
- if (mm == &init_mm) \
- __prot = _PAGE_KERNEL_TABLE; \
- else \
- __prot = _PAGE_USER_TABLE; \
- set_pmd(pmdp, __mk_pmd(pte, __prot)); \
+ BUG_ON(mm == &init_mm); \
+ set_pmd(pmdp, __mk_pmd(pte, _PAGE_USER_TABLE)); \
} while (0)
diff --git a/include/asm-arm/proc-armv/pgtable.h b/include/asm-arm/proc-armv/pgtable.h
index d0da2c4a8d20..bdf9640ddd0b 100644
--- a/include/asm-arm/proc-armv/pgtable.h
+++ b/include/asm-arm/proc-armv/pgtable.h
@@ -125,7 +125,7 @@ static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
return pmd;
}
-static inline unsigned long pmd_page(pmd_t pmd)
+static inline unsigned long __pmd_page(pmd_t pmd)
{
unsigned long ptr;