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