Merge with Linux 2.4.0-test4-pre3.
[linux-2.6/linux-mips.git] / drivers / mtd / mixmem.c
blob8326f864b97557e9d069e17f83ee2461176964b6
1 /*
2 * mixmem - a block device driver for flash rom found on the
3 * piggyback board of the multi-purpose mixcom card
5 * Author: Gergely Madarasz <gorgo@itc.hu>
7 * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
9 * This code is GPL
13 #include <linux/module.h>
14 #include <linux/malloc.h>
15 #include <linux/ioport.h>
16 #include <asm/io.h>
17 #include <linux/init.h>
18 #include <linux/mtd/mapped.h>
20 #define MIXCOM_ID_OFFSET 0xc10
21 #define MIXCOM_PAGE_OFFSET 0xc11
22 #define MIXCOM_ID_1 0x11
23 #define MIXCOM_ID_2 0x13
24 #define MIXMEM_PAGESIZE 4096
25 #define FIRST_BLOCK_OFFSET 0x1000
27 #if LINUX_VERSION_CODE < 0x20300
28 #define __exit
29 #endif
31 static unsigned int mixmem_addrs[] = { 0xc8000, 0xd8000, 0 };
32 static unsigned int mixcom_ports[] = { 0x180, 0x280, 0x380, 0 };
34 // We could store these in the mtd structure, but we only support 1 device..
35 static unsigned long base_io = 0;
36 static unsigned long base_addr = 0;
37 static struct mapped_mtd_info *SSD;
39 static unsigned long mixmem_page(struct mapped_mtd_info *map,
40 unsigned long page)
42 outb((char)(page & 0xff), base_io+MIXCOM_PAGE_OFFSET);
43 outb((char)((page >> 8) & 0x7), base_io+MIXCOM_PAGE_OFFSET+1);
44 return base_addr;
47 static int flash_probe(int base)
49 int prev,curr;
50 unsigned long flags;
52 writeb(0xf0, base);
53 save_flags(flags); cli();
55 prev=readw(base);
57 writeb(0xaa, base+0x555);
58 writeb(0x55, base+0x2AA);
59 writeb(0x90, base+0x555);
61 curr=readw(base);
63 restore_flags(flags);
64 writeb(0xf0, base);
65 return(prev==curr?0:curr);
68 static int mixmem_probe(void)
70 int i;
71 int id;
72 int chip;
74 /* This should really check to see if the io ports are in use before
75 writing to them */
76 for(i=0;mixcom_ports[i]!=0;i++) {
77 id=inb(mixcom_ports[i]+MIXCOM_ID_OFFSET);
78 if(id==MIXCOM_ID_1 || id==MIXCOM_ID_2) {
79 printk("mixmem: mixcom board found at 0x%3x\n",mixcom_ports[i]);
80 break;
84 if(mixcom_ports[i]==0) {
85 printk("mixmem: no mixcom board found\n");
86 return -ENODEV;
89 if (check_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2)) return -EAGAIN;
93 // What is the deal with first_block_offset?
94 for(i=0;mixmem_addrs[i]!=0;i++) {
95 chip=flash_probe(mixmem_addrs[i]+FIRST_BLOCK_OFFSET);
96 if(chip)break;
99 if(mixmem_addrs[i]==0) {
100 printk("mixmem: no flash available\n");
101 return -ENODEV;
103 base_io = mixcom_ports[i];
104 base_addr = mixmem_addrs[i];
105 request_region(mixcom_ports[i]+MIXCOM_PAGE_OFFSET, 2, "mixmem");
106 return 0;
110 static void __exit cleanup_mixmem()
112 mtd_mapped_remove(SSD);
113 kfree(SSD);
114 SSD = 0;
115 release_region(base_io+MIXCOM_PAGE_OFFSET, 2);
118 //static int __init init_mixmem(void)
119 int __init init_mixmem(void)
121 if (mixmem_probe() != 0)
122 return -EAGAIN;
124 // Print out our little header..
125 printk("mixcom MTD IO:0x%lx MEM:0x%lx-0x%lx\n",base_io,base_addr,
126 base_addr+MIXMEM_PAGESIZE);
128 // Allocate some memory
129 SSD = (struct mapped_mtd_info *)kmalloc(sizeof(*SSD),GFP_KERNEL);
130 if (SSD == 0)
131 return 0;
132 memset(SSD,0,sizeof(*SSD));
134 // Setup the MTD structure
135 SSD->page = mixmem_page;
136 SSD->pagesize = MIXMEM_PAGESIZE;
137 SSD->maxsize = 0x7FF;
138 SSD->mtd.name = "mixcom piggyback";
140 // Setup the MTD, this will sense the flash parameters and so on..
141 if (mtd_mapped_setup(SSD) != 0)
143 printk("Failed to register new device\n");
144 cleanup_module();
145 return -EAGAIN;
148 return 0;
150 module_init(init_mixmem);
151 module_exit(cleanup_mixmem);