diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/mtd/maps/scx200_docflash.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/mtd/maps/scx200_docflash.c')
-rw-r--r-- | drivers/mtd/maps/scx200_docflash.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c new file mode 100644 index 000000000000..0ece3786d6ea --- /dev/null +++ b/drivers/mtd/maps/scx200_docflash.c | |||
@@ -0,0 +1,233 @@ | |||
1 | /* linux/drivers/mtd/maps/scx200_docflash.c | ||
2 | |||
3 | Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> | ||
4 | |||
5 | $Id: scx200_docflash.c,v 1.10 2004/11/28 09:40:40 dwmw2 Exp $ | ||
6 | |||
7 | National Semiconductor SCx200 flash mapped with DOCCS | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/types.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <asm/io.h> | ||
16 | #include <linux/mtd/mtd.h> | ||
17 | #include <linux/mtd/map.h> | ||
18 | #include <linux/mtd/partitions.h> | ||
19 | |||
20 | #include <linux/pci.h> | ||
21 | #include <linux/scx200.h> | ||
22 | |||
23 | #define NAME "scx200_docflash" | ||
24 | |||
25 | MODULE_AUTHOR("Christer Weinigel <wingel@hack.org>"); | ||
26 | MODULE_DESCRIPTION("NatSemi SCx200 DOCCS Flash Driver"); | ||
27 | MODULE_LICENSE("GPL"); | ||
28 | |||
29 | static int probe = 0; /* Don't autoprobe */ | ||
30 | static unsigned size = 0x1000000; /* 16 MiB the whole ISA address space */ | ||
31 | static unsigned width = 8; /* Default to 8 bits wide */ | ||
32 | static char *flashtype = "cfi_probe"; | ||
33 | |||
34 | module_param(probe, int, 0); | ||
35 | MODULE_PARM_DESC(probe, "Probe for a BIOS mapping"); | ||
36 | module_param(size, int, 0); | ||
37 | MODULE_PARM_DESC(size, "Size of the flash mapping"); | ||
38 | module_param(width, int, 0); | ||
39 | MODULE_PARM_DESC(width, "Data width of the flash mapping (8/16)"); | ||
40 | module_param(flashtype, charp, 0); | ||
41 | MODULE_PARM_DESC(flashtype, "Type of MTD probe to do"); | ||
42 | |||
43 | static struct resource docmem = { | ||
44 | .flags = IORESOURCE_MEM, | ||
45 | .name = "NatSemi SCx200 DOCCS Flash", | ||
46 | }; | ||
47 | |||
48 | static struct mtd_info *mymtd; | ||
49 | |||
50 | #ifdef CONFIG_MTD_PARTITIONS | ||
51 | static struct mtd_partition partition_info[] = { | ||
52 | { | ||
53 | .name = "DOCCS Boot kernel", | ||
54 | .offset = 0, | ||
55 | .size = 0xc0000 | ||
56 | }, | ||
57 | { | ||
58 | .name = "DOCCS Low BIOS", | ||
59 | .offset = 0xc0000, | ||
60 | .size = 0x40000 | ||
61 | }, | ||
62 | { | ||
63 | .name = "DOCCS File system", | ||
64 | .offset = 0x100000, | ||
65 | .size = ~0 /* calculate from flash size */ | ||
66 | }, | ||
67 | { | ||
68 | .name = "DOCCS High BIOS", | ||
69 | .offset = ~0, /* calculate from flash size */ | ||
70 | .size = 0x80000 | ||
71 | }, | ||
72 | }; | ||
73 | #define NUM_PARTITIONS (sizeof(partition_info)/sizeof(partition_info[0])) | ||
74 | #endif | ||
75 | |||
76 | |||
77 | static struct map_info scx200_docflash_map = { | ||
78 | .name = "NatSemi SCx200 DOCCS Flash", | ||
79 | }; | ||
80 | |||
81 | static int __init init_scx200_docflash(void) | ||
82 | { | ||
83 | unsigned u; | ||
84 | unsigned base; | ||
85 | unsigned ctrl; | ||
86 | unsigned pmr; | ||
87 | struct pci_dev *bridge; | ||
88 | |||
89 | printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n"); | ||
90 | |||
91 | if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, | ||
92 | PCI_DEVICE_ID_NS_SCx200_BRIDGE, | ||
93 | NULL)) == NULL) | ||
94 | return -ENODEV; | ||
95 | |||
96 | /* check that we have found the configuration block */ | ||
97 | if (!scx200_cb_present()) | ||
98 | return -ENODEV; | ||
99 | |||
100 | if (probe) { | ||
101 | /* Try to use the present flash mapping if any */ | ||
102 | pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base); | ||
103 | pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl); | ||
104 | pmr = inl(scx200_cb_base + SCx200_PMR); | ||
105 | |||
106 | if (base == 0 | ||
107 | || (ctrl & 0x07000000) != 0x07000000 | ||
108 | || (ctrl & 0x0007ffff) == 0) | ||
109 | return -ENODEV; | ||
110 | |||
111 | size = ((ctrl&0x1fff)<<13) + (1<<13); | ||
112 | |||
113 | for (u = size; u > 1; u >>= 1) | ||
114 | ; | ||
115 | if (u != 1) | ||
116 | return -ENODEV; | ||
117 | |||
118 | if (pmr & (1<<6)) | ||
119 | width = 16; | ||
120 | else | ||
121 | width = 8; | ||
122 | |||
123 | docmem.start = base; | ||
124 | docmem.end = base + size; | ||
125 | |||
126 | if (request_resource(&iomem_resource, &docmem)) { | ||
127 | printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n"); | ||
128 | return -ENOMEM; | ||
129 | } | ||
130 | } else { | ||
131 | for (u = size; u > 1; u >>= 1) | ||
132 | ; | ||
133 | if (u != 1) { | ||
134 | printk(KERN_ERR NAME ": invalid size for flash mapping\n"); | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | if (width != 8 && width != 16) { | ||
139 | printk(KERN_ERR NAME ": invalid bus width for flash mapping\n"); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | if (allocate_resource(&iomem_resource, &docmem, | ||
144 | size, | ||
145 | 0xc0000000, 0xffffffff, | ||
146 | size, NULL, NULL)) { | ||
147 | printk(KERN_ERR NAME ": unable to allocate memory for flash mapping\n"); | ||
148 | return -ENOMEM; | ||
149 | } | ||
150 | |||
151 | ctrl = 0x07000000 | ((size-1) >> 13); | ||
152 | |||
153 | printk(KERN_INFO "DOCCS BASE=0x%08lx, CTRL=0x%08lx\n", (long)docmem.start, (long)ctrl); | ||
154 | |||
155 | pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start); | ||
156 | pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl); | ||
157 | pmr = inl(scx200_cb_base + SCx200_PMR); | ||
158 | |||
159 | if (width == 8) { | ||
160 | pmr &= ~(1<<6); | ||
161 | } else { | ||
162 | pmr |= (1<<6); | ||
163 | } | ||
164 | outl(pmr, scx200_cb_base + SCx200_PMR); | ||
165 | } | ||
166 | |||
167 | printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n", | ||
168 | docmem.start, docmem.end, width); | ||
169 | |||
170 | scx200_docflash_map.size = size; | ||
171 | if (width == 8) | ||
172 | scx200_docflash_map.bankwidth = 1; | ||
173 | else | ||
174 | scx200_docflash_map.bankwidth = 2; | ||
175 | |||
176 | simple_map_init(&scx200_docflash_map); | ||
177 | |||
178 | scx200_docflash_map.phys = docmem.start; | ||
179 | scx200_docflash_map.virt = ioremap(docmem.start, scx200_docflash_map.size); | ||
180 | if (!scx200_docflash_map.virt) { | ||
181 | printk(KERN_ERR NAME ": failed to ioremap the flash\n"); | ||
182 | release_resource(&docmem); | ||
183 | return -EIO; | ||
184 | } | ||
185 | |||
186 | mymtd = do_map_probe(flashtype, &scx200_docflash_map); | ||
187 | if (!mymtd) { | ||
188 | printk(KERN_ERR NAME ": unable to detect flash\n"); | ||
189 | iounmap(scx200_docflash_map.virt); | ||
190 | release_resource(&docmem); | ||
191 | return -ENXIO; | ||
192 | } | ||
193 | |||
194 | if (size < mymtd->size) | ||
195 | printk(KERN_WARNING NAME ": warning, flash mapping is smaller than flash size\n"); | ||
196 | |||
197 | mymtd->owner = THIS_MODULE; | ||
198 | |||
199 | #ifdef CONFIG_MTD_PARTITIONS | ||
200 | partition_info[3].offset = mymtd->size-partition_info[3].size; | ||
201 | partition_info[2].size = partition_info[3].offset-partition_info[2].offset; | ||
202 | add_mtd_partitions(mymtd, partition_info, NUM_PARTITIONS); | ||
203 | #else | ||
204 | add_mtd_device(mymtd); | ||
205 | #endif | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static void __exit cleanup_scx200_docflash(void) | ||
210 | { | ||
211 | if (mymtd) { | ||
212 | #ifdef CONFIG_MTD_PARTITIONS | ||
213 | del_mtd_partitions(mymtd); | ||
214 | #else | ||
215 | del_mtd_device(mymtd); | ||
216 | #endif | ||
217 | map_destroy(mymtd); | ||
218 | } | ||
219 | if (scx200_docflash_map.virt) { | ||
220 | iounmap(scx200_docflash_map.virt); | ||
221 | release_resource(&docmem); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | module_init(init_scx200_docflash); | ||
226 | module_exit(cleanup_scx200_docflash); | ||
227 | |||
228 | /* | ||
229 | Local variables: | ||
230 | compile-command: "make -k -C ../../.. SUBDIRS=drivers/mtd/maps modules" | ||
231 | c-basic-offset: 8 | ||
232 | End: | ||
233 | */ | ||