4607aeda68fb10a532fd6116344a451dcb0e71e7
[openwrt.git] / target / linux / olpc / patches-2.6.23 / 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;