2 * drivers/pcmcia/h3600_generic
4 * PCMCIA implementation routines for H3600 iPAQ standards sleeves
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>
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",
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
);
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
)
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
);
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
)
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
);
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 ",
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
,
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)
131 void *(*cfi_probe
)(void *) = inter_module_get("cfi_probe");
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
);
151 printk(" *** " __FUNCTION__
": unable to add flash device\n");
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)
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");
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
);