summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mixmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mixmem.c')
-rw-r--r--drivers/mtd/mixmem.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/drivers/mtd/mixmem.c b/drivers/mtd/mixmem.c
new file mode 100644
index 000000000..8326f864b
--- /dev/null
+++ b/drivers/mtd/mixmem.c
@@ -0,0 +1,151 @@
+/*
+ * mixmem - a block device driver for flash rom found on the
+ * piggyback board of the multi-purpose mixcom card
+ *
+ * Author: Gergely Madarasz <gorgo@itc.hu>
+ *
+ * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
+ *
+ * This code is GPL
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/init.h>
+#include <linux/mtd/mapped.h>
+
+#define MIXCOM_ID_OFFSET 0xc10
+#define MIXCOM_PAGE_OFFSET 0xc11
+#define MIXCOM_ID_1 0x11
+#define MIXCOM_ID_2 0x13
+#define MIXMEM_PAGESIZE 4096
+#define FIRST_BLOCK_OFFSET 0x1000
+
+#if LINUX_VERSION_CODE < 0x20300
+#define __exit
+#endif
+
+static unsigned int mixmem_addrs[] = { 0xc8000, 0xd8000, 0 };
+static unsigned int mixcom_ports[] = { 0x180, 0x280, 0x380, 0 };
+
+// We could store these in the mtd structure, but we only support 1 device..
+static unsigned long base_io = 0;
+static unsigned long base_addr = 0;
+static struct mapped_mtd_info *SSD;
+
+static unsigned long mixmem_page(struct mapped_mtd_info *map,
+ unsigned long page)
+{
+ outb((char)(page & 0xff), base_io+MIXCOM_PAGE_OFFSET);
+ outb((char)((page >> 8) & 0x7), base_io+MIXCOM_PAGE_OFFSET+1);
+ return base_addr;
+}
+
+static int flash_probe(int base)
+{
+ int prev,curr;
+ unsigned long flags;
+
+ writeb(0xf0, base);
+ save_flags(flags); cli();
+
+ prev=readw(base);
+
+ writeb(0xaa, base+0x555);
+ writeb(0x55, base+0x2AA);
+ writeb(0x90, base+0x555);
+
+ curr=readw(base);
+
+ restore_flags(flags);
+ writeb(0xf0, base);
+ return(prev==curr?0:curr);
+}
+
+static int mixmem_probe(void)
+{
+ int i;
+ int id;
+ int chip;
+
+ /* This should really check to see if the io ports are in use before
+ writing to them */
+ for(i=0;mixcom_ports[i]!=0;i++) {
+ id=inb(mixcom_ports[i]+MIXCOM_ID_OFFSET);
+ if(id==MIXCOM_ID_1 || id==MIXCOM_ID_2) {
+ printk("mixmem: mixcom board found at 0x%3x\n",mixcom_ports[i]);
+ break;
+ }
+ }
+
+ if(mixcom_ports[i]==0) {
+ printk("mixmem: no mixcom board found\n");
+ return -ENODEV;
+ }
+
+ if (check_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2)) return -EAGAIN;
+
+
+
+ // What is the deal with first_block_offset?
+ for(i=0;mixmem_addrs[i]!=0;i++) {
+ chip=flash_probe(mixmem_addrs[i]+FIRST_BLOCK_OFFSET);
+ if(chip)break;
+ }
+
+ if(mixmem_addrs[i]==0) {
+ printk("mixmem: no flash available\n");
+ return -ENODEV;
+ }
+ base_io = mixcom_ports[i];
+ base_addr = mixmem_addrs[i];
+ request_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2, "mixmem");
+ return 0;
+}
+
+
+static void __exit cleanup_mixmem()
+{
+ mtd_mapped_remove(SSD);
+ kfree(SSD);
+ SSD = 0;
+ release_region(base_io+MIXCOM_PAGE_OFFSET, 2);
+}
+
+//static int __init init_mixmem(void)
+int __init init_mixmem(void)
+{
+ if (mixmem_probe() != 0)
+ return -EAGAIN;
+
+ // Print out our little header..
+ printk("mixcom MTD IO:0x%lx MEM:0x%lx-0x%lx\n",base_io,base_addr,
+ base_addr+MIXMEM_PAGESIZE);
+
+ // Allocate some memory
+ SSD = (struct mapped_mtd_info *)kmalloc(sizeof(*SSD),GFP_KERNEL);
+ if (SSD == 0)
+ return 0;
+ memset(SSD,0,sizeof(*SSD));
+
+ // Setup the MTD structure
+ SSD->page = mixmem_page;
+ SSD->pagesize = MIXMEM_PAGESIZE;
+ SSD->maxsize = 0x7FF;
+ SSD->mtd.name = "mixcom piggyback";
+
+ // Setup the MTD, this will sense the flash parameters and so on..
+ if (mtd_mapped_setup(SSD) != 0)
+ {
+ printk("Failed to register new device\n");
+ cleanup_module();
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+module_init(init_mixmem);
+module_exit(cleanup_mixmem);