dslinux/linux-2.6.x/drivers/ide/arm Makefile ide_arm.c sccf_s.S
amadeus
dslinux_amadeus at user.in-berlin.de
Sun Sep 3 22:22:29 CEST 2006
Update of /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/ide/arm
In directory antilope:/tmp/cvs-serv7204/linux-2.6.x/drivers/ide/arm
Modified Files:
Makefile ide_arm.c
Added Files:
sccf_s.S
Log Message:
First "switching" CF driver for Supercard CF.
--- NEW FILE: sccf_s.S ---
/*
* linux/drivers/ide/arm/sccf_s.S - Supercard CF driver
*
* Copyright (C) 2006 Amadeus, All Rights Reserved.
*
* 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.
*
* This driver must be in main memory.
*/
/* common macros for all NDS GBA ROM device drivers */
#include <asm/arch/gbarom-macro.S>
.TEXT
/*****************************************************************************/
#define REG_SCCF_LBA1 0x09060000 @ 1st byte of sector address
/*****************************************************************************/
@ Test if the card is present.
@ This test is tricky because if it's NOT this card,
@ we are not allowed to destroy contents of GBA ROM space.
@ R0: Return != 0 if present.
.ALIGN
.GLOBAL sccf_detect_card
sccf_detect_card:
gba_prefix
@ read old value @ REG_SCCF_LBA1 (in RAM) and save in R1
ldr r3, =REG_SCCF_LBA1
ldrh r1, [r3]
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
@ test if the lower 8 bit of LBA1 are read- and writable
ldr r3, =REG_SCCF_LBA1
ldrb ip, [r3]
eor ip, ip, #0xFF @ invert lower 8 bit of LBA1
strh ip, [r3] @ store complement in LBA1
ldrb r0, [r3]
teq ip, r0 @ are they the same?
bne sccf_not_detected
@ make sure the register is 8 bit, not 16
ldr ip, =0xAA55
strh ip, [r3]
ldrh r0, [r3]
teq ip, r0 @ are they the same?
beq sccf_not_detected
mov r0, #1 @ positive detection
sccf_detect_exit:
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
@ restore RAM contents @ REG_SCCF_LBA1 from R1
ldr r3, =REG_SCCF_LBA1
strh r1, [r3]
gba_suffix
mov pc, lr
sccf_not_detected:
mov r0, #0
b sccf_detect_exit
/*****************************************************************************/
@ Read a byte from card register.
@ R0: address of register.
@ R0: return value @ register.
.ALIGN
.GLOBAL sccf_ide_inb
sccf_ide_inb:
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
ldrb r0, [r0]
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
mov pc, lr
/*****************************************************************************/
@ Read a word from card register.
@ R0: address of register.
@ R0: return value @ register.
.ALIGN
.GLOBAL sccf_ide_inw
sccf_ide_inw:
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
ldrh r0, [r0]
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
mov pc, lr
/*****************************************************************************/
@ Read a long from card register.
@ R0: address of register.
@ R0: return value @ register.
.ALIGN
.GLOBAL sccf_ide_inl
sccf_ide_inl:
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
ldr r0, [r0]
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
mov pc, lr
/*****************************************************************************/
@ Write a byte/word to card register.
@ R0: value
@ R1: address of register.
.ALIGN
.GLOBAL sccf_ide_outb
.GLOBAL sccf_ide_outw
sccf_ide_outb:
sccf_ide_outw:
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
strh r0, [r1] @ write a word. NDS can't write bytes.
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
mov pc, lr
/*****************************************************************************/
@ Write a long to card register.
@ R0: value
@ R1: address of register.
.ALIGN
.GLOBAL sccf_ide_outl
sccf_ide_outl:
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
str r0, [r1]
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
mov pc, lr
/*****************************************************************************/
@ Read a block of word data from card register.
@ R0: address of register.
@ R1: destination address.
@ R2: count
.ALIGN
.GLOBAL sccf_ide_insw
sccf_ide_insw:
stmfd sp!,{r4} @ use additional registers
mov r4, r2 @ save word count
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
sccf_ide_insw_loop:
ldrh r3, [r0]
strh r3, [r1], #2
subs r4, r4, #1
bne sccf_ide_insw_loop
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
ldmfd sp!,{r4} @ restore used registers
mov pc, lr
/*****************************************************************************/
@ Write a block of word data to card register.
@ R0: address of register.
@ R1: source address.
@ R2: count
.ALIGN
.GLOBAL sccf_ide_outsw
sccf_ide_outsw:
stmfd sp!,{r4} @ use additional registers
mov r4, r2 @ save word count
gba_prefix
@ now switch to IO mode (save old value @SC_LOCK in R2)
sc_set_io
sccf_ide_outsw_loop:
ldrh r3, [r1], #2
strh r3, [r0]
subs r4, r4, #1
bne sccf_ide_outsw_loop
@ switch back to RAM (restore old value @SC_LOCK from R2)
sc_set_ram
gba_suffix
ldmfd sp!,{r4} @ restore used registers
mov pc, lr
/*****************************************************************************/
.END
/*****************************************************************************/
Index: ide_arm.c
===================================================================
RCS file: /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/ide/arm/ide_arm.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- ide_arm.c 22 Aug 2006 15:07:58 -0000 1.8
+++ ide_arm.c 3 Sep 2006 20:22:27 -0000 1.9
@@ -30,7 +30,78 @@
# define IDE_ARM_IRQ IRQ_HARDDISK
#endif
+/*****************************************************************************/
+#ifdef CONFIG_NDS_ROM8BIT
+#define MAIN_MEM_BUFSIZE 256
+static u16 cf_data_buf[MAIN_MEM_BUFSIZE] __attribute__ ((aligned (4)));
+static void (*hw_ide_insw) (unsigned long port, u16 *dest, u32 count);
+static void (*hw_ide_outsw) (unsigned long port, u16 *src, u32 count);
+static void (*hw_ide_outb) (u8 value, unsigned long port);
+#endif
+
+/*****************************************************************************/
+#ifdef CONFIG_IDE_NDS_SUPERCARD
+/* externals from sccf_s.S */
+extern int sccf_detect_card(void);
+extern u8 sccf_ide_inb(unsigned long port);
+extern u16 sccf_ide_inw(unsigned long port);
+extern u32 sccf_ide_inl(unsigned long port);
+
+extern void sccf_ide_outb( u8 value, unsigned long port);
+extern void sccf_ide_outw(u16 value, unsigned long port);
+extern void sccf_ide_outl(u32 value, unsigned long port);
+
+extern void sccf_ide_insw(unsigned long port, u16 *dest, u32 count);
+extern void sccf_ide_outsw(unsigned long port, u16 *src, u32 count);
+#endif
+/*****************************************************************************/
+#ifdef CONFIG_NDS_ROM8BIT
+static void nds_ide_insw(unsigned long port, void *dest, u32 count)
+{
+ u16 *dst = (u16*)dest;
+ do {
+ u32 len = count;
+ if (len > MAIN_MEM_BUFSIZE)
+ len = MAIN_MEM_BUFSIZE;
+ hw_ide_insw(port, cf_data_buf, len);
+ memcpy(dst, cf_data_buf, len*sizeof(u16));
+ count -= len;
+ dst += len;
+ } while (count);
+}
+
+static void nds_ide_insl(unsigned long port, void *dest, u32 count)
+{
+ nds_ide_insw(port, dest, count *2);
+}
+
+static void nds_ide_outsw(unsigned long port, void *source, u32 count)
+{
+ u16 *src = (u16*)source;
+ do {
+ u32 len = count;
+ if (len > MAIN_MEM_BUFSIZE)
+ len = MAIN_MEM_BUFSIZE;
+ memcpy(cf_data_buf, src, len*sizeof(u16));
+ hw_ide_outsw(port, cf_data_buf, len);
+ count -= len;
+ src += len;
+ } while (count);
+}
+
+static void nds_ide_outsl(unsigned long port, void *source, u32 count)
+{
+ nds_ide_outsw(port, source, count *2);
+}
+
+static void nds_ide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port)
+{
+ hw_ide_outb(addr, port);
+}
+#endif
+
+/*****************************************************************************/
#ifdef CONFIG_IDE_NDS_M3
static void M3_Unlock( void )
{
@@ -55,6 +126,43 @@
int i;
memset(&hw, 0, sizeof(hw));
+
+#ifdef CONFIG_IDE_NDS_SUPERCARD
+ if (sccf_detect_card()) {
+ ide_hwif_t *hwif;
+
+ printk( KERN_INFO "Supercard CF detected\n");
+
+ /* setup register addresses */
+ for (i=0; i<8; i++)
+ hw.io_ports[i] = 0x09000000 + 0x20000*i;
+ hw.io_ports[8] = 0x098C0000; // control
+ /* setup IRQ */
+ hw.irq = IRQ_CART;
+ /* register hardware addresses */
+ ide_register_hw(&hw, &hwif);
+ /* modify IO functions */
+ hw_ide_insw = sccf_ide_insw;
+ hw_ide_outsw = sccf_ide_outsw;
+ hw_ide_outb = sccf_ide_outb;
+ hwif->OUTB = sccf_ide_outb;
+ hwif->OUTBSYNC = nds_ide_outbsync;
+ hwif->OUTW = sccf_ide_outw;
+ hwif->OUTL = sccf_ide_outl;
+ hwif->OUTSW = nds_ide_outsw;
+ hwif->OUTSL = nds_ide_outsl;
+ hwif->INB = sccf_ide_inb;
+ hwif->INW = sccf_ide_inw;
+ hwif->INL = sccf_ide_inl;
+ hwif->INSW = nds_ide_insw;
+ hwif->INSL = nds_ide_insl;
+ /* all OK */
+ return;
+ }
+#endif
+
+#ifndef CONFIG_NDS_ROM8BIT
+
#ifdef CONFIG_IDE_NDS_M3
M3_Unlock();
for (i=0; i<8; i++)
@@ -71,5 +179,6 @@
#endif
hw.irq = IRQ_CART;
ide_register_hw(&hw, NULL);
+#endif
}
}
Index: Makefile
===================================================================
RCS file: /cvsroot/dslinux/dslinux/linux-2.6.x/drivers/ide/arm/Makefile,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile 20 Feb 2006 16:04:59 -0000 1.2
+++ Makefile 3 Sep 2006 20:22:27 -0000 1.3
@@ -2,5 +2,6 @@
obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o
+obj-$(CONFIG_IDE_NDS_SUPERCARD) += sccf_s.o
EXTRA_CFLAGS := -Idrivers/ide
More information about the dslinux-commit
mailing list