sync hh.org
[hh.org.git] / drivers / pcmcia / h3600_sleeve_flash.c
blob097a467297929b164d3ab91d2229ca23e180ebbd
1 /*
2 * drivers/pcmcia/h3600_generic
4 * PCMCIA implementation routines for H3600 iPAQ standards sleeves
6 */
8 #include <linux/module.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/i2c.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/map.h>
16 #include <linux/mtd/partitions.h>
18 #include <asm/hardware.h>
19 #include <asm/irq.h>
20 #include <asm/io.h>
21 #include <asm/arch/pcmcia.h>
22 #include <asm/arch/h3600-sleeve.h>
23 #include <asm/arch/linkup-l1110.h>
24 #include <asm/arch/backpaq.h>
29 struct mtd_partition pcmcia_sleeve_flash_partitions[] = {
31 name: "PCMCIA Sleeve Flash",
32 offset: 0x00000000,
33 size: 0 /* will expand to the end of the flash */
37 #define NB_OF(x) (sizeof(x)/sizeof(x[0]))
39 #define WINDOW_ADDR 0xf1000000 /* static memory bank 1 */
41 static int offset_multiplier = 1; /* 2 for rev-A backpaqs -- don't ask -- Jamey 2/12/2001 */
43 static __u8 sa1100_read8(struct map_info *map, unsigned long ofs)
45 return *(__u8 *)(WINDOW_ADDR + ofs*offset_multiplier);
48 static __u16 sa1100_read16(struct map_info *map, unsigned long ofs)
50 __u16 d = *(__u16 *)(WINDOW_ADDR + ofs*offset_multiplier);
51 if (debug >= 1) printk(__FUNCTION__ " ofs=%08lx (adr=%p) => d=%#x\n", ofs, (__u16 *)(WINDOW_ADDR + ofs*offset_multiplier), d);
52 return d;
55 static __u32 sa1100_read32(struct map_info *map, unsigned long ofs)
57 return *(__u32 *)(WINDOW_ADDR + ofs*offset_multiplier);
60 static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
62 int i;
63 if (0) printk(__FUNCTION__ " from=%08lx offset_multiplier=%d\n", WINDOW_ADDR + from, offset_multiplier);
64 if (offset_multiplier == 1) {
65 memcpy(to, (void *)(WINDOW_ADDR + from), len);
66 } else {
67 for (i = 0; i < len; i += 2) {
68 *(short *)(to++) = *(short *)(WINDOW_ADDR + from*offset_multiplier + i*offset_multiplier);
73 static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr)
75 *(__u8 *)(WINDOW_ADDR + adr*offset_multiplier) = d;
78 static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr)
80 if (debug >= 1) printk(__FUNCTION__ " adr=%08lx d=%x\n", WINDOW_ADDR + adr*offset_multiplier, d);
81 *(__u16 *)(WINDOW_ADDR + adr*offset_multiplier) = d;
84 static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr)
86 *(__u32 *)(WINDOW_ADDR + adr*offset_multiplier) = d;
89 static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
91 int i;
92 if (0) printk(__FUNCTION__ " to=%08lx offset_multiplier=%d\n", WINDOW_ADDR + to, offset_multiplier);
93 if (offset_multiplier == 1) {
94 memcpy((void *)(WINDOW_ADDR + to), from, len);
95 } else {
96 for (i = 0; i < len; i += 2) {
97 *(short *)(WINDOW_ADDR + to*offset_multiplier + i*offset_multiplier) = *(short *)(from + i);
102 static void pcmcia_set_vpp(struct map_info *map, int vpp)
104 /* ??? Is this correct? Why not set flash program mode? */
105 assign_h3600_egpio( IPAQ_EGPIO_OPT_RESET, vpp );
108 static struct map_info pcmcia_sleeve_flash_map = {
109 name: "PCMCIA Sleeve Flash ",
110 read8: sa1100_read8,
111 read16: sa1100_read16,
112 read32: sa1100_read32,
113 copy_from: sa1100_copy_from,
114 write8: sa1100_write8,
115 write16: sa1100_write16,
116 write32: sa1100_write32,
117 copy_to: sa1100_copy_to,
118 size: 0x02000000,
119 set_vpp: NULL,
120 buswidth: 2
123 static struct mtd_info *pcmcia_sleeve_mtd = NULL;
125 int pcmcia_sleeve_attach_flash(void (*set_vpp)(struct map_info *, int), unsigned long map_size)
127 unsigned long msc1_sm1_config = (MSC_NonBrst | MSC_16BitStMem
128 | MSC_RdAcc((150 + 100)/4)
129 | MSC_NxtRdAcc((150 + 100)/4)
130 | MSC_Rec(100/4));
131 void *(*cfi_probe)(void *) = inter_module_get("cfi_probe");
132 if ( !cfi_probe )
133 return -ENXIO;
135 msc1_sm1_config = 0xFFFC;
136 MSC1 = ((MSC1 & 0xFFFF) /* sm0 */
137 | (msc1_sm1_config << 16));
139 printk(__FUNCTION__ ": setting MSC1=0x%x\n", MSC1);
141 pcmcia_sleeve_flash_map.set_vpp = set_vpp;
142 pcmcia_sleeve_flash_map.size = map_size;
144 pcmcia_sleeve_mtd = cfi_probe(&pcmcia_sleeve_flash_map);
145 if ( pcmcia_sleeve_mtd ) {
146 pcmcia_sleeve_mtd->module = THIS_MODULE;
147 add_mtd_device(pcmcia_sleeve_mtd);
148 return 0;
151 printk(" *** " __FUNCTION__ ": unable to add flash device\n");
152 return -ENXIO;
155 void pcmcia_sleeve_detach_flash(void)
157 printk(" ### " __FUNCTION__ "\n");
158 if (pcmcia_sleeve_mtd != NULL) {
159 printk(" ### " __FUNCTION__ " 2\n");
160 del_mtd_device(pcmcia_sleeve_mtd);
161 printk(" #### " __FUNCTION__ " 3\n");
162 map_destroy(pcmcia_sleeve_mtd);
163 printk(" ### " __FUNCTION__ " 4\n");
164 pcmcia_sleeve_mtd = NULL;
169 int old_pcmcia_sleeve_attach_flash(void (*set_vpp)(struct map_info *, int), unsigned long map_size)
171 void *(*cfi_probe)(void *) = inter_module_get("cfi_probe");
173 printk(" ### " __FUNCTION__ "\n");
175 if (cfi_probe != NULL) {
177 * assuming 150ns Flash, 30ns extra to cross the expansion ASIC and control logic
178 * and 206 MHz CPU clock (4ns ns cycle time, up to 250MHz)
180 unsigned long msc1_sm1_config = (MSC_NonBrst | MSC_16BitStMem
181 | MSC_RdAcc((150 + 100)/4)
182 | MSC_NxtRdAcc((150 + 100)/4)
183 | MSC_Rec(100/4));
184 msc1_sm1_config = 0xFFFC;
185 MSC1 = ((MSC1 & 0xFFFF) /* sm0 */
186 | (msc1_sm1_config << 16));
188 printk(__FUNCTION__ ": setting MSC1=0x%x\n", MSC1);
190 pcmcia_sleeve_flash_map.set_vpp = set_vpp;
191 pcmcia_sleeve_flash_map.size = map_size;
193 pcmcia_sleeve_mtd = cfi_probe(&pcmcia_sleeve_flash_map);
194 if (pcmcia_sleeve_mtd) {
195 pcmcia_sleeve_mtd->module = THIS_MODULE;
196 if ( add_mtd_partitions(pcmcia_sleeve_mtd, pcmcia_sleeve_flash_partitions,
197 NB_OF(pcmcia_sleeve_flash_partitions)))
198 printk(" *** " __FUNCTION__ ": unable to add flash partitions\n");
199 printk(KERN_NOTICE "PCMCIA flash access initialized\n");
200 return 0;
202 return -ENXIO;
203 } else {
204 return -EINVAL;
209 void old_pcmcia_sleeve_detach_flash(void)
211 printk(" ### " __FUNCTION__ "\n");
212 if (pcmcia_sleeve_mtd != NULL) {
213 printk(" ### " __FUNCTION__ " 2\n");
214 del_mtd_partitions(pcmcia_sleeve_mtd);
215 printk(" #### " __FUNCTION__ " 3\n");
216 map_destroy(pcmcia_sleeve_mtd);
217 printk(" ### " __FUNCTION__ " 4\n");
220 EXPORT_SYMBOL(pcmcia_sleeve_attach_flash);
221 EXPORT_SYMBOL(pcmcia_sleeve_detach_flash);