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