Fix location to the ebtables modules (#3855)
[openwrt/svn-archive/archive.git] / target / linux / olpc / patches / 100-olpc.patch
1 Index: linux-2.6.23.17/arch/i386/Kconfig
2 ===================================================================
3 --- linux-2.6.23.17.orig/arch/i386/Kconfig
4 +++ linux-2.6.23.17/arch/i386/Kconfig
5 @@ -796,6 +796,15 @@ config SECCOMP
6
7 If unsure, say Y. Only embedded should say N here.
8
9 +config VGA_NOPROBE
10 + bool "Don't probe VGA at boot" if EMBEDDED
11 + default n
12 + help
13 + Saying Y here will cause the kernel to not probe VGA at boot time.
14 + This will break everything that depends on the probed screen
15 + data. Say N here unless you are absolutely sure this is what you
16 + want.
17 +
18 source kernel/Kconfig.hz
19
20 config KEXEC
21 @@ -1120,6 +1129,9 @@ config PCI_GODIRECT
22 config PCI_GOANY
23 bool "Any"
24
25 +config PCI_GOOLPC
26 + bool "OLPC"
27 +
28 endchoice
29
30 config PCI_BIOS
31 @@ -1129,7 +1141,7 @@ config PCI_BIOS
32
33 config PCI_DIRECT
34 bool
35 - depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
36 + depends on PCI && ((PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS)
37 default y
38
39 config PCI_MMCONFIG
40 @@ -1137,6 +1149,11 @@ config PCI_MMCONFIG
41 depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
42 default y
43
44 +config PCI_OLPC
45 + bool
46 + depends on PCI && PCI_GOOLPC
47 + default y
48 +
49 source "drivers/pci/pcie/Kconfig"
50
51 source "drivers/pci/Kconfig"
52 @@ -1206,10 +1223,43 @@ config SCx200HR_TIMER
53 processor goes idle (as is done by the scheduler). The
54 other workaround is idle=poll boot option.
55
56 +config GEODE_MFGPT_TIMER
57 + bool "Geode Multi-Function General Purpose Timer (mfgpt) Support"
58 + depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS
59 + default y
60 + help
61 + This driver provides a clock event source based on the MFGPT
62 + timer(s) in the CS5535 and CS5536 companion chip for the geode.
63 + MFGPTs have a better resolution and max interval than the
64 + generic PIT, and are suitable for use as high-res timers.
65 +
66 config K8_NB
67 def_bool y
68 depends on AGP_AMD64
69
70 +config OLPC
71 + bool "OLPC Support"
72 + default n
73 + help
74 + Add support for detecting the unique features of the OLPC
75 + Childrens Machine
76 +
77 +config OLPC_PM
78 + tristate "OLPC power management support"
79 + default y
80 + depends on OLPC
81 + help
82 + Add support for the Geode power management facilities on the
83 + OLPC Childrens Machine
84 +
85 +config OPEN_FIRMWARE
86 + bool "Support for Open Firmware"
87 + default y if OLPC
88 + help
89 + This option adds support for the implementation of Open Firmware
90 + that is used on the OLPC Children's Machine.
91 + If unsure, say N here.
92 +
93 source "drivers/pcmcia/Kconfig"
94
95 source "drivers/pci/hotplug/Kconfig"
96 Index: linux-2.6.23.17/arch/i386/kernel/Makefile
97 ===================================================================
98 --- linux-2.6.23.17.orig/arch/i386/kernel/Makefile
99 +++ linux-2.6.23.17/arch/i386/kernel/Makefile
100 @@ -39,13 +39,17 @@ obj-$(CONFIG_VM86) += vm86.o
101 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
102 obj-$(CONFIG_HPET_TIMER) += hpet.o
103 obj-$(CONFIG_K8_NB) += k8.o
104 -obj-$(CONFIG_MGEODE_LX) += geode.o
105 +obj-$(CONFIG_MGEODE_LX) += geode.o mfgpt.o
106
107 obj-$(CONFIG_VMI) += vmi.o vmiclock.o
108 obj-$(CONFIG_PARAVIRT) += paravirt.o
109 obj-y += pcspeaker.o
110
111 obj-$(CONFIG_SCx200) += scx200.o
112 +obj-$(CONFIG_OLPC) += olpc.o
113 +obj-$(CONFIG_OLPC_PM) += olpc-pm.o olpc-wakeup.o
114 +obj-$(CONFIG_OPEN_FIRMWARE) += ofw.o
115 +obj-$(CONFIG_PROMFS_FS) += prom.o
116
117 # vsyscall.o contains the vsyscall DSO images as __initdata.
118 # We must build both images before we can assemble it.
119 Index: linux-2.6.23.17/arch/i386/kernel/geode.c
120 ===================================================================
121 --- linux-2.6.23.17.orig/arch/i386/kernel/geode.c
122 +++ linux-2.6.23.17/arch/i386/kernel/geode.c
123 @@ -145,10 +145,14 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event
124
125 static int __init geode_southbridge_init(void)
126 {
127 + int timers;
128 +
129 if (!is_geode())
130 return -ENODEV;
131
132 init_lbars();
133 + timers = geode_mfgpt_detect();
134 + printk(KERN_INFO "geode-mfgpt: %d timers available.\n", timers);
135 return 0;
136 }
137
138 Index: linux-2.6.23.17/arch/i386/kernel/head.S
139 ===================================================================
140 --- linux-2.6.23.17.orig/arch/i386/kernel/head.S
141 +++ linux-2.6.23.17/arch/i386/kernel/head.S
142 @@ -117,8 +117,34 @@ ENTRY(startup_32)
143 movl $(COMMAND_LINE_SIZE/4),%ecx
144 rep
145 movsl
146 +
147 +#ifdef CONFIG_OPEN_FIRMWARE
148 +/*
149 + * If Open Firmware booted us, save the OFW client interface callback address
150 + * and preserve the OFW page mappings by priming the kernel's new page
151 + * directory area with a copy of the OFW page directory. That lets OFW stay
152 + * resident in high memory (high in both the virtual and physical spaces)
153 + * for at least long enough to copy out the device tree.
154 + */
155 1:
156 + movl $(boot_params - __PAGE_OFFSET + OFW_INFO_OFFSET), %ebp
157 + cmpl $0x2057464F, (%ebp) /* Magic number "OFW " */
158 + jne 1f
159 +
160 + mov 0x8(%ebp), %eax /* Save callback address */
161 + mov %eax, call_firmware - __PAGE_OFFSET
162 +
163 + /* Copy the OFW pdir into swapper_pg_dir */
164 + movl %esi, %edx /* save %esi */
165 + movl $(swapper_pg_dir - __PAGE_OFFSET), %edi
166 + movl %cr3, %esi /* Source is current pg_dir base address */
167 + movl $1024, %ecx /* Number of page directory entries */
168 + rep
169 + movsl
170 + movl %edx, %esi /* restore %esi */
171 +#endif
172
173 +1:
174 /*
175 * Initialize page tables. This creates a PDE and a set of page
176 * tables, which are located immediately beyond _end. The variable
177 @@ -129,6 +155,7 @@ ENTRY(startup_32)
178 * Warning: don't use %esi or the stack in this code. However, %esp
179 * can be used as a GPR if you really need it...
180 */
181 +
182 page_pde_offset = (__PAGE_OFFSET >> 20);
183
184 movl $(pg0 - __PAGE_OFFSET), %edi
185 Index: linux-2.6.23.17/arch/i386/kernel/setup.c
186 ===================================================================
187 --- linux-2.6.23.17.orig/arch/i386/kernel/setup.c
188 +++ linux-2.6.23.17/arch/i386/kernel/setup.c
189 @@ -362,8 +362,10 @@ void __init zone_sizes_init(void)
190 {
191 unsigned long max_zone_pfns[MAX_NR_ZONES];
192 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
193 +#ifdef CONFIG_ZONE_DMA
194 max_zone_pfns[ZONE_DMA] =
195 virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
196 +#endif
197 max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
198 #ifdef CONFIG_HIGHMEM
199 max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
200 @@ -428,6 +430,9 @@ void __init setup_bootmem_allocator(void
201 */
202 acpi_reserve_bootmem();
203 #endif
204 +#ifdef CONFIG_OLPC_PM
205 + reserve_bootmem(0xf0000, PAGE_SIZE);
206 +#endif
207 #ifdef CONFIG_X86_FIND_SMP_CONFIG
208 /*
209 * Find and reserve possible boot-time SMP configuration:
210 Index: linux-2.6.23.17/arch/i386/pci/Makefile
211 ===================================================================
212 --- linux-2.6.23.17.orig/arch/i386/pci/Makefile
213 +++ linux-2.6.23.17/arch/i386/pci/Makefile
214 @@ -3,6 +3,7 @@ obj-y := i386.o init.o
215 obj-$(CONFIG_PCI_BIOS) += pcbios.o
216 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
217 obj-$(CONFIG_PCI_DIRECT) += direct.o
218 +obj-$(CONFIG_PCI_OLPC) += olpc.o
219
220 pci-y := fixup.o
221 pci-$(CONFIG_ACPI) += acpi.o
222 Index: linux-2.6.23.17/arch/i386/pci/init.c
223 ===================================================================
224 --- linux-2.6.23.17.orig/arch/i386/pci/init.c
225 +++ linux-2.6.23.17/arch/i386/pci/init.c
226 @@ -14,6 +14,9 @@ static __init int pci_access_init(void)
227 #ifdef CONFIG_PCI_MMCONFIG
228 pci_mmcfg_init(type);
229 #endif
230 +#ifdef CONFIG_PCI_OLPC
231 + pci_olpc_init();
232 +#endif
233 if (raw_pci_ops)
234 return 0;
235 #ifdef CONFIG_PCI_BIOS
236 Index: linux-2.6.23.17/arch/i386/pci/pci.h
237 ===================================================================
238 --- linux-2.6.23.17.orig/arch/i386/pci/pci.h
239 +++ linux-2.6.23.17/arch/i386/pci/pci.h
240 @@ -93,6 +93,7 @@ extern void pci_direct_init(int type);
241 extern void pci_pcbios_init(void);
242 extern void pci_mmcfg_init(int type);
243 extern void pcibios_sort(void);
244 +extern void pci_olpc_init(void);
245
246 /* pci-mmconfig.c */
247
248 Index: linux-2.6.23.17/drivers/Makefile
249 ===================================================================
250 --- linux-2.6.23.17.orig/drivers/Makefile
251 +++ linux-2.6.23.17/drivers/Makefile
252 @@ -23,6 +23,8 @@ obj-y += char/
253
254 obj-$(CONFIG_CONNECTOR) += connector/
255
256 +obj-$(CONFIG_SYSPROF) += sysprof/
257 +
258 # i810fb and intelfb depend on char/agp/
259 obj-$(CONFIG_FB_I810) += video/i810/
260 obj-$(CONFIG_FB_INTEL) += video/intelfb/
261 Index: linux-2.6.23.17/drivers/char/vt_ioctl.c
262 ===================================================================
263 --- linux-2.6.23.17.orig/drivers/char/vt_ioctl.c
264 +++ linux-2.6.23.17/drivers/char/vt_ioctl.c
265 @@ -37,6 +37,9 @@
266 char vt_dont_switch;
267 extern struct tty_driver *console_driver;
268
269 +/* Add a notifier chain to inform drivers of a VT_TEXT/VT_GRAPHICS switch */
270 +RAW_NOTIFIER_HEAD(console_notifier_list);
271 +
272 #define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
273 #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
274
275 @@ -491,6 +494,14 @@ int vt_ioctl(struct tty_struct *tty, str
276 vc->vc_mode = (unsigned char) arg;
277 if (console != fg_console)
278 return 0;
279 +
280 + /* Notify listeners if the current fg_console has switched */
281 +
282 + raw_notifier_call_chain(&console_notifier_list,
283 + (arg == KD_TEXT) ?
284 + CONSOLE_EVENT_SWITCH_TEXT :
285 + CONSOLE_EVENT_SWITCH_GRAPHICS, 0);
286 +
287 /*
288 * explicitly blank/unblank the screen if switching modes
289 */
290 Index: linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
291 ===================================================================
292 --- linux-2.6.23.17.orig/drivers/i2c/busses/scx200_acb.c
293 +++ linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
294 @@ -46,6 +46,10 @@ static int base[MAX_DEVICES] = { 0x820,
295 module_param_array(base, int, NULL, 0);
296 MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
297
298 +static unsigned int smbclk = 0x70;
299 +module_param(smbclk, uint, 0);
300 +MODULE_PARM_DESC(smbclk, "Specify the SMB_CLK value");
301 +
302 #define POLL_TIMEOUT (HZ/5)
303
304 enum scx200_acb_state {
305 @@ -108,6 +112,7 @@ struct scx200_acb_iface {
306 #define ACBADDR (iface->base + 4)
307 #define ACBCTL2 (iface->base + 5)
308 #define ACBCTL2_ENABLE 0x01
309 +#define ACBCTL3 (iface->base + 6)
310
311 /************************************************************************/
312
313 @@ -392,11 +397,13 @@ static __init int scx200_acb_probe(struc
314 {
315 u8 val;
316
317 - /* Disable the ACCESS.bus device and Configure the SCL
318 - frequency: 16 clock cycles */
319 - outb(0x70, ACBCTL2);
320 + /* Disable the ACCESS.bus device and Configure the SCL */
321 +
322 + outb((smbclk & 0x7F) << 1, ACBCTL2);
323 +
324 + outb((smbclk >> 7) & 0xFF, ACBCTL3);
325
326 - if (inb(ACBCTL2) != 0x70) {
327 + if (inb(ACBCTL2) != ((smbclk & 0x7F) << 1)) {
328 pr_debug(NAME ": ACBCTL2 readback failed\n");
329 return -ENXIO;
330 }
331 Index: linux-2.6.23.17/drivers/input/keyboard/atkbd.c
332 ===================================================================
333 --- linux-2.6.23.17.orig/drivers/input/keyboard/atkbd.c
334 +++ linux-2.6.23.17/drivers/input/keyboard/atkbd.c
335 @@ -63,12 +63,25 @@ static int atkbd_extra;
336 module_param_named(extra, atkbd_extra, bool, 0);
337 MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
338
339 +#define ATKBD_KEY_UNKNOWN 0
340 +#define ATKBD_KEY_NULL 0xFF0000FF
341 +
342 +#define ATKBD_SCR_1 0xFF0000FE
343 +#define ATKBD_SCR_2 0xFF0000FD
344 +#define ATKBD_SCR_4 0xFF0000FC
345 +#define ATKBD_SCR_8 0xFF0000FB
346 +#define ATKBD_SCR_CLICK 0xFF0000FA
347 +#define ATKBD_SCR_LEFT 0xFF0000F9
348 +#define ATKBD_SCR_RIGHT 0xFF0000F8
349 +
350 +#define ATKBD_SPECIAL 0xFF0000F8
351 +
352 /*
353 * Scancode to keycode tables. These are just the default setting, and
354 * are loadable via an userland utility.
355 */
356
357 -static unsigned char atkbd_set2_keycode[512] = {
358 +static unsigned int atkbd_set2_keycode[512] = {
359
360 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
361
362 @@ -87,11 +100,17 @@ static unsigned char atkbd_set2_keycode[
363 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
364
365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
366 - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
367 +
368 + 217,100,ATKBD_KEY_NULL, 0, 97,165, 0, 0,
369 + 156, 0, 0, 0, 0, 0, 0,125,
370 +
371 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
372 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
373 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
374 - 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
375 +
376 + 226, 0, 0, 0, 0, 0, 0, 0,
377 + 0,ATKBD_KEY_NULL, 96, 0, 0, 0,143, 0,
378 +
379 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
380 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
381
382 @@ -150,19 +169,6 @@ static unsigned char atkbd_unxlate_table
383 #define ATKBD_RET_HANGEUL 0xf2
384 #define ATKBD_RET_ERR 0xff
385
386 -#define ATKBD_KEY_UNKNOWN 0
387 -#define ATKBD_KEY_NULL 255
388 -
389 -#define ATKBD_SCR_1 254
390 -#define ATKBD_SCR_2 253
391 -#define ATKBD_SCR_4 252
392 -#define ATKBD_SCR_8 251
393 -#define ATKBD_SCR_CLICK 250
394 -#define ATKBD_SCR_LEFT 249
395 -#define ATKBD_SCR_RIGHT 248
396 -
397 -#define ATKBD_SPECIAL 248
398 -
399 #define ATKBD_LED_EVENT_BIT 0
400 #define ATKBD_REP_EVENT_BIT 1
401
402 @@ -174,7 +180,7 @@ static unsigned char atkbd_unxlate_table
403 #define ATKBD_XL_HANJA 0x20
404
405 static struct {
406 - unsigned char keycode;
407 + unsigned int keycode;
408 unsigned char set2;
409 } atkbd_scroll_keys[] = {
410 { ATKBD_SCR_1, 0xc5 },
411 @@ -200,7 +206,7 @@ struct atkbd {
412 char phys[32];
413
414 unsigned short id;
415 - unsigned char keycode[512];
416 + unsigned int keycode[512];
417 unsigned char set;
418 unsigned char translated;
419 unsigned char extra;
420 @@ -351,7 +357,7 @@ static irqreturn_t atkbd_interrupt(struc
421 unsigned int code = data;
422 int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
423 int value;
424 - unsigned char keycode;
425 + unsigned int keycode;
426
427 #ifdef ATKBD_DEBUG
428 printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
429 @@ -856,9 +862,11 @@ static void atkbd_set_keycode_table(stru
430 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
431 }
432 } else if (atkbd->set == 3) {
433 - memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
434 + for (i = 0; i < ARRAY_SIZE(atkbd_set3_keycode); i++)
435 + atkbd->keycode[i] = atkbd_set3_keycode[i];
436 } else {
437 - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
438 + for (i = 0; i < ARRAY_SIZE(atkbd_set2_keycode); i++)
439 + atkbd->keycode[i] = atkbd_set2_keycode[i];
440
441 if (atkbd->scroll)
442 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
443 @@ -925,8 +933,8 @@ static void atkbd_set_device_attrs(struc
444 }
445
446 input_dev->keycode = atkbd->keycode;
447 - input_dev->keycodesize = sizeof(unsigned char);
448 - input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
449 + input_dev->keycodesize = sizeof(unsigned int);
450 + input_dev->keycodemax = ARRAY_SIZE(atkbd->keycode);
451
452 for (i = 0; i < 512; i++)
453 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
454 @@ -1017,6 +1025,10 @@ static int atkbd_connect(struct serio *s
455 return err;
456 }
457
458 +#ifdef CONFIG_OLPC
459 +#include <asm/olpc.h>
460 +#endif
461 +
462 /*
463 * atkbd_reconnect() tries to restore keyboard into a sane state and is
464 * most likely called on resume.
465 @@ -1027,6 +1039,12 @@ static int atkbd_reconnect(struct serio
466 struct atkbd *atkbd = serio_get_drvdata(serio);
467 struct serio_driver *drv = serio->drv;
468
469 +#ifdef CONFIG_OLPC
470 + if (olpc_rev_after(OLPC_REV_B2))
471 + if (serio->dev.power.power_state.event != PM_EVENT_ON)
472 + return 0;
473 +#endif
474 +
475 if (!atkbd || !drv) {
476 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
477 return -1;
478 Index: linux-2.6.23.17/drivers/input/mouse/Kconfig
479 ===================================================================
480 --- linux-2.6.23.17.orig/drivers/input/mouse/Kconfig
481 +++ linux-2.6.23.17/drivers/input/mouse/Kconfig
482 @@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
483
484 If unsure, say N.
485
486 +config MOUSE_PS2_OLPC
487 + bool "OLPC PS/2 mouse protocol extension" if EMBEDDED
488 + default n
489 + depends on MOUSE_PS2 && OLPC
490 + ---help---
491 + Say Y here if you have an OLPC PS/2 touchpad connected to
492 + your system.
493 +
494 + If unsure, say N.
495 +
496 config MOUSE_SERIAL
497 tristate "Serial mouse"
498 select SERIO
499 Index: linux-2.6.23.17/drivers/input/mouse/Makefile
500 ===================================================================
501 --- linux-2.6.23.17.orig/drivers/input/mouse/Makefile
502 +++ linux-2.6.23.17/drivers/input/mouse/Makefile
503 @@ -24,3 +24,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) +=
504 psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
505 psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
506 psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
507 +psmouse-$(CONFIG_MOUSE_PS2_OLPC) += olpc.o
508 Index: linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
509 ===================================================================
510 --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse-base.c
511 +++ linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
512 @@ -26,6 +26,7 @@
513 #include "synaptics.h"
514 #include "logips2pp.h"
515 #include "alps.h"
516 +#include "olpc.h"
517 #include "lifebook.h"
518 #include "trackpoint.h"
519 #include "touchkit_ps2.h"
520 @@ -103,7 +104,7 @@ static struct attribute_group psmouse_at
521 */
522 static DEFINE_MUTEX(psmouse_mutex);
523
524 -static struct workqueue_struct *kpsmoused_wq;
525 +struct workqueue_struct *kpsmoused_wq;
526
527 struct psmouse_protocol {
528 enum psmouse_type type;
529 @@ -320,7 +321,7 @@ static irqreturn_t psmouse_interrupt(str
530 goto out;
531 }
532
533 - if (psmouse->packet[1] == PSMOUSE_RET_ID) {
534 + if (psmouse->packet[1] == PSMOUSE_RET_ID || psmouse->packet[1] == PSMOUSE_RET_BAT) {
535 __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
536 serio_reconnect(serio);
537 goto out;
538 @@ -631,8 +632,21 @@ static int psmouse_extensions(struct psm
539 }
540 }
541
542 +/*
543 + * Try OLPC touchpad.
544 + */
545 if (max_proto > PSMOUSE_IMEX) {
546 + if (olpc_detect(psmouse, set_properties) == 0) {
547 + if (!set_properties || olpc_init(psmouse) == 0)
548 + return PSMOUSE_OLPC;
549 +/*
550 + * Init failed, try basic relative protocols
551 + */
552 + max_proto = PSMOUSE_IMEX;
553 + }
554 + }
555
556 + if (max_proto > PSMOUSE_IMEX) {
557 if (genius_detect(psmouse, set_properties) == 0)
558 return PSMOUSE_GENPS;
559
560 @@ -762,6 +776,14 @@ static const struct psmouse_protocol psm
561 .detect = touchkit_ps2_detect,
562 },
563 #endif
564 +#ifdef CONFIG_MOUSE_PS2_OLPC
565 + {
566 + .type = PSMOUSE_OLPC,
567 + .name = "OLPC",
568 + .alias = "olpc",
569 + .detect = olpc_detect,
570 + },
571 +#endif
572 {
573 .type = PSMOUSE_CORTRON,
574 .name = "CortronPS/2",
575 Index: linux-2.6.23.17/drivers/input/mouse/psmouse.h
576 ===================================================================
577 --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse.h
578 +++ linux-2.6.23.17/drivers/input/mouse/psmouse.h
579 @@ -89,6 +89,7 @@ enum psmouse_type {
580 PSMOUSE_TRACKPOINT,
581 PSMOUSE_TOUCHKIT_PS2,
582 PSMOUSE_CORTRON,
583 + PSMOUSE_OLPC,
584 PSMOUSE_AUTO /* This one should always be last */
585 };
586
587 @@ -96,6 +97,7 @@ int psmouse_sliced_command(struct psmous
588 int psmouse_reset(struct psmouse *psmouse);
589 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
590
591 +extern struct workqueue_struct *kpsmoused_wq;
592
593 struct psmouse_attribute {
594 struct device_attribute dattr;
595 Index: linux-2.6.23.17/drivers/input/serio/i8042.c
596 ===================================================================
597 --- linux-2.6.23.17.orig/drivers/input/serio/i8042.c
598 +++ linux-2.6.23.17/drivers/input/serio/i8042.c
599 @@ -868,6 +868,11 @@ static long i8042_panic_blink(long count
600 #undef DELAY
601
602 #ifdef CONFIG_PM
603 +
604 +#ifdef CONFIG_OLPC
605 +#include <asm/olpc.h>
606 +#endif
607 +
608 /*
609 * Here we try to restore the original BIOS settings. We only want to
610 * do that once, when we really suspend, not when we taking memory
611 @@ -878,8 +883,15 @@ static long i8042_panic_blink(long count
612 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
613 {
614 if (dev->dev.power.power_state.event != state.event) {
615 +#ifdef CONFIG_OLPC
616 + /* Anything newer than B2 remains powered; no reset needed */
617 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
618 +#endif
619 if (state.event == PM_EVENT_SUSPEND)
620 i8042_controller_reset();
621 +#ifdef CONFIG_OLPC
622 + }
623 +#endif
624
625 dev->dev.power.power_state = state;
626 }
627 @@ -902,9 +914,15 @@ static int i8042_resume(struct platform_
628 if (dev->dev.power.power_state.event == PM_EVENT_ON)
629 return 0;
630
631 +#ifdef CONFIG_OLPC
632 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
633 +#endif
634 error = i8042_controller_check();
635 if (error)
636 return error;
637 +#ifdef CONFIG_OLPC
638 + }
639 +#endif
640
641 error = i8042_controller_selftest();
642 if (error)
643 Index: linux-2.6.23.17/drivers/input/serio/serio.c
644 ===================================================================
645 --- linux-2.6.23.17.orig/drivers/input/serio/serio.c
646 +++ linux-2.6.23.17/drivers/input/serio/serio.c
647 @@ -916,11 +916,22 @@ static int serio_uevent(struct device *d
648 #endif /* CONFIG_HOTPLUG */
649
650 #ifdef CONFIG_PM
651 +
652 +#ifdef CONFIG_OLPC
653 +#include <asm/olpc.h>
654 +#endif
655 +
656 static int serio_suspend(struct device *dev, pm_message_t state)
657 {
658 if (dev->power.power_state.event != state.event) {
659 +#ifdef CONFIG_OLPC
660 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
661 +#endif
662 if (state.event == PM_EVENT_SUSPEND)
663 serio_cleanup(to_serio_port(dev));
664 +#ifdef CONFIG_OLPC
665 + }
666 +#endif
667
668 dev->power.power_state = state;
669 }
670 Index: linux-2.6.23.17/drivers/media/video/cafe_ccic.c
671 ===================================================================
672 --- linux-2.6.23.17.orig/drivers/media/video/cafe_ccic.c
673 +++ linux-2.6.23.17/drivers/media/video/cafe_ccic.c
674 @@ -63,13 +63,13 @@ MODULE_SUPPORTED_DEVICE("Video");
675 */
676
677 #define MAX_DMA_BUFS 3
678 -static int alloc_bufs_at_load = 0;
679 -module_param(alloc_bufs_at_load, bool, 0444);
680 -MODULE_PARM_DESC(alloc_bufs_at_load,
681 - "Non-zero value causes DMA buffers to be allocated at module "
682 - "load time. This increases the chances of successfully getting "
683 - "those buffers, but at the cost of nailing down the memory from "
684 - "the outset.");
685 +static int alloc_bufs_at_read = 0;
686 +module_param(alloc_bufs_at_read, bool, 0444);
687 +MODULE_PARM_DESC(alloc_bufs_at_read,
688 + "Non-zero value causes DMA buffers to be allocated when the "
689 + "video capture device is read, rather than at module load "
690 + "time. This saves memory, but decreases the chances of "
691 + "successfully getting those buffers.");
692
693 static int n_dma_bufs = 3;
694 module_param(n_dma_bufs, uint, 0644);
695 @@ -370,6 +370,10 @@ static int cafe_smbus_write_data(struct
696 rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
697 cafe_reg_write(cam, REG_TWSIC1, rval);
698 spin_unlock_irqrestore(&cam->dev_lock, flags);
699 + mdelay(2); /* It'll probably take about 900µs anyway, and the
700 + CAFÉ is apparently quite sensitive to being poked
701 + at this point. If we can work out precisely what's
702 + going on and reduce this delay, it would be nice. */
703
704 /*
705 * Time to wait for the write to complete. THIS IS A RACY
706 @@ -1503,7 +1507,7 @@ static int cafe_v4l_release(struct inode
707 }
708 if (cam->users == 0) {
709 cafe_ctlr_power_down(cam);
710 - if (! alloc_bufs_at_load)
711 + if (alloc_bufs_at_read)
712 cafe_free_dma_bufs(cam);
713 }
714 mutex_unlock(&cam->s_mutex);
715 @@ -2162,7 +2166,7 @@ static int cafe_pci_probe(struct pci_dev
716 /*
717 * If so requested, try to get our DMA buffers now.
718 */
719 - if (alloc_bufs_at_load) {
720 + if (!alloc_bufs_at_read) {
721 if (cafe_alloc_dma_bufs(cam, 1))
722 cam_warn(cam, "Unable to alloc DMA buffers at load"
723 " will try again later.");
724 Index: linux-2.6.23.17/drivers/misc/Kconfig
725 ===================================================================
726 --- linux-2.6.23.17.orig/drivers/misc/Kconfig
727 +++ linux-2.6.23.17/drivers/misc/Kconfig
728 @@ -202,5 +202,10 @@ config THINKPAD_ACPI_BAY
729
730 If you are not sure, say Y here.
731
732 +config EEPROM_93CX6
733 + tristate "EEPROM 93CX6 support"
734 + ---help---
735 + This is a driver for the EEPROM chipsets 93c46 and 93c66.
736 + The driver supports both read as well as write commands.
737
738 endif # MISC_DEVICES
739 Index: linux-2.6.23.17/drivers/mmc/host/sdhci.c
740 ===================================================================
741 --- linux-2.6.23.17.orig/drivers/mmc/host/sdhci.c
742 +++ linux-2.6.23.17/drivers/mmc/host/sdhci.c
743 @@ -411,6 +411,12 @@ static void sdhci_prepare_data(struct sd
744 break;
745 }
746
747 + /*
748 + * There's an off-by-one error in the hw that we need to
749 + * compensate for.
750 + */
751 + count++;
752 +
753 if (count >= 0xF) {
754 printk(KERN_WARNING "%s: Too large timeout requested!\n",
755 mmc_hostname(host->mmc));
756 @@ -676,19 +682,17 @@ static void sdhci_set_power(struct sdhci
757 if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
758 writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
759
760 - pwr = SDHCI_POWER_ON;
761 -
762 switch (1 << power) {
763 case MMC_VDD_165_195:
764 - pwr |= SDHCI_POWER_180;
765 + pwr = SDHCI_POWER_180;
766 break;
767 case MMC_VDD_29_30:
768 case MMC_VDD_30_31:
769 - pwr |= SDHCI_POWER_300;
770 + pwr = SDHCI_POWER_300;
771 break;
772 case MMC_VDD_32_33:
773 case MMC_VDD_33_34:
774 - pwr |= SDHCI_POWER_330;
775 + pwr = SDHCI_POWER_330;
776 break;
777 default:
778 BUG();
779 @@ -696,6 +700,10 @@ static void sdhci_set_power(struct sdhci
780
781 writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
782
783 + pwr |= SDHCI_POWER_ON;
784 +
785 + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
786 +
787 out:
788 host->power = power;
789 }
790 Index: linux-2.6.23.17/drivers/mtd/Kconfig
791 ===================================================================
792 --- linux-2.6.23.17.orig/drivers/mtd/Kconfig
793 +++ linux-2.6.23.17/drivers/mtd/Kconfig
794 @@ -288,6 +288,14 @@ config SSFDC
795 This enables read only access to SmartMedia formatted NAND
796 flash. You can mount it with FAT file system.
797
798 +config MTD_OOPS
799 + tristate "Log panic/oops to an MTD buffer"
800 + depends on MTD
801 + help
802 + This enables panic and oops messages to be logged to a circular
803 + buffer in a flash partition where it can be read back at some
804 + later point.
805 +
806 source "drivers/mtd/chips/Kconfig"
807
808 source "drivers/mtd/maps/Kconfig"
809 Index: linux-2.6.23.17/drivers/mtd/Makefile
810 ===================================================================
811 --- linux-2.6.23.17.orig/drivers/mtd/Makefile
812 +++ linux-2.6.23.17/drivers/mtd/Makefile
813 @@ -22,6 +22,7 @@ obj-$(CONFIG_NFTL) += nftl.o
814 obj-$(CONFIG_INFTL) += inftl.o
815 obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
816 obj-$(CONFIG_SSFDC) += ssfdc.o
817 +obj-$(CONFIG_MTD_OOPS) += mtdoops.o
818
819 nftl-objs := nftlcore.o nftlmount.o
820 inftl-objs := inftlcore.o inftlmount.o
821 Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
822 ===================================================================
823 --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0001.c
824 +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
825 @@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(
826 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
827
828 /*
829 - * Probing of multi-partition flash ships.
830 + * Probing of multi-partition flash chips.
831 *
832 * To support multiple partitions when available, we simply arrange
833 * for each of them to have their own flchip structure even if they
834 @@ -1781,7 +1781,7 @@ static int __xipram do_erase_oneblock(st
835 return ret;
836 }
837
838 -int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
839 +static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
840 {
841 unsigned long ofs, len;
842 int ret;
843 @@ -1931,7 +1931,7 @@ static int cfi_intelext_lock(struct mtd_
844 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
845 __FUNCTION__, ofs, len);
846 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
847 - ofs, len, 0);
848 + ofs, len, NULL);
849 #endif
850
851 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
852 @@ -1941,7 +1941,7 @@ static int cfi_intelext_lock(struct mtd_
853 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
854 __FUNCTION__, ret);
855 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
856 - ofs, len, 0);
857 + ofs, len, NULL);
858 #endif
859
860 return ret;
861 @@ -1955,7 +1955,7 @@ static int cfi_intelext_unlock(struct mt
862 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
863 __FUNCTION__, ofs, len);
864 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
865 - ofs, len, 0);
866 + ofs, len, NULL);
867 #endif
868
869 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
870 @@ -1965,7 +1965,7 @@ static int cfi_intelext_unlock(struct mt
871 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
872 __FUNCTION__, ret);
873 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
874 - ofs, len, 0);
875 + ofs, len, NULL);
876 #endif
877
878 return ret;
879 @@ -2256,7 +2256,7 @@ static void cfi_intelext_save_locks(stru
880 adr = region->offset + block * len;
881
882 status = cfi_varsize_frob(mtd,
883 - do_getlockstatus_oneblock, adr, len, 0);
884 + do_getlockstatus_oneblock, adr, len, NULL);
885 if (status)
886 set_bit(block, region->lockmap);
887 else
888 Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
889 ===================================================================
890 --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0002.c
891 +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
892 @@ -1617,7 +1617,7 @@ static int __xipram do_erase_oneblock(st
893 }
894
895
896 -int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
897 +static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
898 {
899 unsigned long ofs, len;
900 int ret;
901 Index: linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
902 ===================================================================
903 --- linux-2.6.23.17.orig/drivers/mtd/chips/jedec_probe.c
904 +++ linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
905 @@ -70,6 +70,7 @@
906
907 /* Fujitsu */
908 #define MBM29F040C 0x00A4
909 +#define MBM29F800BA 0x2258
910 #define MBM29LV650UE 0x22D7
911 #define MBM29LV320TE 0x22F6
912 #define MBM29LV320BE 0x22F9
913 @@ -129,6 +130,7 @@
914 #define LH28F640BF 0x00b0
915
916 /* ST - www.st.com */
917 +#define M29F800AB 0x0058
918 #define M29W800DT 0x00D7
919 #define M29W800DB 0x005B
920 #define M29W160DT 0x22C4
921 @@ -646,6 +648,23 @@ static const struct amd_flash_info jedec
922 }
923 }, {
924 .mfr_id = MANUFACTURER_FUJITSU,
925 + .dev_id = MBM29F800BA,
926 + .name = "Fujitsu MBM29F800BA",
927 + .uaddr = {
928 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
929 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
930 + },
931 + .DevSize = SIZE_1MiB,
932 + .CmdSet = P_ID_AMD_STD,
933 + .NumEraseRegions= 4,
934 + .regions = {
935 + ERASEINFO(0x04000,1),
936 + ERASEINFO(0x02000,2),
937 + ERASEINFO(0x08000,1),
938 + ERASEINFO(0x10000,15),
939 + }
940 + }, {
941 + .mfr_id = MANUFACTURER_FUJITSU,
942 .dev_id = MBM29LV650UE,
943 .name = "Fujitsu MBM29LV650UE",
944 .uaddr = {
945 @@ -1510,6 +1529,23 @@ static const struct amd_flash_info jedec
946 ERASEINFO(0x1000,256)
947 }
948
949 + }, {
950 + .mfr_id = MANUFACTURER_ST,
951 + .dev_id = M29F800AB,
952 + .name = "ST M29F800AB",
953 + .uaddr = {
954 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
955 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
956 + },
957 + .DevSize = SIZE_1MiB,
958 + .CmdSet = P_ID_AMD_STD,
959 + .NumEraseRegions= 4,
960 + .regions = {
961 + ERASEINFO(0x04000,1),
962 + ERASEINFO(0x02000,2),
963 + ERASEINFO(0x08000,1),
964 + ERASEINFO(0x10000,15),
965 + }
966 }, {
967 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
968 .dev_id = M29W800DT,
969 Index: linux-2.6.23.17/drivers/mtd/devices/Kconfig
970 ===================================================================
971 --- linux-2.6.23.17.orig/drivers/mtd/devices/Kconfig
972 +++ linux-2.6.23.17/drivers/mtd/devices/Kconfig
973 @@ -69,12 +69,21 @@ config MTD_DATAFLASH26
974 If you have such a board and such a DataFlash, say 'Y'.
975
976 config MTD_M25P80
977 - tristate "Support for M25 SPI Flash"
978 + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
979 depends on SPI_MASTER && EXPERIMENTAL
980 help
981 - This enables access to ST M25P80 and similar SPI flash chips,
982 - used for program and data storage. Set up your spi devices
983 - with the right board-specific platform data.
984 + This enables access to most modern SPI flash chips, used for
985 + program and data storage. Series supported include Atmel AT26DF,
986 + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
987 + are supported as well. See the driver source for the current list,
988 + or to add other chips.
989 +
990 + Note that the original DataFlash chips (AT45 series, not AT26DF),
991 + need an entirely different driver.
992 +
993 + Set up your spi devices with the right board-specific platform data,
994 + if you want to specify device partitioning or to use a device which
995 + doesn't support the JEDEC ID instruction.
996
997 config MTD_SLRAM
998 tristate "Uncached system RAM"
999 Index: linux-2.6.23.17/drivers/mtd/devices/m25p80.c
1000 ===================================================================
1001 --- linux-2.6.23.17.orig/drivers/mtd/devices/m25p80.c
1002 +++ linux-2.6.23.17/drivers/mtd/devices/m25p80.c
1003 @@ -1,5 +1,5 @@
1004 /*
1005 - * MTD SPI driver for ST M25Pxx flash chips
1006 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
1007 *
1008 * Author: Mike Lavender, mike@steroidmicros.com
1009 *
1010 @@ -19,33 +19,32 @@
1011 #include <linux/module.h>
1012 #include <linux/device.h>
1013 #include <linux/interrupt.h>
1014 -#include <linux/interrupt.h>
1015 +#include <linux/mutex.h>
1016 +
1017 #include <linux/mtd/mtd.h>
1018 #include <linux/mtd/partitions.h>
1019 +
1020 #include <linux/spi/spi.h>
1021 #include <linux/spi/flash.h>
1022
1023 -#include <asm/semaphore.h>
1024 -
1025 -
1026 -/* NOTE: AT 25F and SST 25LF series are very similar,
1027 - * but commands for sector erase and chip id differ...
1028 - */
1029
1030 #define FLASH_PAGESIZE 256
1031
1032 /* Flash opcodes. */
1033 -#define OPCODE_WREN 6 /* Write enable */
1034 -#define OPCODE_RDSR 5 /* Read status register */
1035 -#define OPCODE_READ 3 /* Read data bytes */
1036 -#define OPCODE_PP 2 /* Page program */
1037 -#define OPCODE_SE 0xd8 /* Sector erase */
1038 -#define OPCODE_RES 0xab /* Read Electronic Signature */
1039 +#define OPCODE_WREN 0x06 /* Write enable */
1040 +#define OPCODE_RDSR 0x05 /* Read status register */
1041 +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
1042 +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
1043 +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
1044 +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
1045 +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
1046 +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
1047 #define OPCODE_RDID 0x9f /* Read JEDEC ID */
1048
1049 /* Status Register bits. */
1050 #define SR_WIP 1 /* Write in progress */
1051 #define SR_WEL 2 /* Write enable latch */
1052 +/* meaning of other SR_* bits may differ between vendors */
1053 #define SR_BP0 4 /* Block protect 0 */
1054 #define SR_BP1 8 /* Block protect 1 */
1055 #define SR_BP2 0x10 /* Block protect 2 */
1056 @@ -65,9 +64,10 @@
1057
1058 struct m25p {
1059 struct spi_device *spi;
1060 - struct semaphore lock;
1061 + struct mutex lock;
1062 struct mtd_info mtd;
1063 - unsigned partitioned;
1064 + unsigned partitioned:1;
1065 + u8 erase_opcode;
1066 u8 command[4];
1067 };
1068
1069 @@ -150,8 +150,9 @@ static int wait_till_ready(struct m25p *
1070 */
1071 static int erase_sector(struct m25p *flash, u32 offset)
1072 {
1073 - DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
1074 - __FUNCTION__, offset);
1075 + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
1076 + flash->spi->dev.bus_id, __FUNCTION__,
1077 + flash->mtd.erasesize / 1024, offset);
1078
1079 /* Wait until finished previous write command. */
1080 if (wait_till_ready(flash))
1081 @@ -161,7 +162,7 @@ static int erase_sector(struct m25p *fla
1082 write_enable(flash);
1083
1084 /* Set up command buffer. */
1085 - flash->command[0] = OPCODE_SE;
1086 + flash->command[0] = flash->erase_opcode;
1087 flash->command[1] = offset >> 16;
1088 flash->command[2] = offset >> 8;
1089 flash->command[3] = offset;
1090 @@ -201,13 +202,17 @@ static int m25p80_erase(struct mtd_info
1091 addr = instr->addr;
1092 len = instr->len;
1093
1094 - down(&flash->lock);
1095 + mutex_lock(&flash->lock);
1096 +
1097 + /* REVISIT in some cases we could speed up erasing large regions
1098 + * by using OPCODE_SE instead of OPCODE_BE_4K
1099 + */
1100
1101 /* now erase those sectors */
1102 while (len) {
1103 if (erase_sector(flash, addr)) {
1104 instr->state = MTD_ERASE_FAILED;
1105 - up(&flash->lock);
1106 + mutex_unlock(&flash->lock);
1107 return -EIO;
1108 }
1109
1110 @@ -215,7 +220,7 @@ static int m25p80_erase(struct mtd_info
1111 len -= mtd->erasesize;
1112 }
1113
1114 - up(&flash->lock);
1115 + mutex_unlock(&flash->lock);
1116
1117 instr->state = MTD_ERASE_DONE;
1118 mtd_erase_callback(instr);
1119 @@ -260,16 +265,19 @@ static int m25p80_read(struct mtd_info *
1120 if (retlen)
1121 *retlen = 0;
1122
1123 - down(&flash->lock);
1124 + mutex_lock(&flash->lock);
1125
1126 /* Wait till previous write/erase is done. */
1127 if (wait_till_ready(flash)) {
1128 /* REVISIT status return?? */
1129 - up(&flash->lock);
1130 + mutex_unlock(&flash->lock);
1131 return 1;
1132 }
1133
1134 - /* NOTE: OPCODE_FAST_READ (if available) is faster... */
1135 + /* FIXME switch to OPCODE_FAST_READ. It's required for higher
1136 + * clocks; and at this writing, every chip this driver handles
1137 + * supports that opcode.
1138 + */
1139
1140 /* Set up the write data buffer. */
1141 flash->command[0] = OPCODE_READ;
1142 @@ -281,7 +289,7 @@ static int m25p80_read(struct mtd_info *
1143
1144 *retlen = m.actual_length - sizeof(flash->command);
1145
1146 - up(&flash->lock);
1147 + mutex_unlock(&flash->lock);
1148
1149 return 0;
1150 }
1151 @@ -323,7 +331,7 @@ static int m25p80_write(struct mtd_info
1152 t[1].tx_buf = buf;
1153 spi_message_add_tail(&t[1], &m);
1154
1155 - down(&flash->lock);
1156 + mutex_lock(&flash->lock);
1157
1158 /* Wait until finished previous write command. */
1159 if (wait_till_ready(flash))
1160 @@ -381,10 +389,10 @@ static int m25p80_write(struct mtd_info
1161 if (retlen)
1162 *retlen += m.actual_length
1163 - sizeof(flash->command);
1164 - }
1165 - }
1166 + }
1167 + }
1168
1169 - up(&flash->lock);
1170 + mutex_unlock(&flash->lock);
1171
1172 return 0;
1173 }
1174 @@ -398,24 +406,118 @@ static int m25p80_write(struct mtd_info
1175
1176 struct flash_info {
1177 char *name;
1178 - u8 id;
1179 - u16 jedec_id;
1180 +
1181 + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
1182 + * a high byte of zero plus three data bytes: the manufacturer id,
1183 + * then a two byte device id.
1184 + */
1185 + u32 jedec_id;
1186 +
1187 + /* The size listed here is what works with OPCODE_SE, which isn't
1188 + * necessarily called a "sector" by the vendor.
1189 + */
1190 unsigned sector_size;
1191 - unsigned n_sectors;
1192 + u16 n_sectors;
1193 +
1194 + u16 flags;
1195 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
1196 };
1197
1198 +
1199 +/* NOTE: double check command sets and memory organization when you add
1200 + * more flash chips. This current list focusses on newer chips, which
1201 + * have been converging on command sets which including JEDEC ID.
1202 + */
1203 static struct flash_info __devinitdata m25p_data [] = {
1204 - /* REVISIT: fill in JEDEC ids, for parts that have them */
1205 - { "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
1206 - { "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
1207 - { "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
1208 - { "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
1209 - { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
1210 - { "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
1211 - { "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
1212 - { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
1213 +
1214 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
1215 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
1216 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
1217 +
1218 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
1219 +
1220 + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
1221 + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
1222 + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
1223 + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
1224 +
1225 + /* Spansion -- single (large) sector size only, at least
1226 + * for the chips listed here (without boot sectors).
1227 + */
1228 + { "s25sl004a", 0x010212, 64 * 1024, 8, },
1229 + { "s25sl008a", 0x010213, 64 * 1024, 16, },
1230 + { "s25sl016a", 0x010214, 64 * 1024, 32, },
1231 + { "s25sl032a", 0x010215, 64 * 1024, 64, },
1232 + { "s25sl064a", 0x010216, 64 * 1024, 128, },
1233 +
1234 + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
1235 + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
1236 + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
1237 + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
1238 + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
1239 +
1240 + /* ST Microelectronics -- newer production may have feature updates */
1241 + { "m25p05", 0x202010, 32 * 1024, 2, },
1242 + { "m25p10", 0x202011, 32 * 1024, 4, },
1243 + { "m25p20", 0x202012, 64 * 1024, 4, },
1244 + { "m25p40", 0x202013, 64 * 1024, 8, },
1245 + { "m25p80", 0, 64 * 1024, 16, },
1246 + { "m25p16", 0x202015, 64 * 1024, 32, },
1247 + { "m25p32", 0x202016, 64 * 1024, 64, },
1248 + { "m25p64", 0x202017, 64 * 1024, 128, },
1249 + { "m25p128", 0x202018, 256 * 1024, 64, },
1250 +
1251 + { "m45pe80", 0x204014, 64 * 1024, 16, },
1252 + { "m45pe16", 0x204015, 64 * 1024, 32, },
1253 +
1254 + { "m25pe80", 0x208014, 64 * 1024, 16, },
1255 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
1256 +
1257 + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
1258 + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
1259 + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
1260 + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
1261 + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
1262 + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
1263 + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
1264 + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
1265 };
1266
1267 +static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
1268 +{
1269 + int tmp;
1270 + u8 code = OPCODE_RDID;
1271 + u8 id[3];
1272 + u32 jedec;
1273 + struct flash_info *info;
1274 +
1275 + /* JEDEC also defines an optional "extended device information"
1276 + * string for after vendor-specific data, after the three bytes
1277 + * we use here. Supporting some chips might require using it.
1278 + */
1279 + tmp = spi_write_then_read(spi, &code, 1, id, 3);
1280 + if (tmp < 0) {
1281 + DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
1282 + spi->dev.bus_id, tmp);
1283 + return NULL;
1284 + }
1285 + jedec = id[0];
1286 + jedec = jedec << 8;
1287 + jedec |= id[1];
1288 + jedec = jedec << 8;
1289 + jedec |= id[2];
1290 +
1291 + for (tmp = 0, info = m25p_data;
1292 + tmp < ARRAY_SIZE(m25p_data);
1293 + tmp++, info++) {
1294 + if (info->jedec_id == jedec)
1295 + return info;
1296 + }
1297 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
1298 + return NULL;
1299 +}
1300 +
1301 +
1302 /*
1303 * board specific setup should have ensured the SPI clock used here
1304 * matches what the READ command supports, at least until this driver
1305 @@ -429,37 +531,51 @@ static int __devinit m25p_probe(struct s
1306 unsigned i;
1307
1308 /* Platform data helps sort out which chip type we have, as
1309 - * well as how this board partitions it.
1310 + * well as how this board partitions it. If we don't have
1311 + * a chip ID, try the JEDEC id commands; they'll work for most
1312 + * newer chips, even if we don't recognize the particular chip.
1313 */
1314 data = spi->dev.platform_data;
1315 - if (!data || !data->type) {
1316 - /* FIXME some chips can identify themselves with RES
1317 - * or JEDEC get-id commands. Try them ...
1318 - */
1319 - DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
1320 - spi->dev.bus_id);
1321 - return -ENODEV;
1322 - }
1323 + if (data && data->type) {
1324 + for (i = 0, info = m25p_data;
1325 + i < ARRAY_SIZE(m25p_data);
1326 + i++, info++) {
1327 + if (strcmp(data->type, info->name) == 0)
1328 + break;
1329 + }
1330
1331 - for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
1332 - if (strcmp(data->type, info->name) == 0)
1333 - break;
1334 - }
1335 - if (i == ARRAY_SIZE(m25p_data)) {
1336 - DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
1337 - spi->dev.bus_id, data->type);
1338 + /* unrecognized chip? */
1339 + if (i == ARRAY_SIZE(m25p_data)) {
1340 + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
1341 + spi->dev.bus_id, data->type);
1342 + info = NULL;
1343 +
1344 + /* recognized; is that chip really what's there? */
1345 + } else if (info->jedec_id) {
1346 + struct flash_info *chip = jedec_probe(spi);
1347 +
1348 + if (!chip || chip != info) {
1349 + dev_warn(&spi->dev, "found %s, expected %s\n",
1350 + chip ? chip->name : "UNKNOWN",
1351 + info->name);
1352 + info = NULL;
1353 + }
1354 + }
1355 + } else
1356 + info = jedec_probe(spi);
1357 +
1358 + if (!info)
1359 return -ENODEV;
1360 - }
1361
1362 flash = kzalloc(sizeof *flash, GFP_KERNEL);
1363 if (!flash)
1364 return -ENOMEM;
1365
1366 flash->spi = spi;
1367 - init_MUTEX(&flash->lock);
1368 + mutex_init(&flash->lock);
1369 dev_set_drvdata(&spi->dev, flash);
1370
1371 - if (data->name)
1372 + if (data && data->name)
1373 flash->mtd.name = data->name;
1374 else
1375 flash->mtd.name = spi->dev.bus_id;
1376 @@ -468,17 +584,25 @@ static int __devinit m25p_probe(struct s
1377 flash->mtd.writesize = 1;
1378 flash->mtd.flags = MTD_CAP_NORFLASH;
1379 flash->mtd.size = info->sector_size * info->n_sectors;
1380 - flash->mtd.erasesize = info->sector_size;
1381 flash->mtd.erase = m25p80_erase;
1382 flash->mtd.read = m25p80_read;
1383 flash->mtd.write = m25p80_write;
1384
1385 + /* prefer "small sector" erase if possible */
1386 + if (info->flags & SECT_4K) {
1387 + flash->erase_opcode = OPCODE_BE_4K;
1388 + flash->mtd.erasesize = 4096;
1389 + } else {
1390 + flash->erase_opcode = OPCODE_SE;
1391 + flash->mtd.erasesize = info->sector_size;
1392 + }
1393 +
1394 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
1395 flash->mtd.size / 1024);
1396
1397 DEBUG(MTD_DEBUG_LEVEL2,
1398 - "mtd .name = %s, .size = 0x%.8x (%uM) "
1399 - ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
1400 + "mtd .name = %s, .size = 0x%.8x (%uMiB) "
1401 + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
1402 flash->mtd.name,
1403 flash->mtd.size, flash->mtd.size / (1024*1024),
1404 flash->mtd.erasesize, flash->mtd.erasesize / 1024,
1405 @@ -488,7 +612,7 @@ static int __devinit m25p_probe(struct s
1406 for (i = 0; i < flash->mtd.numeraseregions; i++)
1407 DEBUG(MTD_DEBUG_LEVEL2,
1408 "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
1409 - ".erasesize = 0x%.8x (%uK), "
1410 + ".erasesize = 0x%.8x (%uKiB), "
1411 ".numblocks = %d }\n",
1412 i, flash->mtd.eraseregions[i].offset,
1413 flash->mtd.eraseregions[i].erasesize,
1414 @@ -516,14 +640,14 @@ static int __devinit m25p_probe(struct s
1415 }
1416
1417 if (nr_parts > 0) {
1418 - for (i = 0; i < data->nr_parts; i++) {
1419 + for (i = 0; i < nr_parts; i++) {
1420 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
1421 "{.name = %s, .offset = 0x%.8x, "
1422 - ".size = 0x%.8x (%uK) }\n",
1423 - i, data->parts[i].name,
1424 - data->parts[i].offset,
1425 - data->parts[i].size,
1426 - data->parts[i].size / 1024);
1427 + ".size = 0x%.8x (%uKiB) }\n",
1428 + i, parts[i].name,
1429 + parts[i].offset,
1430 + parts[i].size,
1431 + parts[i].size / 1024);
1432 }
1433 flash->partitioned = 1;
1434 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
1435 @@ -560,6 +684,11 @@ static struct spi_driver m25p80_driver =
1436 },
1437 .probe = m25p_probe,
1438 .remove = __devexit_p(m25p_remove),
1439 +
1440 + /* REVISIT: many of these chips have deep power-down modes, which
1441 + * should clearly be entered on suspend() to minimize power use.
1442 + * And also when they're otherwise idle...
1443 + */
1444 };
1445
1446
1447 Index: linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
1448 ===================================================================
1449 --- linux-2.6.23.17.orig/drivers/mtd/devices/mtd_dataflash.c
1450 +++ linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
1451 @@ -14,6 +14,7 @@
1452 #include <linux/slab.h>
1453 #include <linux/delay.h>
1454 #include <linux/device.h>
1455 +#include <linux/mutex.h>
1456 #include <linux/spi/spi.h>
1457 #include <linux/spi/flash.h>
1458
1459 @@ -89,7 +90,7 @@ struct dataflash {
1460 unsigned short page_offset; /* offset in flash address */
1461 unsigned int page_size; /* of bytes per page */
1462
1463 - struct semaphore lock;
1464 + struct mutex lock;
1465 struct spi_device *spi;
1466
1467 struct mtd_info mtd;
1468 @@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_in
1469 x.len = 4;
1470 spi_message_add_tail(&x, &msg);
1471
1472 - down(&priv->lock);
1473 + mutex_lock(&priv->lock);
1474 while (instr->len > 0) {
1475 unsigned int pageaddr;
1476 int status;
1477 @@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_in
1478 instr->len -= priv->page_size;
1479 }
1480 }
1481 - up(&priv->lock);
1482 + mutex_unlock(&priv->lock);
1483
1484 /* Inform MTD subsystem that erase is complete */
1485 instr->state = MTD_ERASE_DONE;
1486 @@ -266,7 +267,7 @@ static int dataflash_read(struct mtd_inf
1487 x[1].len = len;
1488 spi_message_add_tail(&x[1], &msg);
1489
1490 - down(&priv->lock);
1491 + mutex_lock(&priv->lock);
1492
1493 /* Continuous read, max clock = f(car) which may be less than
1494 * the peak rate available. Some chips support commands with
1495 @@ -279,7 +280,7 @@ static int dataflash_read(struct mtd_inf
1496 /* plus 4 "don't care" bytes */
1497
1498 status = spi_sync(priv->spi, &msg);
1499 - up(&priv->lock);
1500 + mutex_unlock(&priv->lock);
1501
1502 if (status >= 0) {
1503 *retlen = msg.actual_length - 8;
1504 @@ -336,7 +337,7 @@ static int dataflash_write(struct mtd_in
1505 else
1506 writelen = len;
1507
1508 - down(&priv->lock);
1509 + mutex_lock(&priv->lock);
1510 while (remaining > 0) {
1511 DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
1512 pageaddr, offset, writelen);
1513 @@ -441,7 +442,7 @@ static int dataflash_write(struct mtd_in
1514 else
1515 writelen = remaining;
1516 }
1517 - up(&priv->lock);
1518 + mutex_unlock(&priv->lock);
1519
1520 return status;
1521 }
1522 @@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, ch
1523 if (!priv)
1524 return -ENOMEM;
1525
1526 - init_MUTEX(&priv->lock);
1527 + mutex_init(&priv->lock);
1528 priv->spi = spi;
1529 priv->page_size = pagesize;
1530 priv->page_offset = pageoffset;
1531 Index: linux-2.6.23.17/drivers/mtd/devices/pmc551.c
1532 ===================================================================
1533 --- linux-2.6.23.17.orig/drivers/mtd/devices/pmc551.c
1534 +++ linux-2.6.23.17/drivers/mtd/devices/pmc551.c
1535 @@ -30,8 +30,8 @@
1536 *
1537 * Notes:
1538 * Due to what I assume is more buggy SROM, the 64M PMC551 I
1539 - * have available claims that all 4 of it's DRAM banks have 64M
1540 - * of ram configured (making a grand total of 256M onboard).
1541 + * have available claims that all 4 of its DRAM banks have 64MiB
1542 + * of ram configured (making a grand total of 256MiB onboard).
1543 * This is slightly annoying since the BAR0 size reflects the
1544 * aperture size, not the dram size, and the V370PDC supplies no
1545 * other method for memory size discovery. This problem is
1546 @@ -70,7 +70,7 @@
1547 * made the memory unusable, added a fix to code to touch up
1548 * the DRAM some.
1549 *
1550 - * Bugs/FIXME's:
1551 + * Bugs/FIXMEs:
1552 * * MUST fix the init function to not spin on a register
1553 * waiting for it to set .. this does not safely handle busted
1554 * devices that never reset the register correctly which will
1555 @@ -562,10 +562,10 @@ static u32 fixup_pmc551(struct pci_dev *
1556 /*
1557 * Some screen fun
1558 */
1559 - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
1560 + printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
1561 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
1562 size >> 10 : size >> 20,
1563 - (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
1564 + (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
1565 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
1566 (unsigned long long)pci_resource_start(dev, 0));
1567
1568 @@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
1569 * Stuff these outside the ifdef so as to not bust compiled in driver support
1570 */
1571 static int msize = 0;
1572 -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
1573 -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
1574 -#else
1575 static int asize = 0;
1576 -#endif
1577
1578 module_param(msize, int, 0);
1579 -MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
1580 +MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
1581 module_param(asize, int, 0);
1582 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
1583
1584 @@ -799,8 +795,7 @@ static int __init init_pmc551(void)
1585 mtd->owner = THIS_MODULE;
1586
1587 if (add_mtd_device(mtd)) {
1588 - printk(KERN_NOTICE "pmc551: Failed to register new "
1589 - "device\n");
1590 + printk(KERN_NOTICE "pmc551: Failed to register new device\n");
1591 pci_iounmap(PCI_Device, priv->start);
1592 kfree(mtd->priv);
1593 kfree(mtd);
1594 @@ -811,13 +806,13 @@ static int __init init_pmc551(void)
1595 pci_dev_get(PCI_Device);
1596
1597 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
1598 - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
1599 + printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
1600 priv->asize >> 20,
1601 priv->start, priv->start + priv->asize);
1602 - printk(KERN_NOTICE "Total memory is %d%c\n",
1603 + printk(KERN_NOTICE "Total memory is %d%sB\n",
1604 (length < 1024) ? length :
1605 (length < 1048576) ? length >> 10 : length >> 20,
1606 - (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
1607 + (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
1608 priv->nextpmc551 = pmc551list;
1609 pmc551list = mtd;
1610 found++;
1611 @@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
1612 pmc551list = priv->nextpmc551;
1613
1614 if (priv->start) {
1615 - printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
1616 + printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
1617 "0x%p\n", priv->asize >> 20, priv->start);
1618 pci_iounmap(priv->dev, priv->start);
1619 }
1620 Index: linux-2.6.23.17/drivers/mtd/maps/nettel.c
1621 ===================================================================
1622 --- linux-2.6.23.17.orig/drivers/mtd/maps/nettel.c
1623 +++ linux-2.6.23.17/drivers/mtd/maps/nettel.c
1624 @@ -158,68 +158,11 @@ static struct notifier_block nettel_noti
1625 nettel_reboot_notifier, NULL, 0
1626 };
1627
1628 -/*
1629 - * Erase the configuration file system.
1630 - * Used to support the software reset button.
1631 - */
1632 -static void nettel_erasecallback(struct erase_info *done)
1633 -{
1634 - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
1635 - wake_up(wait_q);
1636 -}
1637 -
1638 -static struct erase_info nettel_erase;
1639 -
1640 -int nettel_eraseconfig(void)
1641 -{
1642 - struct mtd_info *mtd;
1643 - DECLARE_WAITQUEUE(wait, current);
1644 - wait_queue_head_t wait_q;
1645 - int ret;
1646 -
1647 - init_waitqueue_head(&wait_q);
1648 - mtd = get_mtd_device(NULL, 2);
1649 - if (!IS_ERR(mtd)) {
1650 - nettel_erase.mtd = mtd;
1651 - nettel_erase.callback = nettel_erasecallback;
1652 - nettel_erase.callback = NULL;
1653 - nettel_erase.addr = 0;
1654 - nettel_erase.len = mtd->size;
1655 - nettel_erase.priv = (u_long) &wait_q;
1656 - nettel_erase.priv = 0;
1657 -
1658 - set_current_state(TASK_INTERRUPTIBLE);
1659 - add_wait_queue(&wait_q, &wait);
1660 -
1661 - ret = mtd->erase(mtd, &nettel_erase);
1662 - if (ret) {
1663 - set_current_state(TASK_RUNNING);
1664 - remove_wait_queue(&wait_q, &wait);
1665 - put_mtd_device(mtd);
1666 - return(ret);
1667 - }
1668 -
1669 - schedule(); /* Wait for erase to finish. */
1670 - remove_wait_queue(&wait_q, &wait);
1671 -
1672 - put_mtd_device(mtd);
1673 - }
1674 -
1675 - return(0);
1676 -}
1677 -
1678 -#else
1679 -
1680 -int nettel_eraseconfig(void)
1681 -{
1682 - return(0);
1683 -}
1684 -
1685 #endif
1686
1687 /****************************************************************************/
1688
1689 -int __init nettel_init(void)
1690 +static int __init nettel_init(void)
1691 {
1692 volatile unsigned long *amdpar;
1693 unsigned long amdaddr, maxsize;
1694 @@ -421,10 +364,6 @@ int __init nettel_init(void)
1695
1696 intel_mtd->owner = THIS_MODULE;
1697
1698 -#ifndef CONFIG_BLK_DEV_INITRD
1699 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
1700 -#endif
1701 -
1702 num_intel_partitions = sizeof(nettel_intel_partitions) /
1703 sizeof(nettel_intel_partitions[0]);
1704
1705 @@ -477,7 +416,7 @@ out_unmap2:
1706
1707 /****************************************************************************/
1708
1709 -void __exit nettel_cleanup(void)
1710 +static void __exit nettel_cleanup(void)
1711 {
1712 #ifdef CONFIG_MTD_CFI_INTELEXT
1713 unregister_reboot_notifier(&nettel_notifier_block);
1714 Index: linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
1715 ===================================================================
1716 --- linux-2.6.23.17.orig/drivers/mtd/maps/pmcmsp-ramroot.c
1717 +++ linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
1718 @@ -79,7 +79,6 @@ static int __init init_rrmap(void)
1719 rr_mtd->owner = THIS_MODULE;
1720
1721 add_mtd_device(rr_mtd);
1722 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
1723
1724 return 0;
1725 }
1726 Index: linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
1727 ===================================================================
1728 --- linux-2.6.23.17.orig/drivers/mtd/mtd_blkdevs.c
1729 +++ linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
1730 @@ -24,10 +24,9 @@
1731 #include <linux/kthread.h>
1732 #include <asm/uaccess.h>
1733
1734 -static LIST_HEAD(blktrans_majors);
1735 +#include "mtdcore.h"
1736
1737 -extern struct mutex mtd_table_mutex;
1738 -extern struct mtd_info *mtd_table[];
1739 +static LIST_HEAD(blktrans_majors);
1740
1741 struct mtd_blkcore_priv {
1742 struct task_struct *thread;
1743 @@ -202,7 +201,7 @@ static int blktrans_ioctl(struct inode *
1744 }
1745 }
1746
1747 -struct block_device_operations mtd_blktrans_ops = {
1748 +static struct block_device_operations mtd_blktrans_ops = {
1749 .owner = THIS_MODULE,
1750 .open = blktrans_open,
1751 .release = blktrans_release,
1752 Index: linux-2.6.23.17/drivers/mtd/mtdchar.c
1753 ===================================================================
1754 --- linux-2.6.23.17.orig/drivers/mtd/mtdchar.c
1755 +++ linux-2.6.23.17/drivers/mtd/mtdchar.c
1756 @@ -137,7 +137,8 @@ static int mtd_close(struct inode *inode
1757
1758 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
1759
1760 - if (mtd->sync)
1761 + /* Only sync if opened RW */
1762 + if ((file->f_mode & 2) && mtd->sync)
1763 mtd->sync(mtd);
1764
1765 put_mtd_device(mtd);
1766 Index: linux-2.6.23.17/drivers/mtd/mtdcore.c
1767 ===================================================================
1768 --- linux-2.6.23.17.orig/drivers/mtd/mtdcore.c
1769 +++ linux-2.6.23.17/drivers/mtd/mtdcore.c
1770 @@ -22,6 +22,8 @@
1771
1772 #include <linux/mtd/mtd.h>
1773
1774 +#include "mtdcore.h"
1775 +
1776 /* These are exported solely for the purpose of mtd_blkdevs.c. You
1777 should not use them for _anything_ else */
1778 DEFINE_MUTEX(mtd_table_mutex);
1779 Index: linux-2.6.23.17/drivers/mtd/nand/Kconfig
1780 ===================================================================
1781 --- linux-2.6.23.17.orig/drivers/mtd/nand/Kconfig
1782 +++ linux-2.6.23.17/drivers/mtd/nand/Kconfig
1783 @@ -134,10 +134,10 @@ config MTD_NAND_S3C2410_HWECC
1784
1785 config MTD_NAND_NDFC
1786 tristate "NDFC NanD Flash Controller"
1787 - depends on 44x
1788 + depends on 4xx
1789 select MTD_NAND_ECC_SMC
1790 help
1791 - NDFC Nand Flash Controllers are integrated in EP44x SoCs
1792 + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
1793
1794 config MTD_NAND_S3C2410_CLKSTOP
1795 bool "S3C2410 NAND IDLE clock stop"
1796 @@ -237,7 +237,7 @@ config MTD_NAND_CAFE
1797 select REED_SOLOMON
1798 select REED_SOLOMON_DEC16
1799 help
1800 - Use NAND flash attached to the CAFÉ chip designed for the $100
1801 + Use NAND flash attached to the CAFÉ chip designed for the OLPC
1802 laptop.
1803
1804 config MTD_NAND_CS553X
1805 Index: linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
1806 ===================================================================
1807 --- linux-2.6.23.17.orig/drivers/mtd/nand/cafe_nand.c
1808 +++ linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
1809 @@ -822,14 +822,53 @@ static struct pci_device_id cafe_nand_tb
1810
1811 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
1812
1813 +static int cafe_nand_resume(struct pci_dev *pdev)
1814 +{
1815 + uint32_t timing1, timing2, timing3;
1816 + uint32_t ctrl;
1817 + struct mtd_info *mtd = pci_get_drvdata(pdev);
1818 + struct cafe_priv *cafe = mtd->priv;
1819 +
1820 + timing1 = timing2 = timing3 = 0xffffffff;
1821 + /* Start off by resetting the NAND controller completely */
1822 + cafe_writel(cafe, 1, NAND_RESET);
1823 + cafe_writel(cafe, 0, NAND_RESET);
1824 + cafe_writel(cafe, timing1, NAND_TIMING1);
1825 + cafe_writel(cafe, timing2, NAND_TIMING2);
1826 + cafe_writel(cafe, timing3, NAND_TIMING3);
1827 + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
1828 +
1829 + /* Disable master reset, enable NAND clock */
1830 + ctrl = cafe_readl(cafe, GLOBAL_CTRL);
1831 + ctrl &= 0xffffeff0;
1832 + ctrl |= 0x00007000;
1833 + cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
1834 + cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
1835 + cafe_writel(cafe, 0, NAND_DMA_CTRL);
1836 + cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
1837 + cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
1838 +
1839 + /* Set up DMA address */
1840 + cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
1841 + if (sizeof(cafe->dmaaddr) > 4)
1842 + /* Shift in two parts to shut the compiler up */
1843 + cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
1844 + else
1845 + cafe_writel(cafe, 0, NAND_DMA_ADDR1);
1846 +
1847 + /* Enable NAND IRQ in global IRQ mask register */
1848 + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
1849 + return 0;
1850 +}
1851 +
1852 static struct pci_driver cafe_nand_pci_driver = {
1853 .name = "CAFÉ NAND",
1854 .id_table = cafe_nand_tbl,
1855 .probe = cafe_nand_probe,
1856 .remove = __devexit_p(cafe_nand_remove),
1857 + .resume = cafe_nand_resume,
1858 #ifdef CONFIG_PMx
1859 .suspend = cafe_nand_suspend,
1860 - .resume = cafe_nand_resume,
1861 #endif
1862 };
1863
1864 Index: linux-2.6.23.17/drivers/mtd/nand/ndfc.c
1865 ===================================================================
1866 --- linux-2.6.23.17.orig/drivers/mtd/nand/ndfc.c
1867 +++ linux-2.6.23.17/drivers/mtd/nand/ndfc.c
1868 @@ -24,7 +24,11 @@
1869 #include <linux/platform_device.h>
1870
1871 #include <asm/io.h>
1872 +#ifdef CONFIG_40x
1873 +#include <asm/ibm405.h>
1874 +#else
1875 #include <asm/ibm44x.h>
1876 +#endif
1877
1878 struct ndfc_nand_mtd {
1879 struct mtd_info mtd;
1880 @@ -230,7 +234,11 @@ static int ndfc_nand_probe(struct platfo
1881 struct ndfc_controller *ndfc = &ndfc_ctrl;
1882 unsigned long long phys = settings->ndfc_erpn | res->start;
1883
1884 +#ifndef CONFIG_PHYS_64BIT
1885 + ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
1886 +#else
1887 ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
1888 +#endif
1889 if (!ndfc->ndfcbase) {
1890 printk(KERN_ERR "NDFC: ioremap failed\n");
1891 return -EIO;
1892 Index: linux-2.6.23.17/drivers/mtd/onenand/Kconfig
1893 ===================================================================
1894 --- linux-2.6.23.17.orig/drivers/mtd/onenand/Kconfig
1895 +++ linux-2.6.23.17/drivers/mtd/onenand/Kconfig
1896 @@ -40,4 +40,27 @@ config MTD_ONENAND_OTP
1897
1898 OTP block is fully-guaranteed to be a valid block.
1899
1900 +config MTD_ONENAND_2X_PROGRAM
1901 + bool "OneNAND 2X program support"
1902 + help
1903 + The 2X Program is an extension of Program Operation.
1904 + Since the device is equipped with two DataRAMs, and two-plane NAND
1905 + Flash memory array, these two component enables simultaneous program
1906 + of 4KiB. Plane1 has only even blocks such as block0, block2, block4
1907 + while Plane2 has only odd blocks such as block1, block3, block5.
1908 + So MTD regards it as 4KiB page size and 256KiB block size
1909 +
1910 + Now the following chips support it. (KFXXX16Q2M)
1911 + Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
1912 + Mux: KFM2G16Q2M, KFN4G16Q2M,
1913 +
1914 + And more recent chips
1915 +
1916 +config MTD_ONENAND_SIM
1917 + tristate "OneNAND simulator support"
1918 + depends on MTD_PARTITIONS
1919 + help
1920 + The simulator may simulate various OneNAND flash chips for the
1921 + OneNAND MTD layer.
1922 +
1923 endif # MTD_ONENAND
1924 Index: linux-2.6.23.17/drivers/mtd/onenand/Makefile
1925 ===================================================================
1926 --- linux-2.6.23.17.orig/drivers/mtd/onenand/Makefile
1927 +++ linux-2.6.23.17/drivers/mtd/onenand/Makefile
1928 @@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
1929 # Board specific.
1930 obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
1931
1932 +# Simulator
1933 +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
1934 +
1935 onenand-objs = onenand_base.o onenand_bbt.o
1936 Index: linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
1937 ===================================================================
1938 --- linux-2.6.23.17.orig/drivers/mtd/onenand/onenand_base.c
1939 +++ linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
1940 @@ -206,6 +206,15 @@ static int onenand_command(struct mtd_in
1941 default:
1942 block = (int) (addr >> this->erase_shift);
1943 page = (int) (addr >> this->page_shift);
1944 +
1945 + if (ONENAND_IS_2PLANE(this)) {
1946 + /* Make the even block number */
1947 + block &= ~1;
1948 + /* Is it the odd plane? */
1949 + if (addr & this->writesize)
1950 + block++;
1951 + page >>= 1;
1952 + }
1953 page &= this->page_mask;
1954 break;
1955 }
1956 @@ -216,8 +225,12 @@ static int onenand_command(struct mtd_in
1957 value = onenand_bufferram_address(this, block);
1958 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1959
1960 - /* Switch to the next data buffer */
1961 - ONENAND_SET_NEXT_BUFFERRAM(this);
1962 + if (ONENAND_IS_2PLANE(this))
1963 + /* It is always BufferRAM0 */
1964 + ONENAND_SET_BUFFERRAM0(this);
1965 + else
1966 + /* Switch to the next data buffer */
1967 + ONENAND_SET_NEXT_BUFFERRAM(this);
1968
1969 return 0;
1970 }
1971 @@ -247,6 +260,8 @@ static int onenand_command(struct mtd_in
1972 break;
1973
1974 default:
1975 + if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
1976 + cmd = ONENAND_CMD_2X_PROG;
1977 dataram = ONENAND_CURRENT_BUFFERRAM(this);
1978 break;
1979 }
1980 @@ -445,8 +460,9 @@ static inline int onenand_bufferram_offs
1981 struct onenand_chip *this = mtd->priv;
1982
1983 if (ONENAND_CURRENT_BUFFERRAM(this)) {
1984 + /* Note: the 'this->writesize' is a real page size */
1985 if (area == ONENAND_DATARAM)
1986 - return mtd->writesize;
1987 + return this->writesize;
1988 if (area == ONENAND_SPARERAM)
1989 return mtd->oobsize;
1990 }
1991 @@ -572,6 +588,30 @@ static int onenand_write_bufferram(struc
1992 }
1993
1994 /**
1995 + * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode
1996 + * @param mtd MTD data structure
1997 + * @param addr address to check
1998 + * @return blockpage address
1999 + *
2000 + * Get blockpage address at 2x program mode
2001 + */
2002 +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
2003 +{
2004 + struct onenand_chip *this = mtd->priv;
2005 + int blockpage, block, page;
2006 +
2007 + /* Calculate the even block number */
2008 + block = (int) (addr >> this->erase_shift) & ~1;
2009 + /* Is it the odd plane? */
2010 + if (addr & this->writesize)
2011 + block++;
2012 + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
2013 + blockpage = (block << 7) | page;
2014 +
2015 + return blockpage;
2016 +}
2017 +
2018 +/**
2019 * onenand_check_bufferram - [GENERIC] Check BufferRAM information
2020 * @param mtd MTD data structure
2021 * @param addr address to check
2022 @@ -585,7 +625,10 @@ static int onenand_check_bufferram(struc
2023 int blockpage, found = 0;
2024 unsigned int i;
2025
2026 - blockpage = (int) (addr >> this->page_shift);
2027 + if (ONENAND_IS_2PLANE(this))
2028 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2029 + else
2030 + blockpage = (int) (addr >> this->page_shift);
2031
2032 /* Is there valid data? */
2033 i = ONENAND_CURRENT_BUFFERRAM(this);
2034 @@ -625,7 +668,10 @@ static void onenand_update_bufferram(str
2035 int blockpage;
2036 unsigned int i;
2037
2038 - blockpage = (int) (addr >> this->page_shift);
2039 + if (ONENAND_IS_2PLANE(this))
2040 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2041 + else
2042 + blockpage = (int) (addr >> this->page_shift);
2043
2044 /* Invalidate another BufferRAM */
2045 i = ONENAND_NEXT_BUFFERRAM(this);
2046 @@ -734,6 +780,7 @@ static int onenand_read(struct mtd_info
2047 int read = 0, column;
2048 int thislen;
2049 int ret = 0, boundary = 0;
2050 + int writesize = this->writesize;
2051
2052 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
2053
2054 @@ -754,22 +801,22 @@ static int onenand_read(struct mtd_info
2055 /* Do first load to bufferRAM */
2056 if (read < len) {
2057 if (!onenand_check_bufferram(mtd, from)) {
2058 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2059 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2060 ret = this->wait(mtd, FL_READING);
2061 onenand_update_bufferram(mtd, from, !ret);
2062 }
2063 }
2064
2065 - thislen = min_t(int, mtd->writesize, len - read);
2066 - column = from & (mtd->writesize - 1);
2067 - if (column + thislen > mtd->writesize)
2068 - thislen = mtd->writesize - column;
2069 + thislen = min_t(int, writesize, len - read);
2070 + column = from & (writesize - 1);
2071 + if (column + thislen > writesize)
2072 + thislen = writesize - column;
2073
2074 while (!ret) {
2075 /* If there is more to load then start next load */
2076 from += thislen;
2077 if (read + thislen < len) {
2078 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2079 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2080 /*
2081 * Chip boundary handling in DDP
2082 * Now we issued chip 1 read and pointed chip 1
2083 @@ -794,7 +841,7 @@ static int onenand_read(struct mtd_info
2084 this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
2085 ONENAND_SET_NEXT_BUFFERRAM(this);
2086 buf += thislen;
2087 - thislen = min_t(int, mtd->writesize, len - read);
2088 + thislen = min_t(int, writesize, len - read);
2089 column = 0;
2090 cond_resched();
2091 /* Now wait for load */
2092 @@ -1079,7 +1126,7 @@ int onenand_bbt_read_oob(struct mtd_info
2093 /* Read more? */
2094 if (read < len) {
2095 /* Update Page size */
2096 - from += mtd->writesize;
2097 + from += this->writesize;
2098 column = 0;
2099 }
2100 }
2101 @@ -1135,12 +1182,12 @@ static int onenand_verify(struct mtd_inf
2102 int thislen, column;
2103
2104 while (len != 0) {
2105 - thislen = min_t(int, mtd->writesize, len);
2106 - column = addr & (mtd->writesize - 1);
2107 - if (column + thislen > mtd->writesize)
2108 - thislen = mtd->writesize - column;
2109 + thislen = min_t(int, this->writesize, len);
2110 + column = addr & (this->writesize - 1);
2111 + if (column + thislen > this->writesize)
2112 + thislen = this->writesize - column;
2113
2114 - this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
2115 + this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
2116
2117 onenand_update_bufferram(mtd, addr, 0);
2118
2119 @@ -1236,6 +1283,10 @@ static int onenand_write(struct mtd_info
2120
2121 /* In partial page write we don't update bufferram */
2122 onenand_update_bufferram(mtd, to, !ret && !subpage);
2123 + if (ONENAND_IS_2PLANE(this)) {
2124 + ONENAND_SET_BUFFERRAM1(this);
2125 + onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
2126 + }
2127
2128 if (ret) {
2129 printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
2130 @@ -1384,6 +1435,10 @@ static int onenand_do_write_oob(struct m
2131 this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
2132
2133 onenand_update_bufferram(mtd, to, 0);
2134 + if (ONENAND_IS_2PLANE(this)) {
2135 + ONENAND_SET_BUFFERRAM1(this);
2136 + onenand_update_bufferram(mtd, to + this->writesize, 0);
2137 + }
2138
2139 ret = this->wait(mtd, FL_WRITING);
2140 if (ret) {
2141 @@ -2107,6 +2162,7 @@ static int onenand_lock_user_prot_reg(st
2142 *
2143 * Check and set OneNAND features
2144 * - lock scheme
2145 + * - two plane
2146 */
2147 static void onenand_check_features(struct mtd_info *mtd)
2148 {
2149 @@ -2118,19 +2174,35 @@ static void onenand_check_features(struc
2150 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2151
2152 /* Lock scheme */
2153 - if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
2154 + switch (density) {
2155 + case ONENAND_DEVICE_DENSITY_4Gb:
2156 + this->options |= ONENAND_HAS_2PLANE;
2157 +
2158 + case ONENAND_DEVICE_DENSITY_2Gb:
2159 + /* 2Gb DDP don't have 2 plane */
2160 + if (!ONENAND_IS_DDP(this))
2161 + this->options |= ONENAND_HAS_2PLANE;
2162 + this->options |= ONENAND_HAS_UNLOCK_ALL;
2163 +
2164 + case ONENAND_DEVICE_DENSITY_1Gb:
2165 /* A-Die has all block unlock */
2166 - if (process) {
2167 - printk(KERN_DEBUG "Chip support all block unlock\n");
2168 + if (process)
2169 this->options |= ONENAND_HAS_UNLOCK_ALL;
2170 - }
2171 - } else {
2172 - /* Some OneNAND has continues lock scheme */
2173 - if (!process) {
2174 - printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
2175 + break;
2176 +
2177 + default:
2178 + /* Some OneNAND has continuous lock scheme */
2179 + if (!process)
2180 this->options |= ONENAND_HAS_CONT_LOCK;
2181 - }
2182 + break;
2183 }
2184 +
2185 + if (this->options & ONENAND_HAS_CONT_LOCK)
2186 + printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2187 + if (this->options & ONENAND_HAS_UNLOCK_ALL)
2188 + printk(KERN_DEBUG "Chip support all block unlock\n");
2189 + if (this->options & ONENAND_HAS_2PLANE)
2190 + printk(KERN_DEBUG "Chip has 2 plane\n");
2191 }
2192
2193 /**
2194 @@ -2257,6 +2329,8 @@ static int onenand_probe(struct mtd_info
2195 this->erase_shift = ffs(mtd->erasesize) - 1;
2196 this->page_shift = ffs(mtd->writesize) - 1;
2197 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
2198 + /* It's real page size */
2199 + this->writesize = mtd->writesize;
2200
2201 /* REVIST: Multichip handling */
2202
2203 @@ -2265,6 +2339,17 @@ static int onenand_probe(struct mtd_info
2204 /* Check OneNAND features */
2205 onenand_check_features(mtd);
2206
2207 + /*
2208 + * We emulate the 4KiB page and 256KiB erase block size
2209 + * But oobsize is still 64 bytes.
2210 + * It is only valid if you turn on 2X program support,
2211 + * Otherwise it will be ignored by compiler.
2212 + */
2213 + if (ONENAND_IS_2PLANE(this)) {
2214 + mtd->writesize <<= 1;
2215 + mtd->erasesize <<= 1;
2216 + }
2217 +
2218 return 0;
2219 }
2220
2221 Index: linux-2.6.23.17/drivers/pci/quirks.c
2222 ===================================================================
2223 --- linux-2.6.23.17.orig/drivers/pci/quirks.c
2224 +++ linux-2.6.23.17/drivers/pci/quirks.c
2225 @@ -1396,6 +1396,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
2226 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
2227
2228 /*
2229 + * According to Tom Sylla, the Geode does not support PCI power management
2230 + * transition, so we shouldn't need the D3hot delay.
2231 + */
2232 +static void __init quirk_geode_pci_pm(struct pci_dev *dev)
2233 +{
2234 + pci_pm_d3_delay = 0;
2235 +}
2236 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, quirk_geode_pci_pm);
2237 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_geode_pci_pm);
2238 +
2239 +/*
2240 * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size
2241 * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
2242 * Re-allocate the region if needed...
2243 Index: linux-2.6.23.17/drivers/video/Kconfig
2244 ===================================================================
2245 --- linux-2.6.23.17.orig/drivers/video/Kconfig
2246 +++ linux-2.6.23.17/drivers/video/Kconfig
2247 @@ -594,7 +594,7 @@ config FB_TGA
2248
2249 config FB_VESA
2250 bool "VESA VGA graphics support"
2251 - depends on (FB = y) && X86
2252 + depends on (FB = y) && X86 && !VGA_NOPROBE
2253 select FB_CFB_FILLRECT
2254 select FB_CFB_COPYAREA
2255 select FB_CFB_IMAGEBLIT
2256 @@ -1028,7 +1028,7 @@ config FB_CARILLO_RANCH
2257
2258 config FB_INTEL
2259 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
2260 - depends on FB && EXPERIMENTAL && PCI && X86
2261 + depends on FB && EXPERIMENTAL && PCI && X86 && !VGA_NOPROBE
2262 select AGP
2263 select AGP_INTEL
2264 select FB_MODE_HELPERS
2265 @@ -1383,7 +1383,7 @@ config FB_SAVAGE_ACCEL
2266
2267 config FB_SIS
2268 tristate "SiS/XGI display support"
2269 - depends on FB && PCI
2270 + depends on FB && PCI && !VGA_NOPROBE
2271 select FB_CFB_FILLRECT
2272 select FB_CFB_COPYAREA
2273 select FB_CFB_IMAGEBLIT
2274 @@ -1822,6 +1822,15 @@ config FB_PS3_DEFAULT_SIZE_M
2275 The default value can be overridden on the kernel command line
2276 using the "ps3fb" option (e.g. "ps3fb=9M");
2277
2278 +config FB_OLPC_DCON
2279 + tristate "One Laptop Per Child Display CONtroller support"
2280 + depends on OLPC
2281 + select I2C
2282 + ---help---
2283 + Add support for the OLPC DCON controller. This controller is only
2284 + available on OLPC platforms. Unless you have one of these
2285 + platforms, you will want to say 'N'.
2286 +
2287 config FB_XILINX
2288 tristate "Xilinx frame buffer support"
2289 depends on FB && XILINX_VIRTEX
2290 Index: linux-2.6.23.17/drivers/video/Makefile
2291 ===================================================================
2292 --- linux-2.6.23.17.orig/drivers/video/Makefile
2293 +++ linux-2.6.23.17/drivers/video/Makefile
2294 @@ -111,6 +111,7 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx
2295 obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
2296 obj-$(CONFIG_FB_PS3) += ps3fb.o
2297 obj-$(CONFIG_FB_SM501) += sm501fb.o
2298 +obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon.o
2299 obj-$(CONFIG_FB_XILINX) += xilinxfb.o
2300 obj-$(CONFIG_FB_OMAP) += omap/
2301
2302 Index: linux-2.6.23.17/drivers/video/fbmem.c
2303 ===================================================================
2304 --- linux-2.6.23.17.orig/drivers/video/fbmem.c
2305 +++ linux-2.6.23.17/drivers/video/fbmem.c
2306 @@ -820,6 +820,53 @@ static void try_to_load(int fb)
2307 #endif /* CONFIG_KMOD */
2308
2309 int
2310 +fb_powerup(struct fb_info *info)
2311 +{
2312 + int ret = 0;
2313 +
2314 + if (!info || info->state == FBINFO_STATE_RUNNING)
2315 + return 0;
2316 +
2317 + if (info->fbops->fb_powerup)
2318 + ret = info->fbops->fb_powerup(info);
2319 +
2320 + if (!ret) {
2321 + acquire_console_sem();
2322 + fb_set_suspend(info, 0);
2323 + release_console_sem();
2324 + }
2325 +
2326 + return ret;
2327 +}
2328 +
2329 +int
2330 +fb_powerdown(struct fb_info *info)
2331 +{
2332 + int ret = 0;
2333 +
2334 + if (!info || info->state == FBINFO_STATE_SUSPENDED)
2335 + return 0;
2336 +
2337 + /* Tell everybody that the fbdev is going down */
2338 + acquire_console_sem();
2339 + fb_set_suspend(info, 1);
2340 + release_console_sem();
2341 +
2342 + if (info->fbops->fb_powerdown)
2343 + ret = info->fbops->fb_powerdown(info);
2344 +
2345 + /* If the power down failed, then un-notify */
2346 +
2347 + if (ret) {
2348 + acquire_console_sem();
2349 + fb_set_suspend(info, 0);
2350 + release_console_sem();
2351 + }
2352 +
2353 + return ret;
2354 +}
2355 +
2356 +int
2357 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
2358 {
2359 struct fb_fix_screeninfo *fix = &info->fix;
2360 Index: linux-2.6.23.17/drivers/video/geode/Makefile
2361 ===================================================================
2362 --- linux-2.6.23.17.orig/drivers/video/geode/Makefile
2363 +++ linux-2.6.23.17/drivers/video/geode/Makefile
2364 @@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
2365 obj-$(CONFIG_FB_GEODE_LX) += lxfb.o
2366
2367 gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
2368 -gxfb-objs := gxfb_core.o display_gx.o video_gx.o
2369 +gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
2370 lxfb-objs := lxfb_core.o lxfb_ops.o
2371 Index: linux-2.6.23.17/drivers/video/geode/display_gx.c
2372 ===================================================================
2373 --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.c
2374 +++ linux-2.6.23.17/drivers/video/geode/display_gx.c
2375 @@ -11,26 +11,44 @@
2376 * Free Software Foundation; either version 2 of the License, or * (at your
2377 * option) any later version.
2378 */
2379 +
2380 +#include <linux/kernel.h>
2381 #include <linux/spinlock.h>
2382 #include <linux/fb.h>
2383 #include <linux/delay.h>
2384 #include <asm/io.h>
2385 #include <asm/div64.h>
2386 #include <asm/delay.h>
2387 +#include <asm/olpc.h>
2388
2389 #include "geodefb.h"
2390 #include "display_gx.h"
2391
2392 -#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
2393 -unsigned int gx_frame_buffer_size(void)
2394 +static inline void rmwl(u32 val, u32 *reg)
2395 {
2396 - return CONFIG_FB_GEODE_GX_FBSIZE;
2397 + u32 in = readl(reg);
2398 + if (in != val)
2399 + writel(val, reg);
2400 }
2401 -#else
2402 +
2403 unsigned int gx_frame_buffer_size(void)
2404 {
2405 unsigned int val;
2406
2407 +#ifdef CONFIG_OLPC
2408 + if (machine_is_olpc() && !olpc_has_vsa()) {
2409 + u32 hi,lo;
2410 + rdmsr(GLIU0_P2D_RO0, lo, hi);
2411 +
2412 + /* Top page number */
2413 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
2414 +
2415 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
2416 + val += 1; /* Adjust page count */
2417 + return (val << 12);
2418 + }
2419 +#endif
2420 +
2421 /* FB size is reported by a virtual register */
2422 /* Virtual register class = 0x02 */
2423 /* VG_MEM_SIZE(512Kb units) = 0x00 */
2424 @@ -41,7 +59,6 @@ unsigned int gx_frame_buffer_size(void)
2425 val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
2426 return (val << 19);
2427 }
2428 -#endif
2429
2430 int gx_line_delta(int xres, int bpp)
2431 {
2432 @@ -63,23 +80,23 @@ static void gx_set_mode(struct fb_info *
2433 gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
2434 dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
2435
2436 - /* Disable the timing generator. */
2437 - dcfg &= ~(DC_DCFG_TGEN);
2438 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2439 -
2440 - /* Wait for pending memory requests before disabling the FIFO load. */
2441 - udelay(100);
2442 -
2443 - /* Disable FIFO load and compression. */
2444 - gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2445 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2446 -
2447 - /* Setup DCLK and its divisor. */
2448 - par->vid_ops->set_dclk(info);
2449 -
2450 - /*
2451 - * Setup new mode.
2452 - */
2453 + /* Programming the clock is costly and ugly, so avoid if if we can */
2454 +
2455 + if (par->curdclk != info->var.pixclock) {
2456 + /* Disable the timing generator. */
2457 + dcfg &= ~(DC_DCFG_TGEN);
2458 + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2459 +
2460 + /* Wait for pending memory requests before disabling the FIFO load. */
2461 + udelay(100);
2462 +
2463 + /* Disable FIFO load and compression. */
2464 + gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2465 + writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2466 +
2467 + /* Setup DCLK and its divisor. */
2468 + par->vid_ops->set_dclk(info);
2469 + }
2470
2471 /* Clear all unused feature bits. */
2472 gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
2473 @@ -90,12 +107,13 @@ static void gx_set_mode(struct fb_info *
2474 gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
2475
2476 /* Framebuffer start offset. */
2477 - writel(0, par->dc_regs + DC_FB_ST_OFFSET);
2478 + rmwl(0, par->dc_regs + DC_FB_ST_OFFSET);
2479
2480 /* Line delta and line buffer length. */
2481 - writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2482 - writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2483 - par->dc_regs + DC_LINE_SIZE);
2484 + rmwl(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2485 +
2486 + rmwl(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2487 + par->dc_regs + DC_LINE_SIZE);
2488
2489
2490 /* Enable graphics and video data and unmask address lines. */
2491 @@ -134,17 +152,16 @@ static void gx_set_mode(struct fb_info *
2492 vblankend = vsyncend + info->var.upper_margin;
2493 vtotal = vblankend;
2494
2495 - writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2496 - writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2497 - writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2498 -
2499 - writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2500 - writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2501 - writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2502 + rmwl((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2503 + rmwl((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2504 + rmwl((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2505 + rmwl((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2506 + rmwl((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2507 + rmwl((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2508
2509 /* Write final register values. */
2510 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2511 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2512 + rmwl(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2513 + rmwl(gcfg, par->dc_regs + DC_GENERAL_CFG);
2514
2515 par->vid_ops->configure_display(info);
2516
2517 Index: linux-2.6.23.17/drivers/video/geode/display_gx.h
2518 ===================================================================
2519 --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.h
2520 +++ linux-2.6.23.17/drivers/video/geode/display_gx.h
2521 @@ -20,6 +20,9 @@ extern struct geode_dc_ops gx_dc_ops;
2522 #define GLD_MSR_CONFIG 0xC0002001
2523 #define GLD_MSR_CONFIG_DM_FP 0x40
2524
2525 +/* Used for memory dection on the OLPC */
2526 +#define GLIU0_P2D_RO0 0x10000029
2527 +
2528 /* Display controller registers */
2529
2530 #define DC_UNLOCK 0x00
2531 Index: linux-2.6.23.17/drivers/video/geode/geodefb.h
2532 ===================================================================
2533 --- linux-2.6.23.17.orig/drivers/video/geode/geodefb.h
2534 +++ linux-2.6.23.17/drivers/video/geode/geodefb.h
2535 @@ -12,6 +12,10 @@
2536 #ifndef __GEODEFB_H__
2537 #define __GEODEFB_H__
2538
2539 +#define FB_POWER_STATE_OFF 0
2540 +#define FB_POWER_STATE_SUSPEND 1
2541 +#define FB_POWER_STATE_ON 2
2542 +
2543 struct geodefb_info;
2544
2545 struct geode_dc_ops {
2546 @@ -21,18 +25,24 @@ struct geode_dc_ops {
2547
2548 struct geode_vid_ops {
2549 void (*set_dclk)(struct fb_info *);
2550 + unsigned int (*get_dclk)(struct fb_info *);
2551 void (*configure_display)(struct fb_info *);
2552 int (*blank_display)(struct fb_info *, int blank_mode);
2553 };
2554
2555 struct geodefb_par {
2556 int enable_crt;
2557 + int fbactive; /* True if the current console is in KD_GRAPHICS mode */
2558 int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
2559 int panel_y;
2560 + unsigned int curdclk; /* Used by GX to avoid unnessesary clock switching */
2561 void __iomem *dc_regs;
2562 void __iomem *vid_regs;
2563 + void __iomem *gp_regs;
2564 struct geode_dc_ops *dc_ops;
2565 struct geode_vid_ops *vid_ops;
2566 +
2567 + int state;
2568 };
2569
2570 #endif /* !__GEODEFB_H__ */
2571 Index: linux-2.6.23.17/drivers/video/geode/gxfb_core.c
2572 ===================================================================
2573 --- linux-2.6.23.17.orig/drivers/video/geode/gxfb_core.c
2574 +++ linux-2.6.23.17/drivers/video/geode/gxfb_core.c
2575 @@ -30,12 +30,31 @@
2576 #include <linux/fb.h>
2577 #include <linux/init.h>
2578 #include <linux/pci.h>
2579 +#include <linux/notifier.h>
2580 +#include <linux/vt_kern.h>
2581 +#include <linux/console.h>
2582 +#include <asm/uaccess.h>
2583 +#include <asm/olpc.h>
2584
2585 #include "geodefb.h"
2586 #include "display_gx.h"
2587 #include "video_gx.h"
2588
2589 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
2590 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
2591 +
2592 +#ifdef DEBUG
2593 +
2594 +#define FBIODUMPGP _IOW('F', 0x22, void *)
2595 +#define FBIODUMPDC _IOW('F', 0x23, void *)
2596 +#define FBIODUMPVP _IOW('F', 0x24, void *)
2597 +#define FBIODUMPFP _IOW('F', 0x25, void *)
2598 +
2599 +#endif
2600 +
2601 static char *mode_option;
2602 +static int noclear;
2603 +struct fb_info *gxfb_info;
2604
2605 /* Modes relevant to the GX (taken from modedb.c) */
2606 static const struct fb_videomode gx_modedb[] __initdata = {
2607 @@ -103,8 +122,20 @@ static const struct fb_videomode gx_mode
2608 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
2609 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
2610 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
2611 + /* 1200x900-75 - CRT timings for the OLPC mode */
2612 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
2613 + 0, FB_VMODE_NONINTERLACED, 0 }
2614 };
2615
2616 +#ifdef CONFIG_OLPC
2617 +static const struct fb_videomode gx_dcon_modedb[] __initdata = {
2618 + /* The only mode the DCON has is 1200x900 */
2619 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
2620 + 0, FB_VMODE_NONINTERLACED, 0 }
2621 +};
2622 +#endif
2623 +
2624 +
2625 static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2626 {
2627 if (var->xres > 1600 || var->yres > 1200)
2628 @@ -137,7 +168,7 @@ static int gxfb_check_var(struct fb_var_
2629 return 0;
2630 }
2631
2632 -static int gxfb_set_par(struct fb_info *info)
2633 +int gxfb_set_par(struct fb_info *info)
2634 {
2635 struct geodefb_par *par = info->par;
2636
2637 @@ -204,16 +235,26 @@ static int gxfb_blank(int blank_mode, st
2638 return par->vid_ops->blank_display(info, blank_mode);
2639 }
2640
2641 +static int fbsize;
2642 +
2643 static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
2644 {
2645 struct geodefb_par *par = info->par;
2646 - int fb_len;
2647 int ret;
2648
2649 ret = pci_enable_device(dev);
2650 if (ret < 0)
2651 return ret;
2652
2653 + ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
2654 + if (ret < 0)
2655 + return ret;
2656 +
2657 + par->gp_regs = ioremap(pci_resource_start(dev, 1),
2658 + pci_resource_len(dev, 1));
2659 + if (!par->gp_regs)
2660 + return -ENOMEM;
2661 +
2662 ret = pci_request_region(dev, 3, "gxfb (video processor)");
2663 if (ret < 0)
2664 return ret;
2665 @@ -232,36 +273,118 @@ static int __init gxfb_map_video_memory(
2666 ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
2667 if (ret < 0)
2668 return ret;
2669 - if ((fb_len = gx_frame_buffer_size()) < 0)
2670 - return -ENOMEM;
2671 +
2672 + /* If the fbsize wasn't specified then try to probe it */
2673 +
2674 + if (!fbsize) {
2675 + fbsize = gx_frame_buffer_size();
2676 + if (fbsize == 0)
2677 + return -ENOMEM;
2678 + }
2679 +
2680 info->fix.smem_start = pci_resource_start(dev, 0);
2681 - info->fix.smem_len = fb_len;
2682 + info->fix.smem_len = fbsize;
2683 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2684 if (!info->screen_base)
2685 return -ENOMEM;
2686
2687 - /* Set the 16MB aligned base address of the graphics memory region
2688 + /* Set the 16MiB aligned base address of the graphics memory region
2689 * in the display controller */
2690
2691 writel(info->fix.smem_start & 0xFF000000,
2692 par->dc_regs + DC_GLIU0_MEM_OFFSET);
2693
2694 - dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
2695 + dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
2696 info->fix.smem_len / 1024, info->fix.smem_start);
2697
2698 return 0;
2699 }
2700
2701 +static int gxfb_ioctl( struct fb_info *info, unsigned int cmd,
2702 + unsigned long arg)
2703 +{
2704 + unsigned int gamma[GXFB_GAMMA_DWORDS];
2705 + int ret = -EINVAL;
2706 + struct geodefb_par *par = info->par;
2707 + int i;
2708 +
2709 + switch(cmd) {
2710 + case FBIOSGAMMA:
2711 + /* Read the gamma information from the user - 256 dwords */
2712 +
2713 + if (copy_from_user(gamma, (void * __user) arg, GXFB_GAMMA_SIZE))
2714 + return -EFAULT;
2715 +
2716 + writel(0, par->vid_regs + GX_GAR);
2717 +
2718 + /* Sequential writes to the data register will increment the
2719 + address automatically */
2720 +
2721 + for(i = 0; i < GXFB_GAMMA_DWORDS; i++)
2722 + writel(gamma[i] & 0xFFFFFF, par->vid_regs + GX_GDR);
2723 +
2724 + writel(readl(par->vid_regs + GX_MISC) & ~GX_MISC_GAM_EN,
2725 + par->vid_regs + GX_MISC);
2726 +
2727 + ret = 0;
2728 + break;
2729 +
2730 + case FBIOGGAMMA:
2731 + if (readl(par->vid_regs + GX_MISC) & GX_MISC_GAM_EN)
2732 + return -EINVAL;
2733 +
2734 + memset(gamma, 0, GXFB_GAMMA_SIZE);
2735 + writel(0, par->vid_regs + GX_GAR);
2736 +
2737 + for(i = 0; i < GXFB_GAMMA_DWORDS;i++)
2738 + gamma[i] = readl(par->vid_regs + GX_GDR);
2739 +
2740 + if (copy_to_user((void * __user) arg, gamma, GXFB_GAMMA_SIZE))
2741 + ret = -EFAULT;
2742 + else
2743 + ret = 0;
2744 +
2745 + break;
2746 +
2747 +#ifdef DEBUG
2748 + case FBIODUMPGP:
2749 + ret = 0;
2750 + dump_regs(info, 0);
2751 + break;
2752 +
2753 + case FBIODUMPDC:
2754 + ret = 0;
2755 + dump_regs(info, 1);
2756 + break;
2757 +
2758 + case FBIODUMPVP:
2759 + ret = 0;
2760 + dump_regs(info, 2);
2761 + break;
2762 +
2763 + case FBIODUMPFP:
2764 + ret = 0;
2765 + dump_regs(info, 3);
2766 + break;
2767 +#endif
2768 + }
2769 +
2770 + return ret;
2771 +}
2772 +
2773 static struct fb_ops gxfb_ops = {
2774 .owner = THIS_MODULE,
2775 .fb_check_var = gxfb_check_var,
2776 .fb_set_par = gxfb_set_par,
2777 .fb_setcolreg = gxfb_setcolreg,
2778 .fb_blank = gxfb_blank,
2779 + .fb_ioctl = gxfb_ioctl,
2780 /* No HW acceleration for now. */
2781 .fb_fillrect = cfb_fillrect,
2782 .fb_copyarea = cfb_copyarea,
2783 .fb_imageblit = cfb_imageblit,
2784 + .fb_powerdown = gxfb_powerdown,
2785 + .fb_powerup = gxfb_powerup,
2786 };
2787
2788 static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
2789 @@ -303,23 +426,86 @@ static struct fb_info * __init gxfb_init
2790 return info;
2791 }
2792
2793 -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2794 +static int gxfb_console_notify(struct notifier_block *self,
2795 + unsigned long action, void *data)
2796 +{
2797 + if (gxfb_info != NULL) {
2798 + struct geodefb_par *par = gxfb_info->par;
2799 + par->fbactive = (action == CONSOLE_EVENT_SWITCH_TEXT) ? 0 : 1;
2800 + }
2801 +
2802 + return NOTIFY_OK;
2803 +}
2804 +
2805 +static struct notifier_block gxfb_console_notifier = {
2806 + .notifier_call = gxfb_console_notify
2807 +};
2808 +
2809 +#ifdef CONFIG_PM
2810 +
2811 +static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
2812 +{
2813 + struct fb_info *info = pci_get_drvdata(pdev);
2814 + struct geodefb_par *par = info->par;
2815 +
2816 + if (pdev->dev.power.power_state.event == state.event)
2817 + return 0;
2818 +
2819 + if (state.event == PM_EVENT_SUSPEND) {
2820 +
2821 + acquire_console_sem();
2822 + gxfb_powerdown(info);
2823 +
2824 + par->state = FB_POWER_STATE_OFF;
2825 + fb_set_suspend(info, 1);
2826 +
2827 + release_console_sem();
2828 + }
2829 +
2830 + pdev->dev.power.power_state = state;
2831 + return 0;
2832 +}
2833 +
2834 +static int gxfb_resume(struct pci_dev *pdev)
2835 +{
2836 + struct fb_info *info = pci_get_drvdata(pdev);
2837 +
2838 + acquire_console_sem();
2839 +
2840 + /* Turn the engine completely on */
2841 +
2842 + if (gxfb_powerup(info))
2843 + printk(KERN_ERR "gxfb: Powerup failed\n");
2844 +
2845 + fb_set_suspend(info, 0);
2846 + release_console_sem();
2847 +
2848 + pdev->dev.power.power_state = PMSG_ON;
2849 + return 0;
2850 +}
2851 +#endif
2852 +
2853 +static int __init gxfb_probe(struct pci_dev *pdev,
2854 + const struct pci_device_id *id)
2855 {
2856 struct geodefb_par *par;
2857 - struct fb_info *info;
2858 int ret;
2859 unsigned long val;
2860
2861 - info = gxfb_init_fbinfo(&pdev->dev);
2862 - if (!info)
2863 + struct fb_videomode *modedb_ptr;
2864 + int modedb_size;
2865 +
2866 + gxfb_info = gxfb_init_fbinfo(&pdev->dev);
2867 + if (gxfb_info == NULL)
2868 return -ENOMEM;
2869 - par = info->par;
2870 +
2871 + par = gxfb_info->par;
2872
2873 /* GX display controller and GX video device. */
2874 par->dc_ops = &gx_dc_ops;
2875 par->vid_ops = &gx_vid_ops;
2876
2877 - if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
2878 + if ((ret = gxfb_map_video_memory(gxfb_info, pdev)) < 0) {
2879 dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
2880 goto err;
2881 }
2882 @@ -333,32 +519,60 @@ static int __init gxfb_probe(struct pci_
2883 else
2884 par->enable_crt = 1;
2885
2886 - ret = fb_find_mode(&info->var, info, mode_option,
2887 - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
2888 + /* Get the current dotclock */
2889 +
2890 + par->curdclk = (par->vid_ops->get_dclk) ? par->vid_ops->get_dclk(gxfb_info) : 0;
2891 +
2892 + /* We need to determine a display mode right now, so we will
2893 + * check to see if the DCON was previously detected by the BIOS
2894 + * and use that to make our mode database decision.
2895 + */
2896 +
2897 + modedb_ptr = (struct fb_videomode *) gx_modedb;
2898 + modedb_size = ARRAY_SIZE(gx_modedb);
2899 +
2900 +#ifdef CONFIG_OLPC
2901 + if (olpc_has_dcon()) {
2902 + modedb_ptr = (struct fb_videomode *) gx_dcon_modedb;
2903 + modedb_size = ARRAY_SIZE(gx_dcon_modedb);
2904 + }
2905 +#endif
2906 +
2907 + ret = fb_find_mode(&gxfb_info->var, gxfb_info, mode_option,
2908 + modedb_ptr, modedb_size, NULL, 16);
2909 +
2910 if (ret == 0 || ret == 4) {
2911 dev_err(&pdev->dev, "could not find valid video mode\n");
2912 ret = -EINVAL;
2913 goto err;
2914 }
2915
2916 + /* Clear the screen of garbage, unless noclear was specified,
2917 + * in which case we assume the user knows what he is doing */
2918 +
2919 + if (!noclear)
2920 + memset_io(gxfb_info->screen_base, 0, gxfb_info->fix.smem_len);
2921 +
2922 + gxfb_check_var(&gxfb_info->var, gxfb_info);
2923 + gxfb_set_par(gxfb_info);
2924 +
2925 + /* We are powered up */
2926 + par->state = FB_POWER_STATE_ON;
2927
2928 - /* Clear the frame buffer of garbage. */
2929 - memset_io(info->screen_base, 0, info->fix.smem_len);
2930
2931 - gxfb_check_var(&info->var, info);
2932 - gxfb_set_par(info);
2933 + console_event_register(&gxfb_console_notifier);
2934
2935 - if (register_framebuffer(info) < 0) {
2936 + if (register_framebuffer(gxfb_info) < 0) {
2937 ret = -EINVAL;
2938 goto err;
2939 }
2940 - pci_set_drvdata(pdev, info);
2941 - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
2942 + pci_set_drvdata(pdev, gxfb_info);
2943 + printk(KERN_INFO "fb%d: %s frame buffer device\n", gxfb_info->node, gxfb_info->fix.id);
2944 return 0;
2945
2946 err:
2947 - if (info->screen_base) {
2948 - iounmap(info->screen_base);
2949 + if (gxfb_info->screen_base) {
2950 + iounmap(gxfb_info->screen_base);
2951 pci_release_region(pdev, 0);
2952 }
2953 if (par->vid_regs) {
2954 @@ -370,8 +584,9 @@ static int __init gxfb_probe(struct pci_
2955 pci_release_region(pdev, 2);
2956 }
2957
2958 - if (info)
2959 - framebuffer_release(info);
2960 + if (gxfb_info)
2961 + framebuffer_release(gxfb_info);
2962 +
2963 return ret;
2964 }
2965
2966 @@ -397,9 +612,7 @@ static void gxfb_remove(struct pci_dev *
2967 }
2968
2969 static struct pci_device_id gxfb_id_table[] = {
2970 - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
2971 - PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
2972 - 0xff0000, 0 },
2973 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
2974 { 0, }
2975 };
2976
2977 @@ -410,22 +623,30 @@ static struct pci_driver gxfb_driver = {
2978 .id_table = gxfb_id_table,
2979 .probe = gxfb_probe,
2980 .remove = gxfb_remove,
2981 +#ifdef CONFIG_PM
2982 + .suspend = gxfb_suspend,
2983 + .resume = gxfb_resume
2984 +#endif
2985 };
2986
2987 #ifndef MODULE
2988 -static int __init gxfb_setup(char *options)
2989 -{
2990 +static int __init gxfb_setup(char *options) {
2991
2992 char *opt;
2993
2994 if (!options || !*options)
2995 return 0;
2996
2997 - while ((opt = strsep(&options, ",")) != NULL) {
2998 + while((opt = strsep(&options, ",")) != NULL) {
2999 if (!*opt)
3000 continue;
3001
3002 - mode_option = opt;
3003 + if (!strncmp(opt, "fbsize:", 7))
3004 + fbsize = simple_strtoul(opt+7, NULL, 0);
3005 + else if (!strcmp(opt, "noclear"))
3006 + noclear = 1;
3007 + else
3008 + mode_option = opt;
3009 }
3010
3011 return 0;
3012 @@ -444,7 +665,6 @@ static int __init gxfb_init(void)
3013 #endif
3014 return pci_register_driver(&gxfb_driver);
3015 }
3016 -
3017 static void __exit gxfb_cleanup(void)
3018 {
3019 pci_unregister_driver(&gxfb_driver);
3020 @@ -456,5 +676,8 @@ module_exit(gxfb_cleanup);
3021 module_param(mode_option, charp, 0);
3022 MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
3023
3024 +module_param(fbsize, int, 0);
3025 +MODULE_PARM_DESC(fbsize, "video memory size");
3026 +
3027 MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
3028 MODULE_LICENSE("GPL");
3029 Index: linux-2.6.23.17/drivers/video/geode/lxfb.h
3030 ===================================================================
3031 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb.h
3032 +++ linux-2.6.23.17/drivers/video/geode/lxfb.h
3033 @@ -25,10 +25,23 @@ void lx_set_mode(struct fb_info *);
3034 void lx_get_gamma(struct fb_info *, unsigned int *, int);
3035 void lx_set_gamma(struct fb_info *, unsigned int *, int);
3036 unsigned int lx_framebuffer_size(void);
3037 +int lx_shutdown(struct fb_info *);
3038 +int lx_powerup(struct fb_info *);
3039 int lx_blank_display(struct fb_info *, int);
3040 void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
3041 unsigned int, unsigned int);
3042
3043 +
3044 +
3045 +/* ioctl() defines */
3046 +
3047 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
3048 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
3049 +
3050 +/* General definitions */
3051 +#define LXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
3052 +#define LXFB_GAMMA_SIZE (LXFB_GAMMA_DWORDS * sizeof(unsigned int))
3053 +
3054 /* MSRS */
3055
3056 #define MSR_LX_GLD_CONFIG 0x48002001
3057 Index: linux-2.6.23.17/drivers/video/geode/lxfb_core.c
3058 ===================================================================
3059 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_core.c
3060 +++ linux-2.6.23.17/drivers/video/geode/lxfb_core.c
3061 @@ -22,6 +22,7 @@
3062 #include <linux/init.h>
3063 #include <linux/pci.h>
3064 #include <linux/uaccess.h>
3065 +#include <asm/olpc.h>
3066
3067 #include "lxfb.h"
3068
3069 @@ -35,186 +36,84 @@ static int fbsize;
3070 */
3071
3072 const struct fb_videomode geode_modedb[] __initdata = {
3073 - /* 640x480-60 */
3074 - { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
3075 + /* 640x480-60 VESA */
3076 + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
3077 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3078 + /* 640x480-75 VESA */
3079 + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
3080 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3081 + /* 640x480-85 VESA */
3082 + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
3083 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3084 + /* 800x600-60 VESA */
3085 + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
3086 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3087 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3088 + /* 800x600-75 VESA */
3089 + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
3090 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3091 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3092 + /* 800x600-85 VESA */
3093 + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
3094 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3095 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3096 + /* 1024x768-60 VESA */
3097 + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
3098 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3099 + /* 1024x768-75 VESA */
3100 + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
3101 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3102 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3103 + /* 1024x768-85 VESA */
3104 + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
3105 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3106 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3107 + /* 1280x960-60 VESA */
3108 + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
3109 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3110 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3111 + /* 1280x960-85 VESA */
3112 + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
3113 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3114 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3115 + /* 1280x1024-60 VESA */
3116 + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
3117 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3118 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3119 + /* 1280x1024-75 VESA */
3120 + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
3121 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3122 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3123 + /* 1280x1024-85 VESA */
3124 + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
3125 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3126 - FB_VMODE_NONINTERLACED, 0 },
3127 - /* 640x400-70 */
3128 - { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
3129 - FB_SYNC_HOR_HIGH_ACT,
3130 - FB_VMODE_NONINTERLACED, 0 },
3131 - /* 640x480-70 */
3132 - { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
3133 - 0, FB_VMODE_NONINTERLACED, 0 },
3134 - /* 640x480-72 */
3135 - { NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3,
3136 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3137 - FB_VMODE_NONINTERLACED, 0 },
3138 - /* 640x480-75 */
3139 - { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
3140 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3141 - FB_VMODE_NONINTERLACED, 0 },
3142 - /* 640x480-85 */
3143 - { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
3144 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3145 - FB_VMODE_NONINTERLACED, 0 },
3146 - /* 640x480-90 */
3147 - { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
3148 - 0, FB_VMODE_NONINTERLACED, 0 },
3149 - /* 640x480-100 */
3150 - { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
3151 - 0, FB_VMODE_NONINTERLACED, 0 },
3152 - /* 640x480-60 */
3153 - { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
3154 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3155 - FB_VMODE_NONINTERLACED, 0 },
3156 - /* 800x600-56 */
3157 - { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
3158 - 0, FB_VMODE_NONINTERLACED, 0 },
3159 - /* 800x600-60 */
3160 - { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
3161 - 0, FB_VMODE_NONINTERLACED, 0 },
3162 - /* 800x600-70 */
3163 - { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
3164 - 0, FB_VMODE_NONINTERLACED, 0 },
3165 - /* 800x600-72 */
3166 - { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
3167 - 0, FB_VMODE_NONINTERLACED, 0 },
3168 - /* 800x600-75 */
3169 - { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
3170 - 0, FB_VMODE_NONINTERLACED, 0 },
3171 - /* 800x600-85 */
3172 - { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
3173 - 0, FB_VMODE_NONINTERLACED, 0 },
3174 - /* 800x600-90 */
3175 - { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
3176 - 0, FB_VMODE_NONINTERLACED, 0 },
3177 - /* 800x600-100 */
3178 - { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
3179 - 0, FB_VMODE_NONINTERLACED, 0 },
3180 - /* 800x600-60 */
3181 - { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
3182 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3183 - FB_VMODE_NONINTERLACED, 0 },
3184 - /* 1024x768-60 */
3185 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3186 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3187 - FB_VMODE_NONINTERLACED, 0 },
3188 - /* 1024x768-70 */
3189 - { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
3190 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3191 - FB_VMODE_NONINTERLACED, 0 },
3192 - /* 1024x768-72 */
3193 - { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
3194 - 0, FB_VMODE_NONINTERLACED, 0 },
3195 - /* 1024x768-75 */
3196 - { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
3197 - 0, FB_VMODE_NONINTERLACED, 0 },
3198 - /* 1024x768-85 */
3199 - { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
3200 - 0, FB_VMODE_NONINTERLACED, 0 },
3201 - /* 1024x768-90 */
3202 - { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
3203 - 0, FB_VMODE_NONINTERLACED, 0 },
3204 - /* 1024x768-100 */
3205 - { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
3206 - 0, FB_VMODE_NONINTERLACED, 0 },
3207 - /* 1024x768-60 */
3208 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3209 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3210 - FB_VMODE_NONINTERLACED, 0 },
3211 - /* 1152x864-60 */
3212 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3213 - 0, FB_VMODE_NONINTERLACED, 0 },
3214 - /* 1152x864-70 */
3215 - { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
3216 - 0, FB_VMODE_NONINTERLACED, 0 },
3217 - /* 1152x864-72 */
3218 - { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
3219 - 0, FB_VMODE_NONINTERLACED, 0 },
3220 - /* 1152x864-75 */
3221 - { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
3222 - 0, FB_VMODE_NONINTERLACED, 0 },
3223 - /* 1152x864-85 */
3224 - { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
3225 - 0, FB_VMODE_NONINTERLACED, 0 },
3226 - /* 1152x864-90 */
3227 - { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
3228 - 0, FB_VMODE_NONINTERLACED, 0 },
3229 - /* 1152x864-100 */
3230 - { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
3231 - 0, FB_VMODE_NONINTERLACED, 0 },
3232 - /* 1152x864-60 */
3233 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3234 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3235 - FB_VMODE_NONINTERLACED, 0 },
3236 - /* 1280x1024-60 */
3237 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3238 - 0, FB_VMODE_NONINTERLACED, 0 },
3239 - /* 1280x1024-70 */
3240 - { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
3241 - 0, FB_VMODE_NONINTERLACED, 0 },
3242 - /* 1280x1024-72 */
3243 - { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
3244 - 0, FB_VMODE_NONINTERLACED, 0 },
3245 - /* 1280x1024-75 */
3246 - { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
3247 - 0, FB_VMODE_NONINTERLACED, 0 },
3248 - /* 1280x1024-85 */
3249 - { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
3250 - 0, FB_VMODE_NONINTERLACED, 0 },
3251 - /* 1280x1024-90 */
3252 - { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
3253 - 0, FB_VMODE_NONINTERLACED, 0 },
3254 - /* 1280x1024-100 */
3255 - { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
3256 - 0, FB_VMODE_NONINTERLACED, 0 },
3257 - /* 1280x1024-60 */
3258 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3259 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3260 - FB_VMODE_NONINTERLACED, 0 },
3261 - /* 1600x1200-60 */
3262 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3263 + /* 1600x1200-60 VESA */
3264 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3265 - 0, FB_VMODE_NONINTERLACED, 0 },
3266 - /* 1600x1200-70 */
3267 - { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
3268 - 0, FB_VMODE_NONINTERLACED, 0 },
3269 - /* 1600x1200-72 */
3270 - { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
3271 - 0, FB_VMODE_NONINTERLACED, 0 },
3272 - /* 1600x1200-75 */
3273 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3274 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3275 + /* 1600x1200-75 VESA */
3276 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
3277 - 0, FB_VMODE_NONINTERLACED, 0 },
3278 - /* 1600x1200-85 */
3279 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3280 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3281 + /* 1600x1200-85 VESA */
3282 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
3283 - 0, FB_VMODE_NONINTERLACED, 0 },
3284 - /* 1600x1200-90 */
3285 - { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
3286 - 0, FB_VMODE_NONINTERLACED, 0 },
3287 - /* 1600x1200-100 */
3288 - { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
3289 - 0, FB_VMODE_NONINTERLACED, 0 },
3290 - /* 1600x1200-60 */
3291 - { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3292 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3293 - FB_VMODE_NONINTERLACED, 0 },
3294 - /* 1920x1440-60 */
3295 - { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
3296 - 0, FB_VMODE_NONINTERLACED, 0 },
3297 - /* 1920x1440-70 */
3298 - { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
3299 - 0, FB_VMODE_NONINTERLACED, 0 },
3300 - /* 1920x1440-72 */
3301 - { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
3302 - 0, FB_VMODE_NONINTERLACED, 0 },
3303 - /* 1920x1440-75 */
3304 - { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
3305 - 0, FB_VMODE_NONINTERLACED, 0 },
3306 - /* 1920x1440-85 */
3307 - { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
3308 - 0, FB_VMODE_NONINTERLACED, 0 },
3309 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3310 + /* 1200x900-75 - CRT timings for the OLPC mode */
3311 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
3312 + 0, FB_VMODE_NONINTERLACED, 0 }
3313 };
3314
3315 +#ifdef CONFIG_OLPC
3316 +const struct fb_videomode olpc_dcon_modedb[] __initdata = {
3317 + /* The only mode the DCON has is 1200x900 */
3318 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
3319 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3320 + FB_VMODE_NONINTERLACED, 0 }
3321 +};
3322 +#endif
3323 +
3324 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
3325 {
3326 if (var->xres > 1920 || var->yres > 1440)
3327 @@ -379,16 +278,55 @@ static int __init lxfb_map_video_memory(
3328 return 0;
3329 }
3330
3331 +static int lxfb_set_gamma(struct fb_info *info, void * __user data)
3332 +{
3333 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3334 +
3335 + if (copy_from_user(gamma, data, LXFB_GAMMA_SIZE))
3336 + return -EFAULT;
3337 +
3338 + lx_set_gamma(info, gamma, LXFB_GAMMA_SIZE);
3339 + return 0;
3340 +}
3341 +
3342 +static int lxfb_get_gamma(struct fb_info *info, void * __user data)
3343 +{
3344 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3345 + memset(gamma, 0, sizeof(gamma));
3346 +
3347 + lx_get_gamma(info, gamma, LXFB_GAMMA_DWORDS);
3348 +
3349 + return copy_to_user(data, gamma, LXFB_GAMMA_SIZE) ?
3350 + -EFAULT : 0;
3351 +}
3352 +
3353 +static int lxfb_ioctl( struct fb_info *info, unsigned int cmd,
3354 + unsigned long arg)
3355 +{
3356 + switch(cmd) {
3357 + case FBIOSGAMMA:
3358 + return lxfb_set_gamma(info, (void * __user) arg);
3359 +
3360 + case FBIOGGAMMA:
3361 + return lxfb_get_gamma(info, (void * __user) arg);
3362 + }
3363 +
3364 + return -ENOTTY;
3365 +}
3366 +
3367 static struct fb_ops lxfb_ops = {
3368 .owner = THIS_MODULE,
3369 .fb_check_var = lxfb_check_var,
3370 .fb_set_par = lxfb_set_par,
3371 .fb_setcolreg = lxfb_setcolreg,
3372 .fb_blank = lxfb_blank,
3373 + .fb_ioctl = lxfb_ioctl,
3374 /* No HW acceleration for now. */
3375 .fb_fillrect = cfb_fillrect,
3376 .fb_copyarea = cfb_copyarea,
3377 .fb_imageblit = cfb_imageblit,
3378 + .fb_powerdown = lx_shutdown,
3379 + .fb_powerup = lx_powerup,
3380 };
3381
3382 static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
3383 @@ -431,6 +369,45 @@ static struct fb_info * __init lxfb_init
3384 return info;
3385 }
3386
3387 +#ifdef CONFIG_PM
3388 +
3389 +static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
3390 +{
3391 + struct fb_info *info = pci_get_drvdata(pdev);
3392 +
3393 + if (pdev->dev.power.power_state.event == state.event)
3394 + return 0;
3395 +
3396 + if (state.event == PM_EVENT_SUSPEND) {
3397 +
3398 + acquire_console_sem();
3399 + lx_shutdown(info);
3400 + fb_set_suspend(info, 1);
3401 + release_console_sem();
3402 + }
3403 +
3404 + pdev->dev.power.power_state = state;
3405 + return 0;
3406 +}
3407 +
3408 +static int lxfb_resume(struct pci_dev *pdev)
3409 +{
3410 + struct fb_info *info = pci_get_drvdata(pdev);
3411 +
3412 + acquire_console_sem();
3413 +
3414 + /* Turn the engine completely on */
3415 +
3416 + lx_powerup(info);
3417 + fb_set_suspend(info, 0);
3418 + release_console_sem();
3419 +
3420 + pdev->dev.power.power_state = PMSG_ON;
3421 + return 0;
3422 +}
3423 +
3424 +#endif
3425 +
3426 static int __init lxfb_probe(struct pci_dev *pdev,
3427 const struct pci_device_id *id)
3428 {
3429 @@ -467,6 +444,13 @@ static int __init lxfb_probe(struct pci_
3430 modedb_ptr = (struct fb_videomode *) geode_modedb;
3431 modedb_size = ARRAY_SIZE(geode_modedb);
3432
3433 +#ifdef CONFIG_OLPC
3434 + if (olpc_has_dcon()) {
3435 + modedb_ptr = (struct fb_videomode *) olpc_dcon_modedb;
3436 + modedb_size = ARRAY_SIZE(olpc_dcon_modedb);
3437 + }
3438 +#endif
3439 +
3440 ret = fb_find_mode(&info->var, info, mode_option,
3441 modedb_ptr, modedb_size, NULL, 16);
3442
3443 @@ -556,6 +540,10 @@ static struct pci_driver lxfb_driver = {
3444 .id_table = lxfb_id_table,
3445 .probe = lxfb_probe,
3446 .remove = lxfb_remove,
3447 +#ifdef CONFIG_PM
3448 + .suspend = lxfb_suspend,
3449 + .resume = lxfb_resume
3450 +#endif
3451 };
3452
3453 #ifndef MODULE
3454 Index: linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
3455 ===================================================================
3456 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_ops.c
3457 +++ linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
3458 @@ -13,9 +13,13 @@
3459 #include <linux/fb.h>
3460 #include <linux/uaccess.h>
3461 #include <linux/delay.h>
3462 +#include <asm/olpc.h>
3463
3464 #include "lxfb.h"
3465
3466 +#define _GEODELX_
3467 +#include "geode_regs.h"
3468 +
3469 /* TODO
3470 * Support panel scaling
3471 * Add acceleration
3472 @@ -290,6 +294,19 @@ unsigned int lx_framebuffer_size(void)
3473 {
3474 unsigned int val;
3475
3476 +#ifdef CONFIG_OLPC
3477 + if (machine_is_olpc() && !olpc_has_vsa()) {
3478 + u32 hi,lo;
3479 + rdmsr(MSR_LX_GLIU0_P2D_RO0, lo, hi);
3480 +
3481 + /* Top page number */
3482 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
3483 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
3484 + val += 1; /* Adjust page count */
3485 + return (val << 12);
3486 + }
3487 +#endif
3488 +
3489 /* The frame buffer size is reported by a VSM in VSA II */
3490 /* Virtual Register Class = 0x02 */
3491 /* VG_MEM_SIZE (1MB units) = 0x00 */
3492 @@ -301,6 +318,34 @@ unsigned int lx_framebuffer_size(void)
3493 return (val << 20);
3494 }
3495
3496 +void lx_set_gamma(struct fb_info *info, unsigned int *gamma, int len)
3497 +{
3498 + int i;
3499 + struct lxfb_par *par = info->par;
3500 +
3501 + writel(0, par->df_regs + DF_PAR);
3502 +
3503 + /* Sequential writes to the data register will increment the
3504 + address automatically */
3505 +
3506 + for(i = 0; i < len; i++)
3507 + writel(gamma[i] & 0xFFFFFF, par->df_regs + DF_PDR);
3508 +
3509 + writel(readl(par->df_regs + DF_MISC) & ~DF_MISC_GAM_BYPASS,
3510 + par->df_regs + DF_MISC);
3511 +}
3512 +
3513 +void lx_get_gamma(struct fb_info *info, unsigned int *gamma, int len)
3514 +{
3515 + int i;
3516 + struct lxfb_par *par = info->par;
3517 +
3518 + writel(0, par->df_regs + DF_PAR);
3519 +
3520 + for(i = 0; i < len;i++)
3521 + gamma[i] = readl(par->df_regs + DF_PDR);
3522 +}
3523 +
3524 void lx_set_mode(struct fb_info *info)
3525 {
3526 struct lxfb_par *par = info->par;
3527 @@ -313,6 +358,7 @@ void lx_set_mode(struct fb_info *info)
3528 int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
3529
3530 /* Unlock the DC registers */
3531 + readl(par->dc_regs + DC_UNLOCK);
3532 writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3533
3534 lx_graphics_disable(info);
3535 @@ -534,3 +580,285 @@ int lx_blank_display(struct fb_info *inf
3536
3537 return 0;
3538 }
3539 +
3540 +static struct geoderegs saved_regs;
3541 +
3542 +static void lx_save_regs(struct fb_info *info, struct geoderegs *regs)
3543 +{
3544 + struct lxfb_par *par = info->par;
3545 + int i;
3546 +
3547 + /* Wait for the command buffer to empty */
3548 + while(!(readl(par->gp_regs + 0x44) & (1 << 4)));
3549 +
3550 + rdmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3551 + rdmsrl(MSR_LX_GLCP_DOTPLL, regs->msr.dotpll);
3552 + rdmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3553 + rdmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3554 +
3555 + writel(0x4758, par->dc_regs + 0x00);
3556 +
3557 + memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE);
3558 + memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE);
3559 + memcpy(regs->vp.b, par->df_regs, VP_REG_SIZE);
3560 + memcpy(regs->fp.b, par->df_regs + VP_FP_START, FP_REG_SIZE);
3561 +
3562 + /* Save the palettes */
3563 + writel(0, par->dc_regs + 0x70);
3564 +
3565 + for(i = 0; i < DC_PAL_SIZE; i++)
3566 + regs->pal[i] = readl(par->dc_regs + 0x74);
3567 +
3568 + writel(0, par->df_regs + 0x38);
3569 +
3570 + for(i = 0; i <= 0xFF; i++)
3571 + regs->gamma[i] = readl(par->df_regs + 0x40);
3572 +}
3573 +
3574 +static void lx_restore_regs(struct fb_info *info, struct geoderegs *regs)
3575 +{
3576 + struct lxfb_par *par = info->par;
3577 + u32 val, i;
3578 +
3579 + /* == DOTPLL == */
3580 +
3581 + lx_set_dotpll((u32) (regs->msr.dotpll >> 32));
3582 +
3583 + /* MSRs */
3584 +
3585 + wrmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3586 +
3587 + /* == GP == */
3588 +
3589 + writel(regs->gp.r.dst_offset, par->gp_regs + 0x00);
3590 + writel(regs->gp.r.src_offset, par->gp_regs + 0x04);
3591 + writel(regs->gp.r.stride, par->gp_regs + 0x08);
3592 + writel(regs->gp.r.wid_height, par->gp_regs + 0x0C);
3593 + writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10);
3594 + writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14);
3595 + writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18);
3596 + writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C);
3597 + writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20);
3598 + writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24);
3599 + writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28);
3600 + writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C);
3601 + writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30);
3602 + writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34);
3603 +
3604 + /* Writing to these registers would cause a blt to happen */
3605 + /* 0x38, 0x3c, 0x40 */
3606 +
3607 + /* Status register (0x44) is read only */
3608 +
3609 + writel(regs->gp.r.hst_src, par->gp_regs + 0x48);
3610 + writel(regs->gp.r.base_offset, par->gp_regs + 0x4c);
3611 + writel(regs->gp.r.cmd_top, par->gp_regs + 0x50);
3612 + writel(regs->gp.r.cmd_bot, par->gp_regs + 0x54);
3613 + writel(regs->gp.r.cmd_read, par->gp_regs + 0x58);
3614 + writel(regs->gp.r.cmd_write, par->gp_regs + 0x5C);
3615 + writel(regs->gp.r.ch3_offset, par->gp_regs + 0x60);
3616 + writel(regs->gp.r.ch3_mode_str, par->gp_regs + 0x64);
3617 + writel(regs->gp.r.ch3_width, par->gp_regs + 0x6C);
3618 + writel(regs->gp.r.ch3_hsrc, par->gp_regs + 0x70);
3619 +
3620 + /* FIXME: Restore the LUT data here */
3621 +
3622 + writel(regs->gp.r.int_cntrl, par->gp_regs + 0x70);
3623 +
3624 + /* == DC == */
3625 +
3626 + /* Write the unlock value */
3627 + writel(0x4758, par->dc_regs + 0x00);
3628 +
3629 + /* Write the palette data first */
3630 +
3631 + writel(0, par->dc_regs + 0x70);
3632 +
3633 + for(i = 0; i < DC_PAL_SIZE; i++)
3634 + writel(regs->pal[i], par->dc_regs + 0x74);
3635 +
3636 + /* MSRs */
3637 + wrmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3638 +
3639 + /* Write the gcfg register without the enables */
3640 + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
3641 +
3642 + /* Write the vcfg register without the enables */
3643 + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
3644 +
3645 + /* Write the rest of the active registers */
3646 + writel(regs->dc.r.arb, par->dc_regs + 0x0C);
3647 + writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10);
3648 + writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14);
3649 + writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18);
3650 + writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C);
3651 + writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20);
3652 + writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24);
3653 + writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28);
3654 + writel(regs->dc.r.dctop, par->dc_regs + 0x2c);
3655 + writel(regs->dc.r.line_size, par->dc_regs + 0x30);
3656 + writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34);
3657 + writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38);
3658 + writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40);
3659 + writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44);
3660 + writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48);
3661 + writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50);
3662 + writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54);
3663 + writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58);
3664 + writel(regs->dc.r.fbactive, par->dc_regs + 0x5c);
3665 + writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60);
3666 + writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64);
3667 + writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68);
3668 +
3669 + /* Skip register 0x6C (line_cnt), 0x70/0x74 (palette),
3670 + 0x78 (diagnostic), and 0x7c (diagnostic)
3671 + */
3672 +
3673 + writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80);
3674 + writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84);
3675 + writel(regs->dc.r.dv_ctl, par->dc_regs + 0x88);
3676 + writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C);
3677 +
3678 + writel(regs->dc.r.gfx_scale, par->dc_regs + 0x90);
3679 + writel(regs->dc.r.irq_filt_ctl, par->dc_regs + 0x94);
3680 + writel(regs->dc.r.filt_coeff1, par->dc_regs + 0x98);
3681 + writel(regs->dc.r.filt_coeff2, par->dc_regs + 0x9C);
3682 + writel(regs->dc.r.vbi_event_ctl, par->dc_regs + 0xA0);
3683 +
3684 + writel(regs->dc.r.vbi_odd_ctl, par->dc_regs + 0xA4);
3685 + writel(regs->dc.r.vbi_hor, par->dc_regs + 0xA8);
3686 + writel(regs->dc.r.vbi_ln_odd, par->dc_regs + 0xAC);
3687 + writel(regs->dc.r.vbi_ln_event, par->dc_regs + 0xB0);
3688 + writel(regs->dc.r.vbi_pitch, par->dc_regs + 0xB4);
3689 + writel(regs->dc.r.clr_key, par->dc_regs + 0xB8);
3690 + writel(regs->dc.r.clr_key_mask, par->dc_regs + 0xBC);
3691 +
3692 + writel(regs->dc.r.clr_key_x, par->dc_regs + 0xC0);
3693 + writel(regs->dc.r.clr_key_y, par->dc_regs + 0xC4);
3694 + writel(regs->dc.r.irq, par->dc_regs + 0xC8);
3695 + writel(regs->dc.r.genlk_ctrl, par->dc_regs + 0xD4);
3696 +
3697 + writel(regs->dc.r.vid_even_y_st_offset, par->dc_regs + 0xD8);
3698 + writel(regs->dc.r.vid_even_u_st_offset, par->dc_regs + 0xDC);
3699 + writel(regs->dc.r.vid_even_v_st_offset, par->dc_regs + 0xE0);
3700 +
3701 + writel(regs->dc.r.v_active_even_timing, par->dc_regs + 0xE4);
3702 + writel(regs->dc.r.v_blank_even_timing, par->dc_regs + 0xE8);
3703 + writel(regs->dc.r.v_sync_even_timing, par->dc_regs + 0xEC);
3704 +
3705 + /* == VP == */
3706 +
3707 + /* MSR */
3708 + wrmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3709 +
3710 + /* Write gamma information first */
3711 +
3712 + writel(0, par->df_regs + 0x38);
3713 +
3714 + for(i = 0; i <= 0xFF; i++)
3715 + writel((u32) regs->gamma[i], par->df_regs + 0x40);
3716 +
3717 + /* Don't enable video yet */
3718 + writel((u32) regs->vp.r.vcfg & ~0x01, par->df_regs + 0x00);
3719 +
3720 + /* Don't enable the CRT yet */
3721 + writel((u32) regs->vp.r.dcfg & ~0x0F, par->df_regs + 0x08);
3722 +
3723 + /* Write the rest of the VP registers */
3724 +
3725 + writel((u32) regs->vp.r.vx, par->df_regs + 0x10);
3726 + writel((u32) regs->vp.r.vy, par->df_regs + 0x18);
3727 + writel((u32) regs->vp.r.vs, par->df_regs + 0x20);
3728 + writel((u32) regs->vp.r.vck, par->df_regs + 0x28);
3729 + writel((u32) regs->vp.r.vcm, par->df_regs + 0x30);
3730 + writel((u32) regs->vp.r.misc, par->df_regs + 0x50);
3731 + writel((u32) regs->vp.r.ccs, par->df_regs + 0x58);
3732 + writel((u32) regs->vp.r.vdc, par->df_regs + 0x78);
3733 + writel((u32) regs->vp.r.vco, par->df_regs + 0x80);
3734 + writel((u32) regs->vp.r.crc, par->df_regs + 0x88);
3735 + writel((u32) regs->vp.r.vde, par->df_regs + 0x98);
3736 + writel((u32) regs->vp.r.cck, par->df_regs + 0xA0);
3737 + writel((u32) regs->vp.r.ccm, par->df_regs + 0xA8);
3738 + writel((u32) regs->vp.r.cc1, par->df_regs + 0xB0);
3739 + writel((u32) regs->vp.r.cc2, par->df_regs + 0xB8);
3740 + writel((u32) regs->vp.r.a1x, par->df_regs + 0xC0);
3741 + writel((u32) regs->vp.r.a1y, par->df_regs + 0xC8);
3742 + writel((u32) regs->vp.r.a1c, par->df_regs + 0xD0);
3743 + writel((u32) regs->vp.r.a1t, par->df_regs + 0xD8);
3744 + writel((u32) regs->vp.r.a2x, par->df_regs + 0xE0);
3745 + writel((u32) regs->vp.r.a2y, par->df_regs + 0xE8);
3746 + writel((u32) regs->vp.r.a2c, par->df_regs + 0xF0);
3747 + writel((u32) regs->vp.r.a2t, par->df_regs + 0xF8);
3748 + writel((u32) regs->vp.r.a3x, par->df_regs + 0x100);
3749 + writel((u32) regs->vp.r.a3y, par->df_regs + 0x108);
3750 + writel((u32) regs->vp.r.a3c, par->df_regs + 0x110);
3751 + writel((u32) regs->vp.r.a3t, par->df_regs + 0x118);
3752 + writel((u32) regs->vp.r.vrr, par->df_regs + 0x120);
3753 +
3754 + writel((u32) regs->vp.r.vye, par->df_regs + 0x138);
3755 + writel((u32) regs->vp.r.a1ye, par->df_regs + 0x140);
3756 + writel((u32) regs->vp.r.a2ye, par->df_regs + 0x148);
3757 + writel((u32) regs->vp.r.a3ye, par->df_regs + 0x150);
3758 +
3759 + /* == FP == */
3760 +
3761 + writel((u32) regs->fp.r.pt1, par->df_regs + 0x400);
3762 + writel((u32) regs->fp.r.pt2, par->df_regs + 0x408);
3763 + writel((u32) regs->fp.r.dfc, par->df_regs + 0x418);
3764 + writel(regs->fp.r.dca, par->df_regs + 0x448);
3765 + writel(regs->fp.r.dmd, par->df_regs + 0x450);
3766 + writel(regs->fp.r.crc, par->df_regs + 0x458);
3767 +
3768 + /* Final enables */
3769 +
3770 + val = readl(par->df_regs + 0x410);
3771 +
3772 + /* Control the panel */
3773 + if (regs->fp.r.pm & (1 << 24)) {
3774 +
3775 + if (!(val & 0x09))
3776 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3777 + }
3778 + else {
3779 + if (!(val & 0x05))
3780 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3781 + }
3782 +
3783 + /* Turn everything on */
3784 +
3785 + writel(regs->dc.r.gcfg, par->dc_regs + 0x04);
3786 + writel((u32) regs->vp.r.vcfg, par->df_regs + 0x00);
3787 + writel((u32) regs->vp.r.dcfg, par->df_regs + 0x08);
3788 + writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
3789 +}
3790 +
3791 +static int lx_power_on = 1;
3792 +
3793 +int lx_shutdown(struct fb_info *info)
3794 +{
3795 + struct lxfb_par *par = info->par;
3796 +
3797 + if (lx_power_on == 0)
3798 + return 0;
3799 +
3800 + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3801 + lx_save_regs(info, &saved_regs);
3802 + lx_graphics_disable(info);
3803 +
3804 + lx_power_on = 0;
3805 + return 0;
3806 +}
3807 +
3808 +int lx_powerup(struct fb_info *info)
3809 +{
3810 + struct lxfb_par *par = info->par;
3811 +
3812 + if (lx_power_on == 1)
3813 + return 0;
3814 +
3815 + lx_restore_regs(info, &saved_regs);
3816 + writel(0, par->dc_regs + DC_UNLOCK);
3817 +
3818 + lx_power_on = 1;
3819 + return 0;
3820 +}
3821 Index: linux-2.6.23.17/drivers/video/geode/video_gx.c
3822 ===================================================================
3823 --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.c
3824 +++ linux-2.6.23.17/drivers/video/geode/video_gx.c
3825 @@ -16,10 +16,14 @@
3826 #include <asm/io.h>
3827 #include <asm/delay.h>
3828 #include <asm/msr.h>
3829 +#include <asm/olpc.h>
3830
3831 #include "geodefb.h"
3832 #include "video_gx.h"
3833 +#include "display_gx.h"
3834
3835 +/* This structure is used to store the saved registers during suspend */
3836 +static struct geoderegs gx_saved_regs;
3837
3838 /*
3839 * Tables of register settings for various DOTCLKs.
3840 @@ -58,7 +62,7 @@ static const struct gx_pll_entry gx_pll_
3841 { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
3842 { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
3843 { 13333, 0, 0x00000052 }, /* 75.0000 */
3844 - { 12698, 0, 0x00000056 }, /* 78.7500 */
3845 + { 12698, 0, 0x00000056 }, /* 78.7500 */
3846 { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
3847 { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
3848 { 10582, 0, 0x000002D2 }, /* 94.5000 */
3849 @@ -117,8 +121,9 @@ static const struct gx_pll_entry gx_pll_
3850 { 4357, 0, 0x0000057D }, /* 229.5000 */
3851 };
3852
3853 -static void gx_set_dclk_frequency(struct fb_info *info)
3854 +void gx_set_dclk_frequency(struct fb_info *info)
3855 {
3856 + struct geodefb_par *par = info->par;
3857 const struct gx_pll_entry *pll_table;
3858 int pll_table_len;
3859 int i, best_i;
3860 @@ -173,115 +178,169 @@ static void gx_set_dclk_frequency(struct
3861 do {
3862 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3863 } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
3864 +
3865 + par->curdclk = pll_table[best_i].dotpll_value;
3866 }
3867
3868 -static void
3869 -gx_configure_tft(struct fb_info *info)
3870 +/* Find out the current clock - we will use this information to avoid
3871 + re-programming it if we don't need to */
3872 +
3873 +unsigned int gx_get_dclk(struct fb_info *info)
3874 {
3875 - struct geodefb_par *par = info->par;
3876 - unsigned long val;
3877 - unsigned long fp;
3878 + const struct gx_pll_entry *pll_table;
3879 + int pll_table_len;
3880 + u64 dotpll;
3881 + int i;
3882
3883 - /* Set up the DF pad select MSR */
3884 + if (cpu_data->x86_mask == 1) {
3885 + pll_table = gx_pll_table_14MHz;
3886 + pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
3887 + } else {
3888 + pll_table = gx_pll_table_48MHz;
3889 + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
3890 + }
3891
3892 - rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3893 - val &= ~GX_VP_PAD_SELECT_MASK;
3894 - val |= GX_VP_PAD_SELECT_TFT;
3895 - wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3896 + rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3897
3898 - /* Turn off the panel */
3899 + for(i = 0; i < pll_table_len; i++) {
3900 + if (pll_table[i].dotpll_value == (u32) (dotpll >> 32))
3901 + break;
3902 + }
3903 +
3904 + return (i == pll_table_len) ? 0 : pll_table[i].pixclock;
3905 +}
3906
3907 - fp = readl(par->vid_regs + GX_FP_PM);
3908 - fp &= ~GX_FP_PM_P;
3909 - writel(fp, par->vid_regs + GX_FP_PM);
3910
3911 - /* Set timing 1 */
3912 +#define CMP(val, mask, res) (((val) & (mask)) == (res))
3913
3914 - fp = readl(par->vid_regs + GX_FP_PT1);
3915 - fp &= GX_FP_PT1_VSIZE_MASK;
3916 - fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
3917 - writel(fp, par->vid_regs + GX_FP_PT1);
3918 +static void
3919 +gx_configure_tft(struct fb_info *info) {
3920
3921 - /* Timing 2 */
3922 - /* Set bits that are always on for TFT */
3923 + struct geodefb_par *par = info->par;
3924 + u32 val, fp = 0, fp1, fp2, sync = 0;
3925
3926 - fp = 0x0F100000;
3927 + /* Set up the DF pad select MSR */
3928
3929 - /* Add sync polarity */
3930 + rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3931 +
3932 + if ((val & GX_VP_PAD_SELECT_MASK) != GX_VP_PAD_SELECT_TFT) {
3933 + val &= ~GX_VP_PAD_SELECT_MASK;
3934 + val |= GX_VP_PAD_SELECT_TFT;
3935 + wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3936 + }
3937
3938 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
3939 - fp |= GX_FP_PT2_VSP;
3940 + sync |= GX_FP_PT2_VSP;
3941
3942 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
3943 - fp |= GX_FP_PT2_HSP;
3944 + sync |= GX_FP_PT2_HSP;
3945
3946 - writel(fp, par->vid_regs + GX_FP_PT2);
3947 + /* We only need to turn off the panel if something changed */
3948
3949 - /* Set the dither control */
3950 - writel(0x70, par->vid_regs + GX_FP_DFC);
3951 + fp1 = readl(par->vid_regs + GX_FP_PT1);
3952 + fp2 = readl(par->vid_regs + GX_FP_PT2);
3953 +
3954 + if (!CMP(fp1, GX_FP_PT1_VSIZE_MASK, info->var.yres << GX_FP_PT1_VSIZE_SHIFT) ||
3955 + (fp2 != (0x0F100000 | sync))) {
3956 +
3957 + /* Turn off the panel */
3958 +
3959 +#ifdef NOTUSED
3960 + /* Do we really need to turn off the panel? */
3961 + /* Possibly - we have a glitch somewhere */
3962
3963 - /* Enable the FP data and power (in case the BIOS didn't) */
3964 + fp = readl(par->vid_regs + GX_FP_PM);
3965 + fp &= ~GX_FP_PM_P;
3966 + writel(fp, par->vid_regs + GX_FP_PM);
3967 +#endif
3968
3969 - fp = readl(par->vid_regs + GX_DCFG);
3970 - fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
3971 - writel(fp, par->vid_regs + GX_DCFG);
3972 + /* Timing 1 */
3973 + fp1 &= GX_FP_PT1_VSIZE_MASK;
3974 + fp1 |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
3975 + writel(fp, par->vid_regs + GX_FP_PT1);
3976
3977 - /* Unblank the panel */
3978 + /* Timing 2 */
3979 + writel(0x0F100000 | sync, par->vid_regs + GX_FP_PT2);
3980 + }
3981 +
3982 + /* Set the dither control */
3983 + if (readl(par->vid_regs + GX_FP_DFC) != 0x70) {
3984 + writel(0x70, par->vid_regs + GX_FP_DFC);
3985 + }
3986 +
3987 + /* Turn on the panel */
3988
3989 fp = readl(par->vid_regs + GX_FP_PM);
3990 - fp |= GX_FP_PM_P;
3991 - writel(fp, par->vid_regs + GX_FP_PM);
3992 +
3993 + if (!(fp & 0x09))
3994 + writel(fp | GX_FP_PM_P, par->vid_regs + GX_FP_PM);
3995 }
3996
3997 +#define DCFG_DEFAULT_VAL GX_DCFG_CRT_SYNC_SKW_DFLT | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN | \
3998 +GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN
3999 +
4000 static void gx_configure_display(struct fb_info *info)
4001 {
4002 struct geodefb_par *par = info->par;
4003 - u32 dcfg, misc;
4004 + u32 dcfg, misc, sync = 0;
4005
4006 /* Set up the MISC register */
4007 -
4008 misc = readl(par->vid_regs + GX_MISC);
4009
4010 - /* Power up the DAC */
4011 - misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4012 + /* We leave gamma enabled if it was already enabled.
4013 + Although the hardware enables it without setting
4014 + up the gamma table, the BIOS or bootloader ought
4015 + to have either disabled it or loaded a table by now */
4016
4017 - /* Disable gamma correction */
4018 - misc |= GX_MISC_GAM_EN;
4019
4020 - writel(misc, par->vid_regs + GX_MISC);
4021
4022 - /* Write the display configuration */
4023 - dcfg = readl(par->vid_regs + GX_DCFG);
4024 + if (par->enable_crt) {
4025 + /* Power up the CRT DACs */
4026 + if (misc & ( GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN)) {
4027 + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4028 + writel(misc, par->vid_regs + GX_MISC);
4029 + }
4030
4031 - /* Disable hsync and vsync */
4032 - dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4033 - writel(dcfg, par->vid_regs + GX_DCFG);
4034 + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
4035 + sync |= GX_DCFG_CRT_HSYNC_POL;
4036
4037 - /* Clear bits from existing mode. */
4038 - dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4039 - | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4040 - | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4041 + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
4042 + sync |= GX_DCFG_CRT_VSYNC_POL;
4043 + }
4044 + else {
4045 + /* Turn off the CRT DACs in FP mode - we don't need them */
4046 + if ((misc & (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN))) {
4047 + misc |= (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4048 + writel(misc, par->vid_regs + GX_MISC);
4049 + }
4050 + }
4051
4052 - /* Set default sync skew. */
4053 - dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4054 + /* Write the display configuration */
4055 + dcfg = readl(par->vid_regs + GX_DCFG);
4056
4057 - /* Enable hsync and vsync. */
4058 - dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4059 + if (!CMP(dcfg, DCFG_DEFAULT_VAL | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL,
4060 + DCFG_DEFAULT_VAL | sync)) {
4061
4062 - /* Sync polarities. */
4063 - if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
4064 - dcfg |= GX_DCFG_CRT_HSYNC_POL;
4065 - if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
4066 - dcfg |= GX_DCFG_CRT_VSYNC_POL;
4067 + /* Disable hsync and vsync */
4068 + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4069 + writel(dcfg, par->vid_regs + GX_DCFG);
4070
4071 - /* Enable the display logic */
4072 - /* Set up the DACS to blank normally */
4073 + /* Clear bits from existing mode. */
4074 + dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4075 + | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4076 + | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4077
4078 - dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4079 + /* Set default sync skew. */
4080 + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4081
4082 - /* Enable the external DAC VREF? */
4083 + /* Enable hsync and vsync. */
4084 + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4085
4086 - writel(dcfg, par->vid_regs + GX_DCFG);
4087 + /* Enable the display logic */
4088 + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4089 +
4090 + writel(dcfg, par->vid_regs + GX_DCFG);
4091 + }
4092
4093 /* Set up the flat panel (if it is enabled) */
4094
4095 @@ -289,6 +348,100 @@ static void gx_configure_display(struct
4096 gx_configure_tft(info);
4097 }
4098
4099 +int gxfb_powerdown(struct fb_info *info)
4100 +{
4101 + struct geodefb_par *par = info->par;
4102 +
4103 + /* We're already suspended */
4104 +
4105 + if (par->state != FB_POWER_STATE_ON)
4106 + return 0;
4107 +
4108 + /* Save the registers */
4109 + gx_save_regs(info, &gx_saved_regs);
4110 +
4111 + /* Shut down the engine */
4112 +
4113 + writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + GX_VCFG);
4114 + writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + GX_DCFG);
4115 +
4116 + /* Turn off the flat panel unless we are attached to a DCON */
4117 + if (!olpc_has_dcon())
4118 + writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, par->vid_regs + GX_FP_PM);
4119 +
4120 + writel(0x4758, par->dc_regs + DC_UNLOCK);
4121 +
4122 + writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
4123 + par->dc_regs + DC_GENERAL_CFG);
4124 +
4125 + writel(gx_saved_regs.dc.r.dcfg & ~0x19,
4126 + par->dc_regs + DC_DISPLAY_CFG);
4127 +
4128 + par->state = FB_POWER_STATE_SUSPEND;
4129 +
4130 + return 0;
4131 +}
4132 +
4133 +int gxfb_powerup(struct fb_info *info)
4134 +{
4135 + struct geodefb_par *par = info->par;
4136 + u32 val;
4137 +
4138 + if (par->state == FB_POWER_STATE_SUSPEND) {
4139 +
4140 + writel(gx_saved_regs.dc.r.dcfg,
4141 + par->dc_regs + DC_DISPLAY_CFG);
4142 +
4143 + writel(gx_saved_regs.vp.r.vcfg, par->vid_regs + GX_VCFG);
4144 + writel(gx_saved_regs.vp.r.dcfg, par->vid_regs + GX_DCFG);
4145 +
4146 + val = readl(par->vid_regs + GX_FP_PM);
4147 +
4148 + /* power up the panel if it needs it; we don't always power it down */
4149 + if (!(val & 0x09)) {
4150 + writel(gx_saved_regs.fp.r.pm, par->vid_regs + GX_FP_PM);
4151 + mdelay(64);
4152 + }
4153 + }
4154 +
4155 + /* If the panel is currently on its way up, then wait up to 100ms
4156 + for it */
4157 +
4158 + if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
4159 + int i;
4160 +
4161 + for(i = 0; i < 10; i++) {
4162 + if (readl(par->vid_regs + GX_FP_PM) & 0x01)
4163 + break;
4164 +
4165 + mdelay(10);
4166 + }
4167 +
4168 + if (i == 10)
4169 + printk(KERN_ERR "gxfb: Panel power up timed out\n");
4170 + }
4171 +
4172 + if (par->state == FB_POWER_STATE_ON)
4173 + return 0;
4174 +
4175 + switch(par->state) {
4176 + case FB_POWER_STATE_OFF:
4177 + gx_restore_regs(info, &gx_saved_regs);
4178 + break;
4179 +
4180 + case FB_POWER_STATE_SUSPEND:
4181 + /* Do this because it will turn on the FIFO which will
4182 + start the line count */
4183 + writel(gx_saved_regs.dc.r.gcfg,
4184 + par->dc_regs + DC_GENERAL_CFG);
4185 + writel(0x0, par->dc_regs + DC_UNLOCK);
4186 + break;
4187 + }
4188 +
4189 + par->state = FB_POWER_STATE_ON;
4190 + return 0;
4191 +}
4192 +
4193 static int gx_blank_display(struct fb_info *info, int blank_mode)
4194 {
4195 struct geodefb_par *par = info->par;
4196 @@ -315,6 +468,7 @@ static int gx_blank_display(struct fb_in
4197 default:
4198 return -EINVAL;
4199 }
4200 +
4201 dcfg = readl(par->vid_regs + GX_DCFG);
4202 dcfg &= ~(GX_DCFG_DAC_BL_EN
4203 | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
4204 @@ -326,7 +480,7 @@ static int gx_blank_display(struct fb_in
4205 dcfg |= GX_DCFG_VSYNC_EN;
4206 writel(dcfg, par->vid_regs + GX_DCFG);
4207
4208 - /* Power on/off flat panel. */
4209 + /* Power on/off flat panel */
4210
4211 if (par->enable_crt == 0) {
4212 fp_pm = readl(par->vid_regs + GX_FP_PM);
4213 @@ -340,8 +494,37 @@ static int gx_blank_display(struct fb_in
4214 return 0;
4215 }
4216
4217 +extern struct fb_info *gxfb_info;
4218 +
4219 +/* This function controls the flatpanel power sequencing - this is used
4220 + by the OLPC power management engine to enable the FP sequencing much
4221 + earlier in the resume process
4222 +*/
4223 +
4224 +void gxfb_flatpanel_control(int state)
4225 +{
4226 + struct geodefb_par *par = gxfb_info->par;
4227 + u32 val, fp = readl(par->vid_regs + GX_FP_PM);
4228 + val = fp;
4229 +
4230 + /* Turn on the panel if it isn't aleady */
4231 +
4232 + if (state) {
4233 + if (!(val & 0x01))
4234 + val |= GX_FP_PM_P;
4235 + }
4236 + else {
4237 + if (!(val & 0x02))
4238 + val &= ~GX_FP_PM_P;
4239 + }
4240 +
4241 + if (val != fp)
4242 + writel(val, par->vid_regs + GX_FP_PM);
4243 +}
4244 +
4245 struct geode_vid_ops gx_vid_ops = {
4246 .set_dclk = gx_set_dclk_frequency,
4247 + .get_dclk = gx_get_dclk,
4248 .configure_display = gx_configure_display,
4249 .blank_display = gx_blank_display,
4250 };
4251 Index: linux-2.6.23.17/drivers/video/geode/video_gx.h
4252 ===================================================================
4253 --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.h
4254 +++ linux-2.6.23.17/drivers/video/geode/video_gx.h
4255 @@ -11,6 +11,8 @@
4256 #ifndef __VIDEO_GX_H__
4257 #define __VIDEO_GX_H__
4258
4259 +#include "geode_regs.h"
4260 +
4261 extern struct geode_vid_ops gx_vid_ops;
4262
4263 /* GX Flatpanel control MSR */
4264 @@ -20,6 +22,8 @@ extern struct geode_vid_ops gx_vid_ops;
4265
4266 /* Geode GX video processor registers */
4267
4268 +#define GX_VCFG 0x0000
4269 +
4270 #define GX_DCFG 0x0008
4271 # define GX_DCFG_CRT_EN 0x00000001
4272 # define GX_DCFG_HSYNC_EN 0x00000002
4273 @@ -42,6 +46,14 @@ extern struct geode_vid_ops gx_vid_ops;
4274 #define GX_MISC_DAC_PWRDN 0x00000400
4275 #define GX_MISC_A_PWRDN 0x00000800
4276
4277 +/* Gamma correction RAM - address and data registers */
4278 +
4279 +#define GX_GAR 0x038
4280 +#define GX_GDR 0x040
4281 +
4282 +#define GXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
4283 +#define GXFB_GAMMA_SIZE (GXFB_GAMMA_DWORDS * sizeof(unsigned int))
4284 +
4285 /* Geode GX flat panel display control registers */
4286
4287 #define GX_FP_PT1 0x0400
4288 @@ -69,4 +81,13 @@ extern struct geode_vid_ops gx_vid_ops;
4289 # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
4290 # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
4291
4292 +int gxfb_powerdown(struct fb_info *info);
4293 +int gxfb_powerup(struct fb_info *info);
4294 +
4295 +void gx_set_dclk_frequency(struct fb_info *info);
4296 +unsigned int gx_get_dclk(struct fb_info *info);
4297 +
4298 +void gx_save_regs(struct fb_info *info, struct geoderegs *regs);
4299 +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs);
4300 +
4301 #endif /* !__VIDEO_GX_H__ */
4302 Index: linux-2.6.23.17/drivers/video/modedb.c
4303 ===================================================================
4304 --- linux-2.6.23.17.orig/drivers/video/modedb.c
4305 +++ linux-2.6.23.17/drivers/video/modedb.c
4306 @@ -33,6 +33,8 @@ const char *global_mode_option;
4307 * Standard video mode definitions (taken from XFree86)
4308 */
4309
4310 +#define DEFAULT_MODEDB_INDEX 0
4311 +
4312 static const struct fb_videomode modedb[] = {
4313 {
4314 /* 640x400 @ 70 Hz, 31.5 kHz hsync */
4315 @@ -504,7 +506,8 @@ int fb_find_mode(struct fb_var_screeninf
4316 }
4317
4318 if (!default_mode)
4319 - default_mode = &db[0];
4320 + default_mode = (db == modedb) ?
4321 + &modedb[DEFAULT_MODEDB_INDEX] : &db[0];
4322
4323 if (!default_bpp)
4324 default_bpp = 8;
4325 Index: linux-2.6.23.17/fs/Kconfig
4326 ===================================================================
4327 --- linux-2.6.23.17.orig/fs/Kconfig
4328 +++ linux-2.6.23.17/fs/Kconfig
4329 @@ -1003,6 +1003,23 @@ config HUGETLBFS
4330 config HUGETLB_PAGE
4331 def_bool HUGETLBFS
4332
4333 +config PROMFS_FS
4334 + tristate "PromFS IEEE 1275 file system support"
4335 + depends on SPARC || PPC || OLPC
4336 + help
4337 + PromFS is a file system interface to various IEEE-1275 compatible
4338 + firmwares. If you have such a firmware (Sparc64, PowerPC, and
4339 + some other architectures and embedded systems have such firmwares,
4340 + with names like "OpenBoot (tm)" and "OpenFirmware"), say Y here
4341 + to be able to access the firmware's device-tree from Linux.
4342 +
4343 + The firmware device-tree is available as a virtual file system,
4344 + can be mounted under /prom with the command "mount -t promfs
4345 + none /prom".
4346 +
4347 + To compile PromFS support as a module, choose M here; the module
4348 + will be called promfs. If unsure, choose M.
4349 +
4350 config RAMFS
4351 bool
4352 default y
4353 @@ -1229,6 +1246,14 @@ config JFFS2_FS_WRITEBUFFER
4354 - NOR flash with transparent ECC
4355 - DataFlash
4356
4357 +config JFFS2_FS_WBUF_VERIFY
4358 + bool "Verify JFFS2 write-buffer reads"
4359 + depends on JFFS2_FS_WRITEBUFFER
4360 + default n
4361 + help
4362 + This causes JFFS2 to read back every page written through the
4363 + write-buffer, and check for errors.
4364 +
4365 config JFFS2_SUMMARY
4366 bool "JFFS2 summary support (EXPERIMENTAL)"
4367 depends on JFFS2_FS && EXPERIMENTAL
4368 @@ -1299,52 +1324,52 @@ config JFFS2_ZLIB
4369 select ZLIB_DEFLATE
4370 depends on JFFS2_FS
4371 default y
4372 - help
4373 - Zlib is designed to be a free, general-purpose, legally unencumbered,
4374 - lossless data-compression library for use on virtually any computer
4375 - hardware and operating system. See <http://www.gzip.org/zlib/> for
4376 - further information.
4377 + help
4378 + Zlib is designed to be a free, general-purpose, legally unencumbered,
4379 + lossless data-compression library for use on virtually any computer
4380 + hardware and operating system. See <http://www.gzip.org/zlib/> for
4381 + further information.
4382
4383 - Say 'Y' if unsure.
4384 + Say 'Y' if unsure.
4385
4386 config JFFS2_RTIME
4387 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
4388 depends on JFFS2_FS
4389 default y
4390 - help
4391 - Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4392 + help
4393 + Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4394
4395 config JFFS2_RUBIN
4396 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
4397 depends on JFFS2_FS
4398 default n
4399 - help
4400 - RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4401 + help
4402 + RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4403
4404 choice
4405 - prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4406 - default JFFS2_CMODE_PRIORITY
4407 - depends on JFFS2_FS
4408 - help
4409 - You can set here the default compression mode of JFFS2 from
4410 - the available compression modes. Don't touch if unsure.
4411 + prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4412 + default JFFS2_CMODE_PRIORITY
4413 + depends on JFFS2_FS
4414 + help
4415 + You can set here the default compression mode of JFFS2 from
4416 + the available compression modes. Don't touch if unsure.
4417
4418 config JFFS2_CMODE_NONE
4419 - bool "no compression"
4420 - help
4421 - Uses no compression.
4422 + bool "no compression"
4423 + help
4424 + Uses no compression.
4425
4426 config JFFS2_CMODE_PRIORITY
4427 - bool "priority"
4428 - help
4429 - Tries the compressors in a predefined order and chooses the first
4430 - successful one.
4431 + bool "priority"
4432 + help
4433 + Tries the compressors in a predefined order and chooses the first
4434 + successful one.
4435
4436 config JFFS2_CMODE_SIZE
4437 - bool "size (EXPERIMENTAL)"
4438 - help
4439 - Tries all compressors and chooses the one which has the smallest
4440 - result.
4441 + bool "size (EXPERIMENTAL)"
4442 + help
4443 + Tries all compressors and chooses the one which has the smallest
4444 + result.
4445
4446 endchoice
4447
4448 Index: linux-2.6.23.17/fs/Makefile
4449 ===================================================================
4450 --- linux-2.6.23.17.orig/fs/Makefile
4451 +++ linux-2.6.23.17/fs/Makefile
4452 @@ -110,6 +110,7 @@ obj-$(CONFIG_ADFS_FS) += adfs/
4453 obj-$(CONFIG_FUSE_FS) += fuse/
4454 obj-$(CONFIG_UDF_FS) += udf/
4455 obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
4456 +obj-$(CONFIG_PROMFS_FS) += promfs/
4457 obj-$(CONFIG_JFS_FS) += jfs/
4458 obj-$(CONFIG_XFS_FS) += xfs/
4459 obj-$(CONFIG_9P_FS) += 9p/
4460 Index: linux-2.6.23.17/fs/jffs2/background.c
4461 ===================================================================
4462 --- linux-2.6.23.17.orig/fs/jffs2/background.c
4463 +++ linux-2.6.23.17/fs/jffs2/background.c
4464 @@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(
4465 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
4466 {
4467 spin_lock(&c->erase_completion_lock);
4468 - if (c->gc_task && jffs2_thread_should_wake(c))
4469 - send_sig(SIGHUP, c->gc_task, 1);
4470 + if (c->gc_task && jffs2_thread_should_wake(c))
4471 + send_sig(SIGHUP, c->gc_task, 1);
4472 spin_unlock(&c->erase_completion_lock);
4473 }
4474
4475 Index: linux-2.6.23.17/fs/jffs2/compr.c
4476 ===================================================================
4477 --- linux-2.6.23.17.orig/fs/jffs2/compr.c
4478 +++ linux-2.6.23.17/fs/jffs2/compr.c
4479 @@ -5,7 +5,7 @@
4480 * Created by Arjan van de Ven <arjanv@redhat.com>
4481 *
4482 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4483 - * University of Szeged, Hungary
4484 + * University of Szeged, Hungary
4485 *
4486 * For licensing information, see the file 'LICENCE' in this directory.
4487 *
4488 @@ -43,121 +43,122 @@ static uint32_t none_stat_compr_blocks=0
4489 * *datalen accordingly to show the amount of data which were compressed.
4490 */
4491 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4492 - unsigned char *data_in, unsigned char **cpage_out,
4493 - uint32_t *datalen, uint32_t *cdatalen)
4494 + unsigned char *data_in, unsigned char **cpage_out,
4495 + uint32_t *datalen, uint32_t *cdatalen)
4496 {
4497 int ret = JFFS2_COMPR_NONE;
4498 - int compr_ret;
4499 - struct jffs2_compressor *this, *best=NULL;
4500 - unsigned char *output_buf = NULL, *tmp_buf;
4501 - uint32_t orig_slen, orig_dlen;
4502 - uint32_t best_slen=0, best_dlen=0;
4503 -
4504 - switch (jffs2_compression_mode) {
4505 - case JFFS2_COMPR_MODE_NONE:
4506 - break;
4507 - case JFFS2_COMPR_MODE_PRIORITY:
4508 - output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4509 - if (!output_buf) {
4510 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4511 - goto out;
4512 - }
4513 - orig_slen = *datalen;
4514 - orig_dlen = *cdatalen;
4515 - spin_lock(&jffs2_compressor_list_lock);
4516 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4517 - /* Skip decompress-only backwards-compatibility and disabled modules */
4518 - if ((!this->compress)||(this->disabled))
4519 - continue;
4520 -
4521 - this->usecount++;
4522 - spin_unlock(&jffs2_compressor_list_lock);
4523 - *datalen = orig_slen;
4524 - *cdatalen = orig_dlen;
4525 - compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4526 - spin_lock(&jffs2_compressor_list_lock);
4527 - this->usecount--;
4528 - if (!compr_ret) {
4529 - ret = this->compr;
4530 - this->stat_compr_blocks++;
4531 - this->stat_compr_orig_size += *datalen;
4532 - this->stat_compr_new_size += *cdatalen;
4533 - break;
4534 - }
4535 - }
4536 - spin_unlock(&jffs2_compressor_list_lock);
4537 - if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
4538 - break;
4539 - case JFFS2_COMPR_MODE_SIZE:
4540 - orig_slen = *datalen;
4541 - orig_dlen = *cdatalen;
4542 - spin_lock(&jffs2_compressor_list_lock);
4543 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4544 - /* Skip decompress-only backwards-compatibility and disabled modules */
4545 - if ((!this->compress)||(this->disabled))
4546 - continue;
4547 - /* Allocating memory for output buffer if necessary */
4548 - if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4549 - spin_unlock(&jffs2_compressor_list_lock);
4550 - kfree(this->compr_buf);
4551 - spin_lock(&jffs2_compressor_list_lock);
4552 - this->compr_buf_size=0;
4553 - this->compr_buf=NULL;
4554 - }
4555 - if (!this->compr_buf) {
4556 - spin_unlock(&jffs2_compressor_list_lock);
4557 - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4558 - spin_lock(&jffs2_compressor_list_lock);
4559 - if (!tmp_buf) {
4560 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4561 - continue;
4562 - }
4563 - else {
4564 - this->compr_buf = tmp_buf;
4565 - this->compr_buf_size = orig_dlen;
4566 - }
4567 - }
4568 - this->usecount++;
4569 - spin_unlock(&jffs2_compressor_list_lock);
4570 - *datalen = orig_slen;
4571 - *cdatalen = orig_dlen;
4572 - compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4573 - spin_lock(&jffs2_compressor_list_lock);
4574 - this->usecount--;
4575 - if (!compr_ret) {
4576 - if ((!best_dlen)||(best_dlen>*cdatalen)) {
4577 - best_dlen = *cdatalen;
4578 - best_slen = *datalen;
4579 - best = this;
4580 - }
4581 - }
4582 - }
4583 - if (best_dlen) {
4584 - *cdatalen = best_dlen;
4585 - *datalen = best_slen;
4586 - output_buf = best->compr_buf;
4587 - best->compr_buf = NULL;
4588 - best->compr_buf_size = 0;
4589 - best->stat_compr_blocks++;
4590 - best->stat_compr_orig_size += best_slen;
4591 - best->stat_compr_new_size += best_dlen;
4592 - ret = best->compr;
4593 - }
4594 - spin_unlock(&jffs2_compressor_list_lock);
4595 - break;
4596 - default:
4597 - printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4598 - }
4599 + int compr_ret;
4600 + struct jffs2_compressor *this, *best=NULL;
4601 + unsigned char *output_buf = NULL, *tmp_buf;
4602 + uint32_t orig_slen, orig_dlen;
4603 + uint32_t best_slen=0, best_dlen=0;
4604 +
4605 + switch (jffs2_compression_mode) {
4606 + case JFFS2_COMPR_MODE_NONE:
4607 + break;
4608 + case JFFS2_COMPR_MODE_PRIORITY:
4609 + output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4610 + if (!output_buf) {
4611 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4612 + goto out;
4613 + }
4614 + orig_slen = *datalen;
4615 + orig_dlen = *cdatalen;
4616 + spin_lock(&jffs2_compressor_list_lock);
4617 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4618 + /* Skip decompress-only backwards-compatibility and disabled modules */
4619 + if ((!this->compress)||(this->disabled))
4620 + continue;
4621 +
4622 + this->usecount++;
4623 + spin_unlock(&jffs2_compressor_list_lock);
4624 + *datalen = orig_slen;
4625 + *cdatalen = orig_dlen;
4626 + compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4627 + spin_lock(&jffs2_compressor_list_lock);
4628 + this->usecount--;
4629 + if (!compr_ret) {
4630 + ret = this->compr;
4631 + this->stat_compr_blocks++;
4632 + this->stat_compr_orig_size += *datalen;
4633 + this->stat_compr_new_size += *cdatalen;
4634 + break;
4635 + }
4636 + }
4637 + spin_unlock(&jffs2_compressor_list_lock);
4638 + if (ret == JFFS2_COMPR_NONE)
4639 + kfree(output_buf);
4640 + break;
4641 + case JFFS2_COMPR_MODE_SIZE:
4642 + orig_slen = *datalen;
4643 + orig_dlen = *cdatalen;
4644 + spin_lock(&jffs2_compressor_list_lock);
4645 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4646 + /* Skip decompress-only backwards-compatibility and disabled modules */
4647 + if ((!this->compress)||(this->disabled))
4648 + continue;
4649 + /* Allocating memory for output buffer if necessary */
4650 + if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4651 + spin_unlock(&jffs2_compressor_list_lock);
4652 + kfree(this->compr_buf);
4653 + spin_lock(&jffs2_compressor_list_lock);
4654 + this->compr_buf_size=0;
4655 + this->compr_buf=NULL;
4656 + }
4657 + if (!this->compr_buf) {
4658 + spin_unlock(&jffs2_compressor_list_lock);
4659 + tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4660 + spin_lock(&jffs2_compressor_list_lock);
4661 + if (!tmp_buf) {
4662 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4663 + continue;
4664 + }
4665 + else {
4666 + this->compr_buf = tmp_buf;
4667 + this->compr_buf_size = orig_dlen;
4668 + }
4669 + }
4670 + this->usecount++;
4671 + spin_unlock(&jffs2_compressor_list_lock);
4672 + *datalen = orig_slen;
4673 + *cdatalen = orig_dlen;
4674 + compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4675 + spin_lock(&jffs2_compressor_list_lock);
4676 + this->usecount--;
4677 + if (!compr_ret) {
4678 + if ((!best_dlen)||(best_dlen>*cdatalen)) {
4679 + best_dlen = *cdatalen;
4680 + best_slen = *datalen;
4681 + best = this;
4682 + }
4683 + }
4684 + }
4685 + if (best_dlen) {
4686 + *cdatalen = best_dlen;
4687 + *datalen = best_slen;
4688 + output_buf = best->compr_buf;
4689 + best->compr_buf = NULL;
4690 + best->compr_buf_size = 0;
4691 + best->stat_compr_blocks++;
4692 + best->stat_compr_orig_size += best_slen;
4693 + best->stat_compr_new_size += best_dlen;
4694 + ret = best->compr;
4695 + }
4696 + spin_unlock(&jffs2_compressor_list_lock);
4697 + break;
4698 + default:
4699 + printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4700 + }
4701 out:
4702 - if (ret == JFFS2_COMPR_NONE) {
4703 - *cpage_out = data_in;
4704 - *datalen = *cdatalen;
4705 - none_stat_compr_blocks++;
4706 - none_stat_compr_size += *datalen;
4707 - }
4708 - else {
4709 - *cpage_out = output_buf;
4710 - }
4711 + if (ret == JFFS2_COMPR_NONE) {
4712 + *cpage_out = data_in;
4713 + *datalen = *cdatalen;
4714 + none_stat_compr_blocks++;
4715 + none_stat_compr_size += *datalen;
4716 + }
4717 + else {
4718 + *cpage_out = output_buf;
4719 + }
4720 return ret;
4721 }
4722
4723 @@ -165,8 +166,8 @@ int jffs2_decompress(struct jffs2_sb_inf
4724 uint16_t comprtype, unsigned char *cdata_in,
4725 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
4726 {
4727 - struct jffs2_compressor *this;
4728 - int ret;
4729 + struct jffs2_compressor *this;
4730 + int ret;
4731
4732 /* Older code had a bug where it would write non-zero 'usercompr'
4733 fields. Deal with it. */
4734 @@ -177,32 +178,32 @@ int jffs2_decompress(struct jffs2_sb_inf
4735 case JFFS2_COMPR_NONE:
4736 /* This should be special-cased elsewhere, but we might as well deal with it */
4737 memcpy(data_out, cdata_in, datalen);
4738 - none_stat_decompr_blocks++;
4739 + none_stat_decompr_blocks++;
4740 break;
4741 case JFFS2_COMPR_ZERO:
4742 memset(data_out, 0, datalen);
4743 break;
4744 default:
4745 - spin_lock(&jffs2_compressor_list_lock);
4746 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4747 - if (comprtype == this->compr) {
4748 - this->usecount++;
4749 - spin_unlock(&jffs2_compressor_list_lock);
4750 - ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4751 - spin_lock(&jffs2_compressor_list_lock);
4752 - if (ret) {
4753 - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4754 - }
4755 - else {
4756 - this->stat_decompr_blocks++;
4757 - }
4758 - this->usecount--;
4759 - spin_unlock(&jffs2_compressor_list_lock);
4760 - return ret;
4761 - }
4762 - }
4763 + spin_lock(&jffs2_compressor_list_lock);
4764 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4765 + if (comprtype == this->compr) {
4766 + this->usecount++;
4767 + spin_unlock(&jffs2_compressor_list_lock);
4768 + ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4769 + spin_lock(&jffs2_compressor_list_lock);
4770 + if (ret) {
4771 + printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4772 + }
4773 + else {
4774 + this->stat_decompr_blocks++;
4775 + }
4776 + this->usecount--;
4777 + spin_unlock(&jffs2_compressor_list_lock);
4778 + return ret;
4779 + }
4780 + }
4781 printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
4782 - spin_unlock(&jffs2_compressor_list_lock);
4783 + spin_unlock(&jffs2_compressor_list_lock);
4784 return -EIO;
4785 }
4786 return 0;
4787 @@ -210,108 +211,108 @@ int jffs2_decompress(struct jffs2_sb_inf
4788
4789 int jffs2_register_compressor(struct jffs2_compressor *comp)
4790 {
4791 - struct jffs2_compressor *this;
4792 + struct jffs2_compressor *this;
4793
4794 - if (!comp->name) {
4795 - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4796 - return -1;
4797 - }
4798 - comp->compr_buf_size=0;
4799 - comp->compr_buf=NULL;
4800 - comp->usecount=0;
4801 - comp->stat_compr_orig_size=0;
4802 - comp->stat_compr_new_size=0;
4803 - comp->stat_compr_blocks=0;
4804 - comp->stat_decompr_blocks=0;
4805 - D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4806 -
4807 - spin_lock(&jffs2_compressor_list_lock);
4808 -
4809 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4810 - if (this->priority < comp->priority) {
4811 - list_add(&comp->list, this->list.prev);
4812 - goto out;
4813 - }
4814 - }
4815 - list_add_tail(&comp->list, &jffs2_compressor_list);
4816 + if (!comp->name) {
4817 + printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4818 + return -1;
4819 + }
4820 + comp->compr_buf_size=0;
4821 + comp->compr_buf=NULL;
4822 + comp->usecount=0;
4823 + comp->stat_compr_orig_size=0;
4824 + comp->stat_compr_new_size=0;
4825 + comp->stat_compr_blocks=0;
4826 + comp->stat_decompr_blocks=0;
4827 + D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4828 +
4829 + spin_lock(&jffs2_compressor_list_lock);
4830 +
4831 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4832 + if (this->priority < comp->priority) {
4833 + list_add(&comp->list, this->list.prev);
4834 + goto out;
4835 + }
4836 + }
4837 + list_add_tail(&comp->list, &jffs2_compressor_list);
4838 out:
4839 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4840 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4841 - })
4842 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4843 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4844 + })
4845
4846 - spin_unlock(&jffs2_compressor_list_lock);
4847 + spin_unlock(&jffs2_compressor_list_lock);
4848
4849 - return 0;
4850 + return 0;
4851 }
4852
4853 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
4854 {
4855 - D2(struct jffs2_compressor *this;)
4856 + D2(struct jffs2_compressor *this;)
4857 +
4858 + D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4859
4860 - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4861 + spin_lock(&jffs2_compressor_list_lock);
4862
4863 - spin_lock(&jffs2_compressor_list_lock);
4864 + if (comp->usecount) {
4865 + spin_unlock(&jffs2_compressor_list_lock);
4866 + printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4867 + return -1;
4868 + }
4869 + list_del(&comp->list);
4870
4871 - if (comp->usecount) {
4872 - spin_unlock(&jffs2_compressor_list_lock);
4873 - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4874 - return -1;
4875 - }
4876 - list_del(&comp->list);
4877 -
4878 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4879 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4880 - })
4881 - spin_unlock(&jffs2_compressor_list_lock);
4882 - return 0;
4883 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4884 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4885 + })
4886 + spin_unlock(&jffs2_compressor_list_lock);
4887 + return 0;
4888 }
4889
4890 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
4891 {
4892 - if (orig != comprbuf)
4893 - kfree(comprbuf);
4894 + if (orig != comprbuf)
4895 + kfree(comprbuf);
4896 }
4897
4898 int __init jffs2_compressors_init(void)
4899 {
4900 /* Registering compressors */
4901 #ifdef CONFIG_JFFS2_ZLIB
4902 - jffs2_zlib_init();
4903 + jffs2_zlib_init();
4904 #endif
4905 #ifdef CONFIG_JFFS2_RTIME
4906 - jffs2_rtime_init();
4907 + jffs2_rtime_init();
4908 #endif
4909 #ifdef CONFIG_JFFS2_RUBIN
4910 - jffs2_rubinmips_init();
4911 - jffs2_dynrubin_init();
4912 + jffs2_rubinmips_init();
4913 + jffs2_dynrubin_init();
4914 #endif
4915 /* Setting default compression mode */
4916 #ifdef CONFIG_JFFS2_CMODE_NONE
4917 - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4918 - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4919 + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4920 + D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4921 #else
4922 #ifdef CONFIG_JFFS2_CMODE_SIZE
4923 - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4924 - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4925 + jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4926 + D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4927 #else
4928 - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4929 + D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4930 #endif
4931 #endif
4932 - return 0;
4933 + return 0;
4934 }
4935
4936 int jffs2_compressors_exit(void)
4937 {
4938 /* Unregistering compressors */
4939 #ifdef CONFIG_JFFS2_RUBIN
4940 - jffs2_dynrubin_exit();
4941 - jffs2_rubinmips_exit();
4942 + jffs2_dynrubin_exit();
4943 + jffs2_rubinmips_exit();
4944 #endif
4945 #ifdef CONFIG_JFFS2_RTIME
4946 - jffs2_rtime_exit();
4947 + jffs2_rtime_exit();
4948 #endif
4949 #ifdef CONFIG_JFFS2_ZLIB
4950 - jffs2_zlib_exit();
4951 + jffs2_zlib_exit();
4952 #endif
4953 - return 0;
4954 + return 0;
4955 }
4956 Index: linux-2.6.23.17/fs/jffs2/compr.h
4957 ===================================================================
4958 --- linux-2.6.23.17.orig/fs/jffs2/compr.h
4959 +++ linux-2.6.23.17/fs/jffs2/compr.h
4960 @@ -2,7 +2,7 @@
4961 * JFFS2 -- Journalling Flash File System, Version 2.
4962 *
4963 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4964 - * University of Szeged, Hungary
4965 + * University of Szeged, Hungary
4966 *
4967 * For licensing information, see the file 'LICENCE' in this directory.
4968 *
4969 @@ -32,29 +32,29 @@
4970 #define JFFS2_ZLIB_PRIORITY 60
4971
4972 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
4973 -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4974 +#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4975
4976 #define JFFS2_COMPR_MODE_NONE 0
4977 #define JFFS2_COMPR_MODE_PRIORITY 1
4978 #define JFFS2_COMPR_MODE_SIZE 2
4979
4980 struct jffs2_compressor {
4981 - struct list_head list;
4982 - int priority; /* used by prirority comr. mode */
4983 - char *name;
4984 - char compr; /* JFFS2_COMPR_XXX */
4985 - int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
4986 - uint32_t *srclen, uint32_t *destlen, void *model);
4987 - int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
4988 - uint32_t cdatalen, uint32_t datalen, void *model);
4989 - int usecount;
4990 - int disabled; /* if seted the compressor won't compress */
4991 - unsigned char *compr_buf; /* used by size compr. mode */
4992 - uint32_t compr_buf_size; /* used by size compr. mode */
4993 - uint32_t stat_compr_orig_size;
4994 - uint32_t stat_compr_new_size;
4995 - uint32_t stat_compr_blocks;
4996 - uint32_t stat_decompr_blocks;
4997 + struct list_head list;
4998 + int priority; /* used by prirority comr. mode */
4999 + char *name;
5000 + char compr; /* JFFS2_COMPR_XXX */
5001 + int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
5002 + uint32_t *srclen, uint32_t *destlen, void *model);
5003 + int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
5004 + uint32_t cdatalen, uint32_t datalen, void *model);
5005 + int usecount;
5006 + int disabled; /* if set the compressor won't compress */
5007 + unsigned char *compr_buf; /* used by size compr. mode */
5008 + uint32_t compr_buf_size; /* used by size compr. mode */
5009 + uint32_t stat_compr_orig_size;
5010 + uint32_t stat_compr_new_size;
5011 + uint32_t stat_compr_blocks;
5012 + uint32_t stat_decompr_blocks;
5013 };
5014
5015 int jffs2_register_compressor(struct jffs2_compressor *comp);
5016 @@ -64,12 +64,12 @@ int jffs2_compressors_init(void);
5017 int jffs2_compressors_exit(void);
5018
5019 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5020 - unsigned char *data_in, unsigned char **cpage_out,
5021 - uint32_t *datalen, uint32_t *cdatalen);
5022 + unsigned char *data_in, unsigned char **cpage_out,
5023 + uint32_t *datalen, uint32_t *cdatalen);
5024
5025 int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5026 - uint16_t comprtype, unsigned char *cdata_in,
5027 - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5028 + uint16_t comprtype, unsigned char *cdata_in,
5029 + unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5030
5031 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
5032
5033 Index: linux-2.6.23.17/fs/jffs2/compr_rtime.c
5034 ===================================================================
5035 --- linux-2.6.23.17.orig/fs/jffs2/compr_rtime.c
5036 +++ linux-2.6.23.17/fs/jffs2/compr_rtime.c
5037 @@ -104,7 +104,7 @@ static int jffs2_rtime_decompress(unsign
5038 }
5039 }
5040 }
5041 - return 0;
5042 + return 0;
5043 }
5044
5045 static struct jffs2_compressor jffs2_rtime_comp = {
5046 Index: linux-2.6.23.17/fs/jffs2/compr_rubin.c
5047 ===================================================================
5048 --- linux-2.6.23.17.orig/fs/jffs2/compr_rubin.c
5049 +++ linux-2.6.23.17/fs/jffs2/compr_rubin.c
5050 @@ -384,7 +384,7 @@ static int jffs2_rubinmips_decompress(un
5051 void *model)
5052 {
5053 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
5054 - return 0;
5055 + return 0;
5056 }
5057
5058 static int jffs2_dynrubin_decompress(unsigned char *data_in,
5059 @@ -399,7 +399,7 @@ static int jffs2_dynrubin_decompress(uns
5060 bits[c] = data_in[c];
5061
5062 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
5063 - return 0;
5064 + return 0;
5065 }
5066
5067 static struct jffs2_compressor jffs2_rubinmips_comp = {
5068 Index: linux-2.6.23.17/fs/jffs2/compr_zlib.c
5069 ===================================================================
5070 --- linux-2.6.23.17.orig/fs/jffs2/compr_zlib.c
5071 +++ linux-2.6.23.17/fs/jffs2/compr_zlib.c
5072 @@ -181,7 +181,7 @@ static int jffs2_zlib_decompress(unsigne
5073 }
5074 zlib_inflateEnd(&inf_strm);
5075 mutex_unlock(&inflate_mutex);
5076 - return 0;
5077 + return 0;
5078 }
5079
5080 static struct jffs2_compressor jffs2_zlib_comp = {
5081 @@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
5082
5083 ret = alloc_workspaces();
5084 if (ret)
5085 - return ret;
5086 + return ret;
5087
5088 ret = jffs2_register_compressor(&jffs2_zlib_comp);
5089 if (ret)
5090 - free_workspaces();
5091 + free_workspaces();
5092
5093 return ret;
5094 }
5095 Index: linux-2.6.23.17/fs/jffs2/dir.c
5096 ===================================================================
5097 --- linux-2.6.23.17.orig/fs/jffs2/dir.c
5098 +++ linux-2.6.23.17/fs/jffs2/dir.c
5099 @@ -32,7 +32,7 @@ static int jffs2_mkdir (struct inode *,s
5100 static int jffs2_rmdir (struct inode *,struct dentry *);
5101 static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
5102 static int jffs2_rename (struct inode *, struct dentry *,
5103 - struct inode *, struct dentry *);
5104 + struct inode *, struct dentry *);
5105
5106 const struct file_operations jffs2_dir_operations =
5107 {
5108 @@ -770,7 +770,7 @@ static int jffs2_mknod (struct inode *di
5109 }
5110
5111 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
5112 - struct inode *new_dir_i, struct dentry *new_dentry)
5113 + struct inode *new_dir_i, struct dentry *new_dentry)
5114 {
5115 int ret;
5116 struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
5117 Index: linux-2.6.23.17/fs/jffs2/erase.c
5118 ===================================================================
5119 --- linux-2.6.23.17.orig/fs/jffs2/erase.c
5120 +++ linux-2.6.23.17/fs/jffs2/erase.c
5121 @@ -38,8 +38,8 @@ static void jffs2_erase_block(struct jff
5122 #ifdef __ECOS
5123 ret = jffs2_flash_erase(c, jeb);
5124 if (!ret) {
5125 - jffs2_erase_succeeded(c, jeb);
5126 - return;
5127 + jffs2_erase_succeeded(c, jeb);
5128 + return;
5129 }
5130 bad_offset = jeb->offset;
5131 #else /* Linux */
5132 @@ -50,12 +50,14 @@ static void jffs2_erase_block(struct jff
5133 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
5134 if (!instr) {
5135 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
5136 + down(&c->erase_free_sem);
5137 spin_lock(&c->erase_completion_lock);
5138 list_move(&jeb->list, &c->erase_pending_list);
5139 c->erasing_size -= c->sector_size;
5140 c->dirty_size += c->sector_size;
5141 jeb->dirty_size = c->sector_size;
5142 spin_unlock(&c->erase_completion_lock);
5143 + up(&c->erase_free_sem);
5144 return;
5145 }
5146
5147 @@ -82,12 +84,14 @@ static void jffs2_erase_block(struct jff
5148 if (ret == -ENOMEM || ret == -EAGAIN) {
5149 /* Erase failed immediately. Refile it on the list */
5150 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
5151 + down(&c->erase_free_sem);
5152 spin_lock(&c->erase_completion_lock);
5153 list_move(&jeb->list, &c->erase_pending_list);
5154 c->erasing_size -= c->sector_size;
5155 c->dirty_size += c->sector_size;
5156 jeb->dirty_size = c->sector_size;
5157 spin_unlock(&c->erase_completion_lock);
5158 + up(&c->erase_free_sem);
5159 return;
5160 }
5161
5162 @@ -114,6 +118,7 @@ void jffs2_erase_pending_blocks(struct j
5163 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
5164 list_del(&jeb->list);
5165 spin_unlock(&c->erase_completion_lock);
5166 + up(&c->erase_free_sem);
5167 jffs2_mark_erased_block(c, jeb);
5168
5169 if (!--count) {
5170 @@ -134,6 +139,7 @@ void jffs2_erase_pending_blocks(struct j
5171 jffs2_free_jeb_node_refs(c, jeb);
5172 list_add(&jeb->list, &c->erasing_list);
5173 spin_unlock(&c->erase_completion_lock);
5174 + up(&c->erase_free_sem);
5175
5176 jffs2_erase_block(c, jeb);
5177
5178 @@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct j
5179 }
5180
5181 /* Be nice */
5182 - cond_resched();
5183 + yield();
5184 + down(&c->erase_free_sem);
5185 spin_lock(&c->erase_completion_lock);
5186 }
5187
5188 spin_unlock(&c->erase_completion_lock);
5189 + up(&c->erase_free_sem);
5190 done:
5191 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
5192 -
5193 - up(&c->erase_free_sem);
5194 }
5195
5196 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
5197 {
5198 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
5199 + down(&c->erase_free_sem);
5200 spin_lock(&c->erase_completion_lock);
5201 list_move_tail(&jeb->list, &c->erase_complete_list);
5202 spin_unlock(&c->erase_completion_lock);
5203 + up(&c->erase_free_sem);
5204 /* Ensure that kupdated calls us again to mark them clean */
5205 jffs2_erase_pending_trigger(c);
5206 }
5207 @@ -172,22 +180,26 @@ static void jffs2_erase_failed(struct jf
5208 failed too many times. */
5209 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
5210 /* We'd like to give this block another try. */
5211 + down(&c->erase_free_sem);
5212 spin_lock(&c->erase_completion_lock);
5213 list_move(&jeb->list, &c->erase_pending_list);
5214 c->erasing_size -= c->sector_size;
5215 c->dirty_size += c->sector_size;
5216 jeb->dirty_size = c->sector_size;
5217 spin_unlock(&c->erase_completion_lock);
5218 + up(&c->erase_free_sem);
5219 return;
5220 }
5221 }
5222
5223 + down(&c->erase_free_sem);
5224 spin_lock(&c->erase_completion_lock);
5225 c->erasing_size -= c->sector_size;
5226 c->bad_size += c->sector_size;
5227 list_move(&jeb->list, &c->bad_list);
5228 c->nr_erasing_blocks--;
5229 spin_unlock(&c->erase_completion_lock);
5230 + up(&c->erase_free_sem);
5231 wake_up(&c->erase_wait);
5232 }
5233
5234 @@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struc
5235 size_t retlen;
5236 int ret = -EIO;
5237
5238 + if (c->mtd->point) {
5239 + unsigned long *wordebuf;
5240 +
5241 + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
5242 + if (ret) {
5243 + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
5244 + goto do_flash_read;
5245 + }
5246 + if (retlen < c->sector_size) {
5247 + /* Don't muck about if it won't let us point to the whole erase sector */
5248 + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
5249 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5250 + goto do_flash_read;
5251 + }
5252 + wordebuf = ebuf-sizeof(*wordebuf);
5253 + retlen /= sizeof(*wordebuf);
5254 + do {
5255 + if (*++wordebuf != ~0)
5256 + break;
5257 + } while(--retlen);
5258 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5259 + if (retlen)
5260 + printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n",
5261 + *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
5262 + return 0;
5263 + }
5264 + do_flash_read:
5265 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
5266 if (!ebuf) {
5267 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
5268 @@ -417,6 +456,7 @@ static void jffs2_mark_erased_block(stru
5269 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
5270 }
5271
5272 + down(&c->erase_free_sem);
5273 spin_lock(&c->erase_completion_lock);
5274 c->erasing_size -= c->sector_size;
5275 c->free_size += jeb->free_size;
5276 @@ -429,23 +469,28 @@ static void jffs2_mark_erased_block(stru
5277 c->nr_erasing_blocks--;
5278 c->nr_free_blocks++;
5279 spin_unlock(&c->erase_completion_lock);
5280 + up(&c->erase_free_sem);
5281 wake_up(&c->erase_wait);
5282 return;
5283
5284 filebad:
5285 + down(&c->erase_free_sem);
5286 spin_lock(&c->erase_completion_lock);
5287 /* Stick it on a list (any list) so erase_failed can take it
5288 right off again. Silly, but shouldn't happen often. */
5289 list_add(&jeb->list, &c->erasing_list);
5290 spin_unlock(&c->erase_completion_lock);
5291 + up(&c->erase_free_sem);
5292 jffs2_erase_failed(c, jeb, bad_offset);
5293 return;
5294
5295 refile:
5296 /* Stick it back on the list from whence it came and come back later */
5297 jffs2_erase_pending_trigger(c);
5298 + down(&c->erase_free_sem);
5299 spin_lock(&c->erase_completion_lock);
5300 list_add(&jeb->list, &c->erase_complete_list);
5301 spin_unlock(&c->erase_completion_lock);
5302 + up(&c->erase_free_sem);
5303 return;
5304 }
5305 Index: linux-2.6.23.17/fs/jffs2/gc.c
5306 ===================================================================
5307 --- linux-2.6.23.17.orig/fs/jffs2/gc.c
5308 +++ linux-2.6.23.17/fs/jffs2/gc.c
5309 @@ -556,7 +556,7 @@ static int jffs2_garbage_collect_pristin
5310
5311 node = kmalloc(rawlen, GFP_KERNEL);
5312 if (!node)
5313 - return -ENOMEM;
5314 + return -ENOMEM;
5315
5316 ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
5317 if (!ret && retlen != rawlen)
5318 @@ -624,7 +624,7 @@ static int jffs2_garbage_collect_pristin
5319
5320 if (ret || (retlen != rawlen)) {
5321 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
5322 - rawlen, phys_ofs, ret, retlen);
5323 + rawlen, phys_ofs, ret, retlen);
5324 if (retlen) {
5325 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
5326 } else {
5327 Index: linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
5328 ===================================================================
5329 --- linux-2.6.23.17.orig/fs/jffs2/jffs2_fs_sb.h
5330 +++ linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
5331 @@ -106,6 +106,9 @@ struct jffs2_sb_info {
5332
5333 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
5334
5335 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5336 + unsigned char *wbuf_verify; /* read-back buffer for verification */
5337 +#endif
5338 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
5339 unsigned char *wbuf; /* Write-behind buffer for NAND flash */
5340 uint32_t wbuf_ofs;
5341 Index: linux-2.6.23.17/fs/jffs2/nodelist.h
5342 ===================================================================
5343 --- linux-2.6.23.17.orig/fs/jffs2/nodelist.h
5344 +++ linux-2.6.23.17/fs/jffs2/nodelist.h
5345 @@ -127,7 +127,7 @@ static inline struct jffs2_inode_cache *
5346 return ((struct jffs2_inode_cache *)raw);
5347 }
5348
5349 - /* flash_offset & 3 always has to be zero, because nodes are
5350 + /* flash_offset & 3 always has to be zero, because nodes are
5351 always aligned at 4 bytes. So we have a couple of extra bits
5352 to play with, which indicate the node's status; see below: */
5353 #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
5354 @@ -197,7 +197,7 @@ struct jffs2_inode_cache {
5355 #define RAWNODE_CLASS_XATTR_DATUM 1
5356 #define RAWNODE_CLASS_XATTR_REF 2
5357
5358 -#define INOCACHE_HASHSIZE 128
5359 +#define INOCACHE_HASHSIZE 1024
5360
5361 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
5362
5363 Index: linux-2.6.23.17/fs/jffs2/nodemgmt.c
5364 ===================================================================
5365 --- linux-2.6.23.17.orig/fs/jffs2/nodemgmt.c
5366 +++ linux-2.6.23.17/fs/jffs2/nodemgmt.c
5367 @@ -154,7 +154,7 @@ int jffs2_reserve_space_gc(struct jffs2_
5368 while(ret == -EAGAIN) {
5369 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
5370 if (ret) {
5371 - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5372 + D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5373 }
5374 }
5375 spin_unlock(&c->erase_completion_lock);
5376 @@ -423,7 +423,12 @@ struct jffs2_raw_node_ref *jffs2_add_phy
5377 even after refiling c->nextblock */
5378 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
5379 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
5380 - printk(KERN_WARNING "argh. node added in wrong place\n");
5381 + printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
5382 + if (c->nextblock)
5383 + printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
5384 + else
5385 + printk(KERN_WARNING "No nextblock");
5386 + printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
5387 return ERR_PTR(-EINVAL);
5388 }
5389 #endif
5390 Index: linux-2.6.23.17/fs/jffs2/readinode.c
5391 ===================================================================
5392 --- linux-2.6.23.17.orig/fs/jffs2/readinode.c
5393 +++ linux-2.6.23.17/fs/jffs2/readinode.c
5394 @@ -211,7 +211,7 @@ static void jffs2_kill_tn(struct jffs2_s
5395 * ordering.
5396 *
5397 * Returns 0 if the node was handled (including marking it obsolete)
5398 - * < 0 an if error occurred
5399 + * < 0 an if error occurred
5400 */
5401 static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
5402 struct jffs2_readinode_info *rii,
5403 @@ -862,8 +862,8 @@ static inline int read_unknown(struct jf
5404 JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
5405 ref_offset(ref));
5406 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
5407 - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5408 - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5409 + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5410 + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5411 jffs2_mark_node_obsolete(c, ref);
5412 return 0;
5413 }
5414 Index: linux-2.6.23.17/fs/jffs2/scan.c
5415 ===================================================================
5416 --- linux-2.6.23.17.orig/fs/jffs2/scan.c
5417 +++ linux-2.6.23.17/fs/jffs2/scan.c
5418 @@ -877,7 +877,7 @@ scan_more:
5419 switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
5420 case JFFS2_FEATURE_ROCOMPAT:
5421 printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
5422 - c->flags |= JFFS2_SB_FLAG_RO;
5423 + c->flags |= JFFS2_SB_FLAG_RO;
5424 if (!(jffs2_is_readonly(c)))
5425 return -EROFS;
5426 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
5427 Index: linux-2.6.23.17/fs/jffs2/security.c
5428 ===================================================================
5429 --- linux-2.6.23.17.orig/fs/jffs2/security.c
5430 +++ linux-2.6.23.17/fs/jffs2/security.c
5431 @@ -38,9 +38,9 @@ int jffs2_init_security(struct inode *in
5432 }
5433 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
5434
5435 - kfree(name);
5436 - kfree(value);
5437 - return rc;
5438 + kfree(name);
5439 + kfree(value);
5440 + return rc;
5441 }
5442
5443 /* ---- XATTR Handler for "security.*" ----------------- */
5444 Index: linux-2.6.23.17/fs/jffs2/summary.c
5445 ===================================================================
5446 --- linux-2.6.23.17.orig/fs/jffs2/summary.c
5447 +++ linux-2.6.23.17/fs/jffs2/summary.c
5448 @@ -2,10 +2,10 @@
5449 * JFFS2 -- Journalling Flash File System, Version 2.
5450 *
5451 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5452 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5453 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5454 - * University of Szeged, Hungary
5455 - * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5456 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5457 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5458 + * University of Szeged, Hungary
5459 + * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5460 *
5461 * For licensing information, see the file 'LICENCE' in this directory.
5462 *
5463 Index: linux-2.6.23.17/fs/jffs2/summary.h
5464 ===================================================================
5465 --- linux-2.6.23.17.orig/fs/jffs2/summary.h
5466 +++ linux-2.6.23.17/fs/jffs2/summary.h
5467 @@ -2,9 +2,9 @@
5468 * JFFS2 -- Journalling Flash File System, Version 2.
5469 *
5470 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5471 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5472 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5473 - * University of Szeged, Hungary
5474 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5475 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5476 + * University of Szeged, Hungary
5477 *
5478 * For licensing information, see the file 'LICENCE' in this directory.
5479 *
5480 Index: linux-2.6.23.17/fs/jffs2/wbuf.c
5481 ===================================================================
5482 --- linux-2.6.23.17.orig/fs/jffs2/wbuf.c
5483 +++ linux-2.6.23.17/fs/jffs2/wbuf.c
5484 @@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2
5485 return NULL;
5486 }
5487
5488 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5489 +static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
5490 + uint32_t ofs)
5491 +{
5492 + int ret;
5493 + size_t retlen;
5494 + char *eccstr;
5495 +
5496 + ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
5497 + if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
5498 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
5499 + return ret;
5500 + } else if (retlen != c->wbuf_pagesize) {
5501 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
5502 + return -EIO;
5503 + }
5504 + if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
5505 + return 0;
5506 +
5507 + if (ret == -EUCLEAN)
5508 + eccstr = "corrected";
5509 + else if (ret == -EBADMSG)
5510 + eccstr = "correction failed";
5511 + else
5512 + eccstr = "OK or unused";
5513 +
5514 + printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
5515 + eccstr, c->wbuf_ofs);
5516 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5517 + c->wbuf, c->wbuf_pagesize, 0);
5518 +
5519 + printk(KERN_WARNING "Read back:\n");
5520 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5521 + c->wbuf_verify, c->wbuf_pagesize, 0);
5522 +
5523 + return -EIO;
5524 +}
5525 +#else
5526 +#define jffs2_verify_write(c,b,o) (0)
5527 +#endif
5528 +
5529 /* Recover from failure to write wbuf. Recover the nodes up to the
5530 * wbuf, not the one which we were starting to try to write. */
5531
5532 @@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jf
5533 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
5534 rewrite_buf);
5535
5536 - if (ret || retlen != towrite) {
5537 + if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
5538 /* Argh. We tried. Really we did. */
5539 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
5540 kfree(buf);
5541 @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jff
5542
5543 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
5544
5545 - if (ret || retlen != c->wbuf_pagesize) {
5546 - if (ret)
5547 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
5548 - else {
5549 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5550 - retlen, c->wbuf_pagesize);
5551 - ret = -EIO;
5552 - }
5553 -
5554 + if (ret) {
5555 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
5556 + goto wfail;
5557 + } else if (retlen != c->wbuf_pagesize) {
5558 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5559 + retlen, c->wbuf_pagesize);
5560 + ret = -EIO;
5561 + goto wfail;
5562 + } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
5563 + wfail:
5564 jffs2_wbuf_recover(c);
5565
5566 return ret;
5567 @@ -966,8 +1008,8 @@ exit:
5568
5569 #define NR_OOB_SCAN_PAGES 4
5570
5571 -/* For historical reasons we use only 12 bytes for OOB clean marker */
5572 -#define OOB_CM_SIZE 12
5573 +/* For historical reasons we use only 8 bytes for OOB clean marker */
5574 +#define OOB_CM_SIZE 8
5575
5576 static const struct jffs2_unknown_node oob_cleanmarker =
5577 {
5578 @@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_s
5579 /*
5580 * Check for a valid cleanmarker.
5581 * Returns: 0 if a valid cleanmarker was found
5582 - * 1 if no cleanmarker was found
5583 - * negative error code if an error occurred
5584 + * 1 if no cleanmarker was found
5585 + * negative error code if an error occurred
5586 */
5587 int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
5588 struct jffs2_eraseblock *jeb)
5589 @@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_
5590 return -ENOMEM;
5591 }
5592
5593 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5594 + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
5595 + if (!c->wbuf_verify) {
5596 + kfree(c->oobbuf);
5597 + kfree(c->wbuf);
5598 + return -ENOMEM;
5599 + }
5600 +#endif
5601 return 0;
5602 }
5603
5604 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
5605 {
5606 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5607 + kfree(c->wbuf_verify);
5608 +#endif
5609 kfree(c->wbuf);
5610 kfree(c->oobbuf);
5611 }
5612 Index: linux-2.6.23.17/fs/jffs2/xattr.h
5613 ===================================================================
5614 --- linux-2.6.23.17.orig/fs/jffs2/xattr.h
5615 +++ linux-2.6.23.17/fs/jffs2/xattr.h
5616 @@ -75,7 +75,7 @@ extern void jffs2_build_xattr_subsystem(
5617 extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
5618
5619 extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
5620 - uint32_t xid, uint32_t version);
5621 + uint32_t xid, uint32_t version);
5622
5623 extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5624 extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5625 Index: linux-2.6.23.17/fs/jffs2/xattr_user.c
5626 ===================================================================
5627 --- linux-2.6.23.17.orig/fs/jffs2/xattr_user.c
5628 +++ linux-2.6.23.17/fs/jffs2/xattr_user.c
5629 @@ -17,7 +17,7 @@
5630 #include "nodelist.h"
5631
5632 static int jffs2_user_getxattr(struct inode *inode, const char *name,
5633 - void *buffer, size_t size)
5634 + void *buffer, size_t size)
5635 {
5636 if (!strcmp(name, ""))
5637 return -EINVAL;
5638 @@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct in
5639 }
5640
5641 static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
5642 - size_t size, int flags)
5643 + size_t size, int flags)
5644 {
5645 if (!strcmp(name, ""))
5646 return -EINVAL;
5647 Index: linux-2.6.23.17/include/asm-i386/geode.h
5648 ===================================================================
5649 --- linux-2.6.23.17.orig/include/asm-i386/geode.h
5650 +++ linux-2.6.23.17/include/asm-i386/geode.h
5651 @@ -135,6 +135,55 @@ static inline void geode_gpio_event_pme(
5652 geode_gpio_setup_event(gpio, pair, 1);
5653 }
5654
5655 +/* MFGPT */
5656 +
5657 +#define MFGPT_TIMER_ANY -1
5658 +
5659 +#define MFGPT_DOMAIN_WORKING 1
5660 +#define MFGPT_DOMAIN_STANDBY 2
5661 +#define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY)
5662 +
5663 +#define MFGPT_CMP1 0
5664 +#define MFGPT_CMP2 1
5665 +
5666 +#define MFGPT_EVENT_IRQ 0
5667 +#define MFGPT_EVENT_NMI 1
5668 +#define MFGPT_EVENT_RESET 3
5669 +
5670 +#define MFGPT_REG_CMP1 0
5671 +#define MFGPT_REG_CMP2 2
5672 +#define MFGPT_REG_COUNTER 4
5673 +#define MFGPT_REG_SETUP 6
5674 +
5675 +#define MFGPT_SETUP_CNTEN (1 << 15)
5676 +#define MFGPT_SETUP_CMP2 (1 << 14)
5677 +#define MFGPT_SETUP_CMP1 (1 << 13)
5678 +#define MFGPT_SETUP_SETUP (1 << 12)
5679 +#define MFGPT_SETUP_STOPEN (1 << 11)
5680 +#define MFGPT_SETUP_EXTEN (1 << 10)
5681 +#define MFGPT_SETUP_REVEN (1 << 5)
5682 +#define MFGPT_SETUP_CLKSEL (1 << 4)
5683 +
5684 +static inline void geode_mfgpt_write(int timer, u16 reg, u16 value)
5685 +{
5686 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5687 + outw(value, base + reg + (timer * 8));
5688 +}
5689 +
5690 +static inline u16 geode_mfgpt_read(int timer, u16 reg)
5691 +{
5692 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5693 + return inw(base + reg + (timer * 8));
5694 +}
5695 +
5696 +extern int __init geode_mfgpt_detect(void);
5697 +extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable);
5698 +extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable);
5699 +extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner);
5700 +
5701 +#define geode_mfgpt_setup_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),1)
5702 +#define geode_mfgpt_release_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),0)
5703 +
5704 /* Specific geode tests */
5705
5706 static inline int is_geode_gx(void)
5707 Index: linux-2.6.23.17/include/asm-i386/setup.h
5708 ===================================================================
5709 --- linux-2.6.23.17.orig/include/asm-i386/setup.h
5710 +++ linux-2.6.23.17/include/asm-i386/setup.h
5711 @@ -24,6 +24,7 @@
5712 #define OLD_CL_BASE_ADDR 0x90000
5713 #define OLD_CL_OFFSET 0x90022
5714 #define NEW_CL_POINTER 0x228 /* Relative to real mode data */
5715 +#define OFW_INFO_OFFSET 0xb0 /* Relative to real mode data */
5716
5717 #ifndef __ASSEMBLY__
5718
5719 Index: linux-2.6.23.17/include/linux/console.h
5720 ===================================================================
5721 --- linux-2.6.23.17.orig/include/linux/console.h
5722 +++ linux-2.6.23.17/include/linux/console.h
5723 @@ -121,14 +121,11 @@ extern void console_stop(struct console
5724 extern void console_start(struct console *);
5725 extern int is_console_locked(void);
5726
5727 -#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
5728 +extern int serial_console_suspend_enabled;
5729 +
5730 /* Suspend and resume console messages over PM events */
5731 extern void suspend_console(void);
5732 extern void resume_console(void);
5733 -#else
5734 -static inline void suspend_console(void) {}
5735 -static inline void resume_console(void) {}
5736 -#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
5737
5738 int mda_console_init(void);
5739 void prom_con_init(void);
5740 Index: linux-2.6.23.17/include/linux/fb.h
5741 ===================================================================
5742 --- linux-2.6.23.17.orig/include/linux/fb.h
5743 +++ linux-2.6.23.17/include/linux/fb.h
5744 @@ -664,6 +664,12 @@ struct fb_ops {
5745 /* restore saved state */
5746 void (*fb_restore_state)(struct fb_info *info);
5747
5748 + /* Shut down the graphics engine to save power */
5749 + int (*fb_powerdown)(struct fb_info *info);
5750 +
5751 + /* Power it back up */
5752 + int (*fb_powerup)(struct fb_info *info);
5753 +
5754 /* get capability given var */
5755 void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
5756 struct fb_var_screeninfo *var);
5757 @@ -943,6 +949,9 @@ extern int fb_get_color_depth(struct fb_
5758 extern int fb_get_options(char *name, char **option);
5759 extern int fb_new_modelist(struct fb_info *info);
5760
5761 +extern int fb_powerdown(struct fb_info *info);
5762 +extern int fb_powerup(struct fb_info *info);
5763 +
5764 extern struct fb_info *registered_fb[FB_MAX];
5765 extern int num_registered_fb;
5766 extern struct class *fb_class;
5767 Index: linux-2.6.23.17/include/linux/mtd/onenand.h
5768 ===================================================================
5769 --- linux-2.6.23.17.orig/include/linux/mtd/onenand.h
5770 +++ linux-2.6.23.17/include/linux/mtd/onenand.h
5771 @@ -60,6 +60,7 @@ struct onenand_bufferram {
5772 * @erase_shift: [INTERN] number of address bits in a block
5773 * @page_shift: [INTERN] number of address bits in a page
5774 * @page_mask: [INTERN] a page per block mask
5775 + * @writesize: [INTERN] a real page size
5776 * @bufferram_index: [INTERN] BufferRAM index
5777 * @bufferram: [INTERN] BufferRAM info
5778 * @readw: [REPLACEABLE] hardware specific function for read short
5779 @@ -100,6 +101,7 @@ struct onenand_chip {
5780 unsigned int erase_shift;
5781 unsigned int page_shift;
5782 unsigned int page_mask;
5783 + unsigned int writesize;
5784
5785 unsigned int bufferram_index;
5786 struct onenand_bufferram bufferram[MAX_BUFFERRAM];
5787 @@ -140,6 +142,8 @@ struct onenand_chip {
5788 #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
5789 #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
5790 #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
5791 +#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
5792 +#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
5793
5794 #define ONENAND_GET_SYS_CFG1(this) \
5795 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
5796 @@ -149,6 +153,13 @@ struct onenand_chip {
5797 #define ONENAND_IS_DDP(this) \
5798 (this->device_id & ONENAND_DEVICE_IS_DDP)
5799
5800 +#ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
5801 +#define ONENAND_IS_2PLANE(this) \
5802 + (this->options & ONENAND_HAS_2PLANE)
5803 +#else
5804 +#define ONENAND_IS_2PLANE(this) (0)
5805 +#endif
5806 +
5807 /* Check byte access in OneNAND */
5808 #define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
5809
5810 @@ -157,6 +168,7 @@ struct onenand_chip {
5811 */
5812 #define ONENAND_HAS_CONT_LOCK (0x0001)
5813 #define ONENAND_HAS_UNLOCK_ALL (0x0002)
5814 +#define ONENAND_HAS_2PLANE (0x0004)
5815 #define ONENAND_PAGEBUF_ALLOC (0x1000)
5816 #define ONENAND_OOBBUF_ALLOC (0x2000)
5817
5818 Index: linux-2.6.23.17/include/linux/mtd/onenand_regs.h
5819 ===================================================================
5820 --- linux-2.6.23.17.orig/include/linux/mtd/onenand_regs.h
5821 +++ linux-2.6.23.17/include/linux/mtd/onenand_regs.h
5822 @@ -74,6 +74,8 @@
5823
5824 #define ONENAND_DEVICE_DENSITY_512Mb (0x002)
5825 #define ONENAND_DEVICE_DENSITY_1Gb (0x003)
5826 +#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
5827 +#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
5828
5829 /*
5830 * Version ID Register F002h (R)
5831 @@ -111,6 +113,8 @@
5832 #define ONENAND_CMD_READOOB (0x13)
5833 #define ONENAND_CMD_PROG (0x80)
5834 #define ONENAND_CMD_PROGOOB (0x1A)
5835 +#define ONENAND_CMD_2X_PROG (0x7D)
5836 +#define ONENAND_CMD_2X_CACHE_PROG (0x7F)
5837 #define ONENAND_CMD_UNLOCK (0x23)
5838 #define ONENAND_CMD_LOCK (0x2A)
5839 #define ONENAND_CMD_LOCK_TIGHT (0x2C)
5840 Index: linux-2.6.23.17/include/linux/vt_kern.h
5841 ===================================================================
5842 --- linux-2.6.23.17.orig/include/linux/vt_kern.h
5843 +++ linux-2.6.23.17/include/linux/vt_kern.h
5844 @@ -95,4 +95,23 @@ struct vt_spawn_console {
5845 };
5846 extern struct vt_spawn_console vt_spawn_con;
5847
5848 +/* A notifier list for console events */
5849 +extern struct raw_notifier_head console_notifier_list;
5850 +
5851 +/* Called when the FG console switches to KD_TEXT mode */
5852 +#define CONSOLE_EVENT_SWITCH_TEXT 0x01
5853 +
5854 +/* Called when the FG console switches to KD_GRAPHICS mode */
5855 +#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
5856 +
5857 +static inline int console_event_register(struct notifier_block *n)
5858 +{
5859 + return raw_notifier_chain_register(&console_notifier_list, n);
5860 +}
5861 +
5862 +static inline int console_event_unregister(struct notifier_block *n)
5863 +{
5864 + return raw_notifier_chain_unregister(&console_notifier_list, n);
5865 +}
5866 +
5867 #endif /* _VT_KERN_H */
5868 Index: linux-2.6.23.17/kernel/power/console.c
5869 ===================================================================
5870 --- linux-2.6.23.17.orig/kernel/power/console.c
5871 +++ linux-2.6.23.17/kernel/power/console.c
5872 @@ -9,7 +9,7 @@
5873 #include <linux/console.h>
5874 #include "power.h"
5875
5876 -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
5877 +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) && !defined(CONFIG_DISABLE_SUSPEND_VT_SWITCH)
5878 #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
5879
5880 static int orig_fgconsole, orig_kmsg;