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
7 If unsure, say Y. Only embedded should say N here.
10 + bool "Don't probe VGA at boot" if EMBEDDED
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
18 source kernel/Kconfig.hz
21 @@ -1120,6 +1129,9 @@ config PCI_GODIRECT
31 @@ -1129,7 +1141,7 @@ config PCI_BIOS
35 - depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
36 + depends on PCI && ((PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS)
40 @@ -1137,6 +1149,11 @@ config PCI_MMCONFIG
41 depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
46 + depends on PCI && PCI_GOOLPC
49 source "drivers/pci/pcie/Kconfig"
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.
56 +config GEODE_MFGPT_TIMER
57 + bool "Geode Multi-Function General Purpose Timer (mfgpt) Support"
58 + depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS
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.
74 + Add support for detecting the unique features of the OLPC
78 + tristate "OLPC power management support"
82 + Add support for the Geode power management facilities on the
83 + OLPC Childrens Machine
86 + bool "Support for Open Firmware"
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.
93 source "drivers/pcmcia/Kconfig"
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
107 obj-$(CONFIG_VMI) += vmi.o vmiclock.o
108 obj-$(CONFIG_PARAVIRT) += paravirt.o
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
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);
125 static int __init geode_southbridge_init(void)
133 + timers = geode_mfgpt_detect();
134 + printk(KERN_INFO "geode-mfgpt: %d timers available.\n", timers);
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
147 +#ifdef CONFIG_OPEN_FIRMWARE
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.
156 + movl $(boot_params - __PAGE_OFFSET + OFW_INFO_OFFSET), %ebp
157 + cmpl $0x2057464F, (%ebp) /* Magic number "OFW " */
160 + mov 0x8(%ebp), %eax /* Save callback address */
161 + mov %eax, call_firmware - __PAGE_OFFSET
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 */
170 + movl %edx, %esi /* restore %esi */
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...
182 page_pde_offset = (__PAGE_OFFSET >> 20);
184 movl $(pg0 - __PAGE_OFFSET), %edi
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)
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;
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)
204 acpi_reserve_bootmem();
206 +#ifdef CONFIG_OLPC_PM
207 + reserve_bootmem(0xf0000, PAGE_SIZE);
209 #ifdef CONFIG_X86_FIND_SMP_CONFIG
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
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);
232 +#ifdef CONFIG_PCI_OLPC
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);
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/
256 obj-$(CONFIG_CONNECTOR) += connector/
258 +obj-$(CONFIG_SYSPROF) += sysprof/
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
269 extern struct tty_driver *console_driver;
271 +/* Add a notifier chain to inform drivers of a VT_TEXT/VT_GRAPHICS switch */
272 +RAW_NOTIFIER_HEAD(console_notifier_list);
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)
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)
282 + /* Notify listeners if the current fg_console has switched */
284 + raw_notifier_call_chain(&console_notifier_list,
286 + CONSOLE_EVENT_SWITCH_TEXT :
287 + CONSOLE_EVENT_SWITCH_GRAPHICS, 0);
290 * explicitly blank/unblank the screen if switching modes
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");
300 +static unsigned int smbclk = 0x70;
301 +module_param(smbclk, uint, 0);
302 +MODULE_PARM_DESC(smbclk, "Specify the SMB_CLK value");
304 #define POLL_TIMEOUT (HZ/5)
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)
313 /************************************************************************/
315 @@ -392,11 +397,13 @@ static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
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 */
324 + outb((smbclk & 0x7F) << 1, ACBCTL2);
326 + outb((smbclk >> 7) & 0xFF, ACBCTL3);
328 - if (inb(ACBCTL2) != 0x70) {
329 + if (inb(ACBCTL2) != ((smbclk & 0x7F) << 1)) {
330 pr_debug(NAME ": ACBCTL2 readback failed\n");
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");
341 +#define ATKBD_KEY_UNKNOWN 0
342 +#define ATKBD_KEY_NULL 0xFF0000FF
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
352 +#define ATKBD_SPECIAL 0xFF0000F8
355 * Scancode to keycode tables. These are just the default setting, and
356 * are loadable via an userland utility.
359 -static unsigned char atkbd_set2_keycode[512] = {
360 +static unsigned int atkbd_set2_keycode[512] = {
362 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
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,
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,
370 + 217,100,ATKBD_KEY_NULL, 0, 97,165, 0, 0,
371 + 156, 0, 0, 0, 0, 0, 0,125,
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,
378 + 226, 0, 0, 0, 0, 0, 0, 0,
379 + 0,ATKBD_KEY_NULL, 96, 0, 0, 0,143, 0,
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,
384 @@ -150,19 +169,6 @@ static unsigned char atkbd_unxlate_table[128] = {
385 #define ATKBD_RET_HANGEUL 0xf2
386 #define ATKBD_RET_ERR 0xff
388 -#define ATKBD_KEY_UNKNOWN 0
389 -#define ATKBD_KEY_NULL 255
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
399 -#define ATKBD_SPECIAL 248
401 #define ATKBD_LED_EVENT_BIT 0
402 #define ATKBD_REP_EVENT_BIT 1
404 @@ -174,7 +180,7 @@ static unsigned char atkbd_unxlate_table[128] = {
405 #define ATKBD_XL_HANJA 0x20
408 - unsigned char keycode;
409 + unsigned int keycode;
411 } atkbd_scroll_keys[] = {
412 { ATKBD_SCR_1, 0xc5 },
413 @@ -200,7 +206,7 @@ struct atkbd {
417 - unsigned char keycode[512];
418 + unsigned int keycode[512];
420 unsigned char translated;
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;
426 - unsigned char keycode;
427 + unsigned int keycode;
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;
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];
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];
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)
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);
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)
461 +#include <asm/olpc.h>
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;
472 + if (olpc_rev_after(OLPC_REV_B2))
473 + if (serio->dev.power.power_state.event != PM_EVENT_ON)
477 if (!atkbd || !drv) {
478 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
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
488 +config MOUSE_PS2_OLPC
489 + bool "OLPC PS/2 mouse protocol extension" if EMBEDDED
491 + depends on MOUSE_PS2 && OLPC
493 + Say Y here if you have an OLPC PS/2 touchpad connected to
499 tristate "Serial mouse"
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
515 #include "synaptics.h"
516 #include "logips2pp.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 = {
524 static DEFINE_MUTEX(psmouse_mutex);
526 -static struct workqueue_struct *kpsmoused_wq;
527 +struct workqueue_struct *kpsmoused_wq;
529 struct psmouse_protocol {
530 enum psmouse_type type;
531 @@ -320,7 +321,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
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);
540 @@ -631,8 +632,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
545 + * Try OLPC touchpad.
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;
552 + * Init failed, try basic relative protocols
554 + max_proto = PSMOUSE_IMEX;
558 + if (max_proto > PSMOUSE_IMEX) {
559 if (genius_detect(psmouse, set_properties) == 0)
560 return PSMOUSE_GENPS;
562 @@ -762,6 +776,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
563 .detect = touchkit_ps2_detect,
566 +#ifdef CONFIG_MOUSE_PS2_OLPC
568 + .type = PSMOUSE_OLPC,
571 + .detect = olpc_detect,
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 {
583 PSMOUSE_TOUCHKIT_PS2,
586 PSMOUSE_AUTO /* This one should always be last */
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);
593 +extern struct workqueue_struct *kpsmoused_wq;
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)
607 +#include <asm/olpc.h>
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)
616 if (dev->dev.power.power_state.event != state.event) {
618 + /* Anything newer than B2 remains powered; no reset needed */
619 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
621 if (state.event == PM_EVENT_SUSPEND)
622 i8042_controller_reset();
627 dev->dev.power.power_state = state;
629 @@ -902,9 +914,15 @@ static int i8042_resume(struct platform_device *dev)
630 if (dev->dev.power.power_state.event == PM_EVENT_ON)
634 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
636 error = i8042_controller_check();
643 error = i8042_controller_selftest();
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 */
655 +#include <asm/olpc.h>
658 static int serio_suspend(struct device *dev, pm_message_t state)
660 if (dev->power.power_state.event != state.event) {
662 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
664 if (state.event == PM_EVENT_SUSPEND)
665 serio_cleanup(to_serio_port(dev));
670 dev->power.power_state = state;
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");
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 "
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.");
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. */
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)
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);
716 mutex_unlock(&cam->s_mutex);
717 @@ -2162,7 +2166,7 @@ static int cafe_pci_probe(struct pci_dev *pdev,
719 * If so requested, try to get our DMA buffers now.
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
732 If you are not sure, say Y here.
735 + tristate "EEPROM 93CX6 support"
737 + This is a driver for the EEPROM chipsets 93c46 and 93c66.
738 + The driver supports both read as well as write commands.
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)
750 + * There's an off-by-one error in the hw that we need to
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);
762 - pwr = SDHCI_POWER_ON;
764 switch (1 << power) {
765 case MMC_VDD_165_195:
766 - pwr |= SDHCI_POWER_180;
767 + pwr = SDHCI_POWER_180;
771 - pwr |= SDHCI_POWER_300;
772 + pwr = SDHCI_POWER_300;
776 - pwr |= SDHCI_POWER_330;
777 + pwr = SDHCI_POWER_330;
781 @@ -696,6 +700,10 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
783 writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
785 + pwr |= SDHCI_POWER_ON;
787 + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
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.
801 + tristate "Log panic/oops to an MTD buffer"
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
808 source "drivers/mtd/chips/Kconfig"
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
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;
831 - * Probing of multi-partition flash ships.
832 + * Probing of multi-partition flash chips.
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,
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)
843 unsigned long ofs, len;
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,
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",
857 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
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,
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",
875 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
881 @@ -2255,7 +2255,7 @@ static void cfi_intelext_save_locks(struct mtd_info *mtd)
882 adr = region->offset + block * len;
884 status = cfi_varsize_frob(mtd,
885 - do_getlockstatus_oneblock, adr, len, 0);
886 + do_getlockstatus_oneblock, adr, len, NULL);
888 set_bit(block, region->lockmap);
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,
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)
901 unsigned long ofs, len;
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
910 #define MBM29F040C 0x00A4
911 +#define MBM29F800BA 0x2258
912 #define MBM29LV650UE 0x22D7
913 #define MBM29LV320TE 0x22F6
914 #define MBM29LV320BE 0x22F9
916 #define LH28F640BF 0x00b0
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[] = {
926 .mfr_id = MANUFACTURER_FUJITSU,
927 + .dev_id = MBM29F800BA,
928 + .name = "Fujitsu MBM29F800BA",
930 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
931 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
933 + .DevSize = SIZE_1MiB,
934 + .CmdSet = P_ID_AMD_STD,
935 + .NumEraseRegions= 4,
937 + ERASEINFO(0x04000,1),
938 + ERASEINFO(0x02000,2),
939 + ERASEINFO(0x08000,1),
940 + ERASEINFO(0x10000,15),
943 + .mfr_id = MANUFACTURER_FUJITSU,
944 .dev_id = MBM29LV650UE,
945 .name = "Fujitsu MBM29LV650UE",
947 @@ -1510,6 +1529,23 @@ static const struct amd_flash_info jedec_table[] = {
948 ERASEINFO(0x1000,256)
952 + .mfr_id = MANUFACTURER_ST,
953 + .dev_id = M29F800AB,
954 + .name = "ST M29F800AB",
956 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
957 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
959 + .DevSize = SIZE_1MiB,
960 + .CmdSet = P_ID_AMD_STD,
961 + .NumEraseRegions= 4,
963 + ERASEINFO(0x04000,1),
964 + ERASEINFO(0x02000,2),
965 + ERASEINFO(0x08000,1),
966 + ERASEINFO(0x10000,15),
969 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
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'.
979 - tristate "Support for M25 SPI Flash"
980 + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
981 depends on SPI_MASTER && EXPERIMENTAL
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.
992 + Note that the original DataFlash chips (AT45 series, not AT26DF),
993 + need an entirely different driver.
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.
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
1007 - * MTD SPI driver for ST M25Pxx flash chips
1008 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
1010 * Author: Mike Lavender, mike@steroidmicros.com
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>
1019 #include <linux/mtd/mtd.h>
1020 #include <linux/mtd/partitions.h>
1022 #include <linux/spi/spi.h>
1023 #include <linux/spi/flash.h>
1025 -#include <asm/semaphore.h>
1028 -/* NOTE: AT 25F and SST 25LF series are very similar,
1029 - * but commands for sector erase and chip id differ...
1032 #define FLASH_PAGESIZE 256
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 */
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 */
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;
1071 @@ -150,8 +150,9 @@ static int wait_till_ready(struct m25p *flash)
1073 static int erase_sector(struct m25p *flash, u32 offset)
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);
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);
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)
1096 - down(&flash->lock);
1097 + mutex_lock(&flash->lock);
1099 + /* REVISIT in some cases we could speed up erasing large regions
1100 + * by using OPCODE_SE instead of OPCODE_BE_4K
1103 /* now erase those sectors */
1105 if (erase_sector(flash, addr)) {
1106 instr->state = MTD_ERASE_FAILED;
1108 + mutex_unlock(&flash->lock);
1112 @@ -215,7 +220,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
1113 len -= mtd->erasesize;
1117 + mutex_unlock(&flash->lock);
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,
1125 - down(&flash->lock);
1126 + mutex_lock(&flash->lock);
1128 /* Wait till previous write/erase is done. */
1129 if (wait_till_ready(flash)) {
1130 /* REVISIT status return?? */
1132 + mutex_unlock(&flash->lock);
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.
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,
1146 *retlen = m.actual_length - sizeof(flash->command);
1149 + mutex_unlock(&flash->lock);
1153 @@ -323,7 +331,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
1155 spi_message_add_tail(&t[1], &m);
1157 - down(&flash->lock);
1158 + mutex_lock(&flash->lock);
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,
1164 *retlen += m.actual_length
1165 - sizeof(flash->command);
1172 + mutex_unlock(&flash->lock);
1176 @@ -398,24 +406,118 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
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.
1189 + /* The size listed here is what works with OPCODE_SE, which isn't
1190 + * necessarily called a "sector" by the vendor.
1192 unsigned sector_size;
1193 - unsigned n_sectors;
1197 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
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.
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 },
1216 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
1217 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
1218 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
1220 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
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, },
1227 + /* Spansion -- single (large) sector size only, at least
1228 + * for the chips listed here (without boot sectors).
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, },
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, },
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, },
1253 + { "m45pe80", 0x204014, 64 * 1024, 16, },
1254 + { "m45pe16", 0x204015, 64 * 1024, 32, },
1256 + { "m25pe80", 0x208014, 64 * 1024, 16, },
1257 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
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, },
1269 +static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
1272 + u8 code = OPCODE_RDID;
1275 + struct flash_info *info;
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.
1281 + tmp = spi_write_then_read(spi, &code, 1, id, 3);
1283 + DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
1284 + spi->dev.bus_id, tmp);
1288 + jedec = jedec << 8;
1290 + jedec = jedec << 8;
1293 + for (tmp = 0, info = m25p_data;
1294 + tmp < ARRAY_SIZE(m25p_data);
1296 + if (info->jedec_id == jedec)
1299 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
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)
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.
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 ...
1321 - DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
1325 + if (data && data->type) {
1326 + for (i = 0, info = m25p_data;
1327 + i < ARRAY_SIZE(m25p_data);
1329 + if (strcmp(data->type, info->name) == 0)
1333 - for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
1334 - if (strcmp(data->type, info->name) == 0)
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);
1346 + /* recognized; is that chip really what's there? */
1347 + } else if (info->jedec_id) {
1348 + struct flash_info *chip = jedec_probe(spi);
1350 + if (!chip || chip != info) {
1351 + dev_warn(&spi->dev, "found %s, expected %s\n",
1352 + chip ? chip->name : "UNKNOWN",
1358 + info = jedec_probe(spi);
1364 flash = kzalloc(sizeof *flash, GFP_KERNEL);
1369 - init_MUTEX(&flash->lock);
1370 + mutex_init(&flash->lock);
1371 dev_set_drvdata(&spi->dev, flash);
1374 + if (data && data->name)
1375 flash->mtd.name = data->name;
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;
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;
1392 + flash->erase_opcode = OPCODE_SE;
1393 + flash->mtd.erasesize = info->sector_size;
1396 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
1397 flash->mtd.size / 1024);
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",
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)
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",
1433 + parts[i].size / 1024);
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 = {
1439 .probe = m25p_probe,
1440 .remove = __devexit_p(m25p_remove),
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...
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
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>
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 */
1465 - struct semaphore lock;
1466 + struct mutex lock;
1467 struct spi_device *spi;
1469 struct mtd_info mtd;
1470 @@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
1472 spi_message_add_tail(&x, &msg);
1474 - down(&priv->lock);
1475 + mutex_lock(&priv->lock);
1476 while (instr->len > 0) {
1477 unsigned int pageaddr;
1479 @@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
1480 instr->len -= priv->page_size;
1484 + mutex_unlock(&priv->lock);
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,
1490 spi_message_add_tail(&x[1], &msg);
1492 - down(&priv->lock);
1493 + mutex_lock(&priv->lock);
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 */
1500 status = spi_sync(priv->spi, &msg);
1502 + mutex_unlock(&priv->lock);
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,
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,
1517 writelen = remaining;
1520 + mutex_unlock(&priv->lock);
1524 @@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, char *name,
1528 - init_MUTEX(&priv->lock);
1529 + mutex_init(&priv->lock);
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
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
1549 * made the memory unusable, added a fix to code to touch up
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)
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));
1570 @@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
1571 * Stuff these outside the ifdef so as to not bust compiled in driver support
1573 static int msize = 0;
1574 -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
1575 -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
1577 static int asize = 0;
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]");
1586 @@ -799,8 +795,7 @@ static int __init init_pmc551(void)
1587 mtd->owner = THIS_MODULE;
1589 if (add_mtd_device(mtd)) {
1590 - printk(KERN_NOTICE "pmc551: Failed to register new "
1592 + printk(KERN_NOTICE "pmc551: Failed to register new device\n");
1593 pci_iounmap(PCI_Device, priv->start);
1596 @@ -811,13 +806,13 @@ static int __init init_pmc551(void)
1597 pci_dev_get(PCI_Device);
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",
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;
1613 @@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
1614 pmc551list = priv->nextpmc551;
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);
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
1631 - * Erase the configuration file system.
1632 - * Used to support the software reset button.
1634 -static void nettel_erasecallback(struct erase_info *done)
1636 - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
1640 -static struct erase_info nettel_erase;
1642 -int nettel_eraseconfig(void)
1644 - struct mtd_info *mtd;
1645 - DECLARE_WAITQUEUE(wait, current);
1646 - wait_queue_head_t wait_q;
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;
1660 - set_current_state(TASK_INTERRUPTIBLE);
1661 - add_wait_queue(&wait_q, &wait);
1663 - ret = mtd->erase(mtd, &nettel_erase);
1665 - set_current_state(TASK_RUNNING);
1666 - remove_wait_queue(&wait_q, &wait);
1667 - put_mtd_device(mtd);
1671 - schedule(); /* Wait for erase to finish. */
1672 - remove_wait_queue(&wait_q, &wait);
1674 - put_mtd_device(mtd);
1682 -int nettel_eraseconfig(void)
1689 /****************************************************************************/
1691 -int __init nettel_init(void)
1692 +static int __init nettel_init(void)
1694 volatile unsigned long *amdpar;
1695 unsigned long amdaddr, maxsize;
1696 @@ -421,10 +364,6 @@ int __init nettel_init(void)
1698 intel_mtd->owner = THIS_MODULE;
1700 -#ifndef CONFIG_BLK_DEV_INITRD
1701 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
1704 num_intel_partitions = sizeof(nettel_intel_partitions) /
1705 sizeof(nettel_intel_partitions[0]);
1707 @@ -477,7 +416,7 @@ out_unmap2:
1709 /****************************************************************************/
1711 -void __exit nettel_cleanup(void)
1712 +static void __exit nettel_cleanup(void)
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;
1723 add_mtd_device(rr_mtd);
1724 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
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
1733 #include <linux/kthread.h>
1734 #include <asm/uaccess.h>
1736 -static LIST_HEAD(blktrans_majors);
1737 +#include "mtdcore.h"
1739 -extern struct mutex mtd_table_mutex;
1740 -extern struct mtd_info *mtd_table[];
1741 +static LIST_HEAD(blktrans_majors);
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,
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)
1760 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
1763 + /* Only sync if opened RW */
1764 + if ((file->f_mode & 2) && mtd->sync)
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
1774 #include <linux/mtd/mtd.h>
1776 +#include "mtdcore.h"
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
1787 config MTD_NAND_NDFC
1788 tristate "NDFC NanD Flash Controller"
1791 select MTD_NAND_ECC_SMC
1793 - NDFC Nand Flash Controllers are integrated in EP44x SoCs
1794 + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
1796 config MTD_NAND_S3C2410_CLKSTOP
1797 bool "S3C2410 NAND IDLE clock stop"
1798 @@ -237,7 +237,7 @@ config MTD_NAND_CAFE
1800 select REED_SOLOMON_DEC16
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
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[] = {
1813 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
1815 +static int cafe_nand_resume(struct pci_dev *pdev)
1817 + uint32_t timing1, timing2, timing3;
1819 + struct mtd_info *mtd = pci_get_drvdata(pdev);
1820 + struct cafe_priv *cafe = mtd->priv;
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);
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);
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);
1847 + cafe_writel(cafe, 0, NAND_DMA_ADDR1);
1849 + /* Enable NAND IRQ in global IRQ mask register */
1850 + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
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,
1861 .suspend = cafe_nand_suspend,
1862 - .resume = cafe_nand_resume,
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
1871 #include <linux/platform_device.h>
1875 +#include <asm/ibm405.h>
1877 #include <asm/ibm44x.h>
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;
1886 +#ifndef CONFIG_PHYS_64BIT
1887 + ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
1889 ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
1891 if (!ndfc->ndfcbase) {
1892 printk(KERN_ERR "NDFC: ioremap failed\n");
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
1900 OTP block is fully-guaranteed to be a valid block.
1902 +config MTD_ONENAND_2X_PROGRAM
1903 + bool "OneNAND 2X program support"
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
1912 + Now the following chips support it. (KFXXX16Q2M)
1913 + Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
1914 + Mux: KFM2G16Q2M, KFN4G16Q2M,
1916 + And more recent chips
1918 +config MTD_ONENAND_SIM
1919 + tristate "OneNAND simulator support"
1920 + depends on MTD_PARTITIONS
1922 + The simulator may simulate various OneNAND flash chips for the
1923 + OneNAND MTD layer.
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
1932 obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
1935 +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
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
1944 block = (int) (addr >> this->erase_shift);
1945 page = (int) (addr >> this->page_shift);
1947 + if (ONENAND_IS_2PLANE(this)) {
1948 + /* Make the even block number */
1950 + /* Is it the odd plane? */
1951 + if (addr & this->writesize)
1955 page &= this->page_mask;
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);
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);
1968 + /* Switch to the next data buffer */
1969 + ONENAND_SET_NEXT_BUFFERRAM(this);
1973 @@ -247,6 +260,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
1977 + if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
1978 + cmd = ONENAND_CMD_2X_PROG;
1979 dataram = ONENAND_CURRENT_BUFFERRAM(this);
1982 @@ -445,8 +460,9 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
1983 struct onenand_chip *this = mtd->priv;
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;
1993 @@ -572,6 +588,30 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,
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
2002 + * Get blockpage address at 2x program mode
2004 +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
2006 + struct onenand_chip *this = mtd->priv;
2007 + int blockpage, block, page;
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)
2014 + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
2015 + blockpage = (block << 7) | page;
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;
2028 - blockpage = (int) (addr >> this->page_shift);
2029 + if (ONENAND_IS_2PLANE(this))
2030 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2032 + blockpage = (int) (addr >> this->page_shift);
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,
2040 - blockpage = (int) (addr >> this->page_shift);
2041 + if (ONENAND_IS_2PLANE(this))
2042 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2044 + blockpage = (int) (addr >> this->page_shift);
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;
2051 int ret = 0, boundary = 0;
2052 + int writesize = this->writesize;
2054 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
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 */
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);
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;
2077 /* If there is more to load then start next load */
2079 if (read + thislen < len) {
2080 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2081 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
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);
2089 - thislen = min_t(int, mtd->writesize, len - read);
2090 + thislen = min_t(int, writesize, len - read);
2093 /* Now wait for load */
2094 @@ -1079,7 +1126,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
2097 /* Update Page size */
2098 - from += mtd->writesize;
2099 + from += this->writesize;
2103 @@ -1135,12 +1182,12 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
2104 int thislen, column;
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;
2116 - this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
2117 + this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
2119 onenand_update_bufferram(mtd, addr, 0);
2121 @@ -1236,6 +1283,10 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
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);
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);
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);
2141 ret = this->wait(mtd, FL_WRITING);
2143 @@ -2107,6 +2162,7 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
2145 * Check and set OneNAND features
2149 static void onenand_check_features(struct mtd_info *mtd)
2151 @@ -2118,19 +2174,35 @@ static void onenand_check_features(struct mtd_info *mtd)
2152 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2155 - if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
2156 + switch (density) {
2157 + case ONENAND_DEVICE_DENSITY_4Gb:
2158 + this->options |= ONENAND_HAS_2PLANE;
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;
2166 + case ONENAND_DEVICE_DENSITY_1Gb:
2167 /* A-Die has all block unlock */
2169 - printk(KERN_DEBUG "Chip support all block unlock\n");
2171 this->options |= ONENAND_HAS_UNLOCK_ALL;
2174 - /* Some OneNAND has continues lock scheme */
2176 - printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
2180 + /* Some OneNAND has continuous lock scheme */
2182 this->options |= ONENAND_HAS_CONT_LOCK;
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");
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;
2203 /* REVIST: Multichip handling */
2205 @@ -2265,6 +2339,17 @@ static int onenand_probe(struct mtd_info *mtd)
2206 /* Check OneNAND features */
2207 onenand_check_features(mtd);
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.
2215 + if (ONENAND_IS_2PLANE(this)) {
2216 + mtd->writesize <<= 1;
2217 + mtd->erasesize <<= 1;
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);
2231 + * According to Tom Sylla, the Geode does not support PCI power management
2232 + * transition, so we shouldn't need the D3hot delay.
2234 +static void __init quirk_geode_pci_pm(struct pci_dev *dev)
2236 + pci_pm_d3_delay = 0;
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);
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
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
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
2266 select FB_MODE_HELPERS
2267 @@ -1383,7 +1383,7 @@ config FB_SAVAGE_ACCEL
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");
2280 +config FB_OLPC_DCON
2281 + tristate "One Laptop Per Child Display CONtroller support"
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'.
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/
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 */
2312 +fb_powerup(struct fb_info *info)
2316 + if (!info || info->state == FBINFO_STATE_RUNNING)
2319 + if (info->fbops->fb_powerup)
2320 + ret = info->fbops->fb_powerup(info);
2323 + acquire_console_sem();
2324 + fb_set_suspend(info, 0);
2325 + release_console_sem();
2332 +fb_powerdown(struct fb_info *info)
2336 + if (!info || info->state == FBINFO_STATE_SUSPENDED)
2339 + /* Tell everybody that the fbdev is going down */
2340 + acquire_console_sem();
2341 + fb_set_suspend(info, 1);
2342 + release_console_sem();
2344 + if (info->fbops->fb_powerdown)
2345 + ret = info->fbops->fb_powerdown(info);
2347 + /* If the power down failed, then un-notify */
2350 + acquire_console_sem();
2351 + fb_set_suspend(info, 0);
2352 + release_console_sem();
2359 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
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
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
2378 * Free Software Foundation; either version 2 of the License, or * (at your
2379 * option) any later version.
2382 +#include <linux/kernel.h>
2383 #include <linux/spinlock.h>
2384 #include <linux/fb.h>
2385 #include <linux/delay.h>
2387 #include <asm/div64.h>
2388 #include <asm/delay.h>
2389 +#include <asm/olpc.h>
2391 #include "geodefb.h"
2392 #include "display_gx.h"
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)
2398 - return CONFIG_FB_GEODE_GX_FBSIZE;
2399 + u32 in = readl(reg);
2405 unsigned int gx_frame_buffer_size(void)
2410 + if (machine_is_olpc() && !olpc_has_vsa()) {
2412 + rdmsr(GLIU0_P2D_RO0, lo, hi);
2414 + /* Top page number */
2415 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
2417 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
2418 + val += 1; /* Adjust page count */
2419 + return (val << 12);
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;
2432 int gx_line_delta(int xres, int bpp)
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);
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 */
2443 - /* Wait for pending memory requests before disabling the FIFO load. */
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);
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. */
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);
2465 + /* Setup DCLK and its divisor. */
2466 + par->vid_ops->set_dclk(info);
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;
2474 /* Framebuffer start offset. */
2475 - writel(0, par->dc_regs + DC_FB_ST_OFFSET);
2476 + rmwl(0, par->dc_regs + DC_FB_ST_OFFSET);
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);
2484 + rmwl(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2485 + par->dc_regs + DC_LINE_SIZE);
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;
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);
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);
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);
2513 par->vid_ops->configure_display(info);
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
2523 +/* Used for memory dection on the OLPC */
2524 +#define GLIU0_P2D_RO0 0x10000029
2526 /* Display controller registers */
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
2534 #ifndef __GEODEFB_H__
2535 #define __GEODEFB_H__
2537 +#define FB_POWER_STATE_OFF 0
2538 +#define FB_POWER_STATE_SUSPEND 1
2539 +#define FB_POWER_STATE_ON 2
2541 struct geodefb_info;
2543 struct geode_dc_ops {
2544 @@ -21,18 +25,24 @@ struct geode_dc_ops {
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);
2553 struct geodefb_par {
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 */
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;
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
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>
2583 #include "geodefb.h"
2584 #include "display_gx.h"
2585 #include "video_gx.h"
2587 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
2588 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
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 *)
2599 static char *mode_option;
2600 +static int noclear;
2601 +struct fb_info *gxfb_info;
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 }
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 }
2623 static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
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)
2630 -static int gxfb_set_par(struct fb_info *info)
2631 +int gxfb_set_par(struct fb_info *info)
2633 struct geodefb_par *par = info->par;
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);
2641 static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
2643 struct geodefb_par *par = info->par;
2647 ret = pci_enable_device(dev);
2651 + ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
2655 + par->gp_regs = ioremap(pci_resource_start(dev, 1),
2656 + pci_resource_len(dev, 1));
2657 + if (!par->gp_regs)
2660 ret = pci_request_region(dev, 3, "gxfb (video processor)");
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)");
2667 - if ((fb_len = gx_frame_buffer_size()) < 0)
2670 + /* If the fbsize wasn't specified then try to probe it */
2673 + fbsize = gx_frame_buffer_size();
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)
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 */
2689 writel(info->fix.smem_start & 0xFF000000,
2690 par->dc_regs + DC_GLIU0_MEM_OFFSET);
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);
2699 +static int gxfb_ioctl( struct fb_info *info, unsigned int cmd,
2700 + unsigned long arg)
2702 + unsigned int gamma[GXFB_GAMMA_DWORDS];
2703 + int ret = -EINVAL;
2704 + struct geodefb_par *par = info->par;
2709 + /* Read the gamma information from the user - 256 dwords */
2711 + if (copy_from_user(gamma, (void * __user) arg, GXFB_GAMMA_SIZE))
2714 + writel(0, par->vid_regs + GX_GAR);
2716 + /* Sequential writes to the data register will increment the
2717 + address automatically */
2719 + for(i = 0; i < GXFB_GAMMA_DWORDS; i++)
2720 + writel(gamma[i] & 0xFFFFFF, par->vid_regs + GX_GDR);
2722 + writel(readl(par->vid_regs + GX_MISC) & ~GX_MISC_GAM_EN,
2723 + par->vid_regs + GX_MISC);
2729 + if (readl(par->vid_regs + GX_MISC) & GX_MISC_GAM_EN)
2732 + memset(gamma, 0, GXFB_GAMMA_SIZE);
2733 + writel(0, par->vid_regs + GX_GAR);
2735 + for(i = 0; i < GXFB_GAMMA_DWORDS;i++)
2736 + gamma[i] = readl(par->vid_regs + GX_GDR);
2738 + if (copy_to_user((void * __user) arg, gamma, GXFB_GAMMA_SIZE))
2748 + dump_regs(info, 0);
2753 + dump_regs(info, 1);
2758 + dump_regs(info, 2);
2763 + dump_regs(info, 3);
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,
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)
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)
2795 + if (gxfb_info != NULL) {
2796 + struct geodefb_par *par = gxfb_info->par;
2797 + par->fbactive = (action == CONSOLE_EVENT_SWITCH_TEXT) ? 0 : 1;
2803 +static struct notifier_block gxfb_console_notifier = {
2804 + .notifier_call = gxfb_console_notify
2809 +static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
2811 + struct fb_info *info = pci_get_drvdata(pdev);
2812 + struct geodefb_par *par = info->par;
2814 + if (pdev->dev.power.power_state.event == state.event)
2817 + if (state.event == PM_EVENT_SUSPEND) {
2819 + acquire_console_sem();
2820 + gxfb_powerdown(info);
2822 + par->state = FB_POWER_STATE_OFF;
2823 + fb_set_suspend(info, 1);
2825 + release_console_sem();
2828 + pdev->dev.power.power_state = state;
2832 +static int gxfb_resume(struct pci_dev *pdev)
2834 + struct fb_info *info = pci_get_drvdata(pdev);
2836 + acquire_console_sem();
2838 + /* Turn the engine completely on */
2840 + if (gxfb_powerup(info))
2841 + printk(KERN_ERR "gxfb: Powerup failed\n");
2843 + fb_set_suspend(info, 0);
2844 + release_console_sem();
2846 + pdev->dev.power.power_state = PMSG_ON;
2851 +static int __init gxfb_probe(struct pci_dev *pdev,
2852 + const struct pci_device_id *id)
2854 struct geodefb_par *par;
2855 - struct fb_info *info;
2859 - info = gxfb_init_fbinfo(&pdev->dev);
2861 + struct fb_videomode *modedb_ptr;
2864 + gxfb_info = gxfb_init_fbinfo(&pdev->dev);
2865 + if (gxfb_info == NULL)
2869 + par = gxfb_info->par;
2871 /* GX display controller and GX video device. */
2872 par->dc_ops = &gx_dc_ops;
2873 par->vid_ops = &gx_vid_ops;
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");
2880 @@ -333,32 +519,60 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
2882 par->enable_crt = 1;
2884 - ret = fb_find_mode(&info->var, info, mode_option,
2885 - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
2886 + /* Get the current dotclock */
2888 + par->curdclk = (par->vid_ops->get_dclk) ? par->vid_ops->get_dclk(gxfb_info) : 0;
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.
2895 + modedb_ptr = (struct fb_videomode *) gx_modedb;
2896 + modedb_size = ARRAY_SIZE(gx_modedb);
2899 + if (olpc_has_dcon()) {
2900 + modedb_ptr = (struct fb_videomode *) gx_dcon_modedb;
2901 + modedb_size = ARRAY_SIZE(gx_dcon_modedb);
2905 + ret = fb_find_mode(&gxfb_info->var, gxfb_info, mode_option,
2906 + modedb_ptr, modedb_size, NULL, 16);
2908 if (ret == 0 || ret == 4) {
2909 dev_err(&pdev->dev, "could not find valid video mode\n");
2914 + /* Clear the screen of garbage, unless noclear was specified,
2915 + * in which case we assume the user knows what he is doing */
2918 + memset_io(gxfb_info->screen_base, 0, gxfb_info->fix.smem_len);
2920 + gxfb_check_var(&gxfb_info->var, gxfb_info);
2921 + gxfb_set_par(gxfb_info);
2923 + /* We are powered up */
2924 + par->state = FB_POWER_STATE_ON;
2926 - /* Clear the frame buffer of garbage. */
2927 - memset_io(info->screen_base, 0, info->fix.smem_len);
2929 - gxfb_check_var(&info->var, info);
2930 - gxfb_set_par(info);
2931 + console_event_register(&gxfb_console_notifier);
2933 - if (register_framebuffer(info) < 0) {
2934 + if (register_framebuffer(gxfb_info) < 0) {
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);
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);
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);
2957 - framebuffer_release(info);
2959 + framebuffer_release(gxfb_info);
2964 @@ -397,9 +612,7 @@ static void gxfb_remove(struct pci_dev *pdev)
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,
2971 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
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,
2980 + .suspend = gxfb_suspend,
2981 + .resume = gxfb_resume
2986 -static int __init gxfb_setup(char *options)
2988 +static int __init gxfb_setup(char *options) {
2992 if (!options || !*options)
2995 - while ((opt = strsep(&options, ",")) != NULL) {
2996 + while((opt = strsep(&options, ",")) != NULL) {
3000 - mode_option = opt;
3001 + if (!strncmp(opt, "fbsize:", 7))
3002 + fbsize = simple_strtoul(opt+7, NULL, 0);
3003 + else if (!strcmp(opt, "noclear"))
3006 + mode_option = opt;
3010 @@ -444,7 +665,6 @@ static int __init gxfb_init(void)
3012 return pci_register_driver(&gxfb_driver);
3015 static void __exit gxfb_cleanup(void)
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>])");
3022 +module_param(fbsize, int, 0);
3023 +MODULE_PARM_DESC(fbsize, "video memory size");
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);
3043 +/* ioctl() defines */
3045 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
3046 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
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))
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
3060 #include <linux/init.h>
3061 #include <linux/pci.h>
3062 #include <linux/uaccess.h>
3063 +#include <asm/olpc.h>
3067 @@ -35,186 +36,84 @@ static int fbsize;
3070 const struct fb_videomode geode_modedb[] __initdata = {
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 },
3087 - { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
3088 - FB_SYNC_HOR_HIGH_ACT,
3089 - FB_VMODE_NONINTERLACED, 0 },
3091 - { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
3092 - 0, FB_VMODE_NONINTERLACED, 0 },
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 },
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 },
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 },
3118 - { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
3119 - 0, FB_VMODE_NONINTERLACED, 0 },
3121 - { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
3122 - 0, FB_VMODE_NONINTERLACED, 0 },
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 },
3131 - { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
3132 - 0, FB_VMODE_NONINTERLACED, 0 },
3134 - { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
3135 - 0, FB_VMODE_NONINTERLACED, 0 },
3137 - { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
3138 - 0, FB_VMODE_NONINTERLACED, 0 },
3140 - { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
3141 - 0, FB_VMODE_NONINTERLACED, 0 },
3143 - { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
3144 - 0, FB_VMODE_NONINTERLACED, 0 },
3146 - { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
3147 - 0, FB_VMODE_NONINTERLACED, 0 },
3149 - { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
3150 - 0, FB_VMODE_NONINTERLACED, 0 },
3152 - { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
3153 - 0, FB_VMODE_NONINTERLACED, 0 },
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 },
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 },
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 },
3176 - { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
3177 - 0, FB_VMODE_NONINTERLACED, 0 },
3179 - { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
3180 - 0, FB_VMODE_NONINTERLACED, 0 },
3182 - { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
3183 - 0, FB_VMODE_NONINTERLACED, 0 },
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 },
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 },
3198 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3199 - 0, FB_VMODE_NONINTERLACED, 0 },
3201 - { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
3202 - 0, FB_VMODE_NONINTERLACED, 0 },
3204 - { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
3205 - 0, FB_VMODE_NONINTERLACED, 0 },
3207 - { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
3208 - 0, FB_VMODE_NONINTERLACED, 0 },
3210 - { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
3211 - 0, FB_VMODE_NONINTERLACED, 0 },
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 },
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 }
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 }
3313 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
3315 if (var->xres > 1920 || var->yres > 1440)
3316 @@ -379,16 +278,55 @@ static int __init lxfb_map_video_memory(struct fb_info *info,
3320 +static int lxfb_set_gamma(struct fb_info *info, void * __user data)
3322 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3324 + if (copy_from_user(gamma, data, LXFB_GAMMA_SIZE))
3327 + lx_set_gamma(info, gamma, LXFB_GAMMA_SIZE);
3331 +static int lxfb_get_gamma(struct fb_info *info, void * __user data)
3333 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3334 + memset(gamma, 0, sizeof(gamma));
3336 + lx_get_gamma(info, gamma, LXFB_GAMMA_DWORDS);
3338 + return copy_to_user(data, gamma, LXFB_GAMMA_SIZE) ?
3342 +static int lxfb_ioctl( struct fb_info *info, unsigned int cmd,
3343 + unsigned long arg)
3347 + return lxfb_set_gamma(info, (void * __user) arg);
3350 + return lxfb_get_gamma(info, (void * __user) arg);
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,
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)
3378 +static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
3380 + struct fb_info *info = pci_get_drvdata(pdev);
3382 + if (pdev->dev.power.power_state.event == state.event)
3385 + if (state.event == PM_EVENT_SUSPEND) {
3387 + acquire_console_sem();
3388 + lx_shutdown(info);
3389 + fb_set_suspend(info, 1);
3390 + release_console_sem();
3393 + pdev->dev.power.power_state = state;
3397 +static int lxfb_resume(struct pci_dev *pdev)
3399 + struct fb_info *info = pci_get_drvdata(pdev);
3401 + acquire_console_sem();
3403 + /* Turn the engine completely on */
3406 + fb_set_suspend(info, 0);
3407 + release_console_sem();
3409 + pdev->dev.power.power_state = PMSG_ON;
3415 static int __init lxfb_probe(struct pci_dev *pdev,
3416 const struct pci_device_id *id)
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);
3423 + if (olpc_has_dcon()) {
3424 + modedb_ptr = (struct fb_videomode *) olpc_dcon_modedb;
3425 + modedb_size = ARRAY_SIZE(olpc_dcon_modedb);
3429 ret = fb_find_mode(&info->var, info, mode_option,
3430 modedb_ptr, modedb_size, NULL, 16);
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,
3437 + .suspend = lxfb_suspend,
3438 + .resume = lxfb_resume
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
3448 #include <linux/fb.h>
3449 #include <linux/uaccess.h>
3450 #include <linux/delay.h>
3451 +#include <asm/olpc.h>
3456 +#include "geode_regs.h"
3459 * Support panel scaling
3461 @@ -290,6 +294,19 @@ unsigned int lx_framebuffer_size(void)
3466 + if (machine_is_olpc() && !olpc_has_vsa()) {
3468 + rdmsr(MSR_LX_GLIU0_P2D_RO0, lo, hi);
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);
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)
3485 +void lx_set_gamma(struct fb_info *info, unsigned int *gamma, int len)
3488 + struct lxfb_par *par = info->par;
3490 + writel(0, par->df_regs + DF_PAR);
3492 + /* Sequential writes to the data register will increment the
3493 + address automatically */
3495 + for(i = 0; i < len; i++)
3496 + writel(gamma[i] & 0xFFFFFF, par->df_regs + DF_PDR);
3498 + writel(readl(par->df_regs + DF_MISC) & ~DF_MISC_GAM_BYPASS,
3499 + par->df_regs + DF_MISC);
3502 +void lx_get_gamma(struct fb_info *info, unsigned int *gamma, int len)
3505 + struct lxfb_par *par = info->par;
3507 + writel(0, par->df_regs + DF_PAR);
3509 + for(i = 0; i < len;i++)
3510 + gamma[i] = readl(par->df_regs + DF_PDR);
3513 void lx_set_mode(struct fb_info *info)
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;
3519 /* Unlock the DC registers */
3520 + readl(par->dc_regs + DC_UNLOCK);
3521 writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3523 lx_graphics_disable(info);
3524 @@ -534,3 +580,285 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
3529 +static struct geoderegs saved_regs;
3531 +static void lx_save_regs(struct fb_info *info, struct geoderegs *regs)
3533 + struct lxfb_par *par = info->par;
3536 + /* Wait for the command buffer to empty */
3537 + while(!(readl(par->gp_regs + 0x44) & (1 << 4)));
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);
3544 + writel(0x4758, par->dc_regs + 0x00);
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);
3551 + /* Save the palettes */
3552 + writel(0, par->dc_regs + 0x70);
3554 + for(i = 0; i < DC_PAL_SIZE; i++)
3555 + regs->pal[i] = readl(par->dc_regs + 0x74);
3557 + writel(0, par->df_regs + 0x38);
3559 + for(i = 0; i <= 0xFF; i++)
3560 + regs->gamma[i] = readl(par->df_regs + 0x40);
3563 +static void lx_restore_regs(struct fb_info *info, struct geoderegs *regs)
3565 + struct lxfb_par *par = info->par;
3568 + /* == DOTPLL == */
3570 + lx_set_dotpll((u32) (regs->msr.dotpll >> 32));
3574 + wrmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
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);
3593 + /* Writing to these registers would cause a blt to happen */
3594 + /* 0x38, 0x3c, 0x40 */
3596 + /* Status register (0x44) is read only */
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);
3609 + /* FIXME: Restore the LUT data here */
3611 + writel(regs->gp.r.int_cntrl, par->gp_regs + 0x70);
3615 + /* Write the unlock value */
3616 + writel(0x4758, par->dc_regs + 0x00);
3618 + /* Write the palette data first */
3620 + writel(0, par->dc_regs + 0x70);
3622 + for(i = 0; i < DC_PAL_SIZE; i++)
3623 + writel(regs->pal[i], par->dc_regs + 0x74);
3626 + wrmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3628 + /* Write the gcfg register without the enables */
3629 + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
3631 + /* Write the vcfg register without the enables */
3632 + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
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);
3658 + /* Skip register 0x6C (line_cnt), 0x70/0x74 (palette),
3659 + 0x78 (diagnostic), and 0x7c (diagnostic)
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);
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);
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);
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);
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);
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);
3697 + wrmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3699 + /* Write gamma information first */
3701 + writel(0, par->df_regs + 0x38);
3703 + for(i = 0; i <= 0xFF; i++)
3704 + writel((u32) regs->gamma[i], par->df_regs + 0x40);
3706 + /* Don't enable video yet */
3707 + writel((u32) regs->vp.r.vcfg & ~0x01, par->df_regs + 0x00);
3709 + /* Don't enable the CRT yet */
3710 + writel((u32) regs->vp.r.dcfg & ~0x0F, par->df_regs + 0x08);
3712 + /* Write the rest of the VP registers */
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);
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);
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);
3757 + /* Final enables */
3759 + val = readl(par->df_regs + 0x410);
3761 + /* Control the panel */
3762 + if (regs->fp.r.pm & (1 << 24)) {
3764 + if (!(val & 0x09))
3765 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3768 + if (!(val & 0x05))
3769 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3772 + /* Turn everything on */
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);
3780 +static int lx_power_on = 1;
3782 +int lx_shutdown(struct fb_info *info)
3784 + struct lxfb_par *par = info->par;
3786 + if (lx_power_on == 0)
3789 + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3790 + lx_save_regs(info, &saved_regs);
3791 + lx_graphics_disable(info);
3797 +int lx_powerup(struct fb_info *info)
3799 + struct lxfb_par *par = info->par;
3801 + if (lx_power_on == 1)
3804 + lx_restore_regs(info, &saved_regs);
3805 + writel(0, par->dc_regs + DC_UNLOCK);
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
3816 #include <asm/delay.h>
3817 #include <asm/msr.h>
3818 +#include <asm/olpc.h>
3820 #include "geodefb.h"
3821 #include "video_gx.h"
3822 +#include "display_gx.h"
3824 +/* This structure is used to store the saved registers during suspend */
3825 +static struct geoderegs gx_saved_regs;
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 */
3842 -static void gx_set_dclk_frequency(struct fb_info *info)
3843 +void gx_set_dclk_frequency(struct fb_info *info)
3845 + struct geodefb_par *par = info->par;
3846 const struct gx_pll_entry *pll_table;
3849 @@ -173,115 +178,169 @@ static void gx_set_dclk_frequency(struct fb_info *info)
3851 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3852 } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
3854 + par->curdclk = pll_table[best_i].dotpll_value;
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 */
3862 +unsigned int gx_get_dclk(struct fb_info *info)
3864 - struct geodefb_par *par = info->par;
3865 - unsigned long val;
3867 + const struct gx_pll_entry *pll_table;
3868 + int pll_table_len;
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);
3877 + pll_table = gx_pll_table_48MHz;
3878 + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
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);
3887 - /* Turn off the panel */
3888 + for(i = 0; i < pll_table_len; i++) {
3889 + if (pll_table[i].dotpll_value == (u32) (dotpll >> 32))
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;
3900 +#define CMP(val, mask, res) (((val) & (mask)) == (res))
3902 - /* Set timing 1 */
3904 +gx_configure_tft(struct fb_info *info) {
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;
3914 - /* Set bits that are always on for TFT */
3915 + /* Set up the DF pad select MSR */
3918 + rdmsrl(GX_VP_MSR_PAD_SELECT, val);
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);
3927 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
3928 - fp |= GX_FP_PT2_VSP;
3929 + sync |= GX_FP_PT2_VSP;
3931 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
3932 - fp |= GX_FP_PT2_HSP;
3933 + sync |= GX_FP_PT2_HSP;
3935 - writel(fp, par->vid_regs + GX_FP_PT2);
3936 + /* We only need to turn off the panel if something changed */
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);
3943 + if (!CMP(fp1, GX_FP_PT1_VSIZE_MASK, info->var.yres << GX_FP_PT1_VSIZE_SHIFT) ||
3944 + (fp2 != (0x0F100000 | sync))) {
3946 - /* Enable the FP data and power (in case the BIOS didn't) */
3947 + /* Turn off the panel */
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);
3953 + /* Do we really need to turn off the panel? */
3954 + /* Possibly - we have a glitch somewhere */
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);
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);
3968 + writel(0x0F100000 | sync, par->vid_regs + GX_FP_PT2);
3971 + /* Set the dither control */
3972 + if (readl(par->vid_regs + GX_FP_DFC) != 0x70) {
3973 + writel(0x70, par->vid_regs + GX_FP_DFC);
3976 + /* Turn on the panel */
3978 fp = readl(par->vid_regs + GX_FP_PM);
3980 - writel(fp, par->vid_regs + GX_FP_PM);
3983 + writel(fp | GX_FP_PM_P, par->vid_regs + GX_FP_PM);
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
3989 static void gx_configure_display(struct fb_info *info)
3991 struct geodefb_par *par = info->par;
3993 + u32 dcfg, misc, sync = 0;
3995 /* Set up the MISC register */
3997 misc = readl(par->vid_regs + GX_MISC);
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 */
4006 - /* Disable gamma correction */
4007 - misc |= GX_MISC_GAM_EN;
4009 - writel(misc, par->vid_regs + GX_MISC);
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);
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;
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;
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);
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);
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)) {
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);
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);
4067 - dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4068 + /* Set default sync skew. */
4069 + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4071 - /* Enable the external DAC VREF? */
4072 + /* Enable hsync and vsync. */
4073 + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4075 - writel(dcfg, par->vid_regs + GX_DCFG);
4076 + /* Enable the display logic */
4077 + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4079 + writel(dcfg, par->vid_regs + GX_DCFG);
4082 /* Set up the flat panel (if it is enabled) */
4084 @@ -289,6 +348,100 @@ static void gx_configure_display(struct fb_info *info)
4085 gx_configure_tft(info);
4088 +int gxfb_powerdown(struct fb_info *info)
4090 + struct geodefb_par *par = info->par;
4092 + /* We're already suspended */
4094 + if (par->state != FB_POWER_STATE_ON)
4097 + /* Save the registers */
4098 + gx_save_regs(info, &gx_saved_regs);
4100 + /* Shut down the engine */
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);
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);
4109 + writel(0x4758, par->dc_regs + DC_UNLOCK);
4111 + writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
4112 + par->dc_regs + DC_GENERAL_CFG);
4114 + writel(gx_saved_regs.dc.r.dcfg & ~0x19,
4115 + par->dc_regs + DC_DISPLAY_CFG);
4117 + par->state = FB_POWER_STATE_SUSPEND;
4122 +int gxfb_powerup(struct fb_info *info)
4124 + struct geodefb_par *par = info->par;
4127 + if (par->state == FB_POWER_STATE_SUSPEND) {
4129 + writel(gx_saved_regs.dc.r.dcfg,
4130 + par->dc_regs + DC_DISPLAY_CFG);
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);
4135 + val = readl(par->vid_regs + GX_FP_PM);
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);
4144 + /* If the panel is currently on its way up, then wait up to 100ms
4147 + if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
4150 + for(i = 0; i < 10; i++) {
4151 + if (readl(par->vid_regs + GX_FP_PM) & 0x01)
4158 + printk(KERN_ERR "gxfb: Panel power up timed out\n");
4161 + if (par->state == FB_POWER_STATE_ON)
4164 + switch(par->state) {
4165 + case FB_POWER_STATE_OFF:
4166 + gx_restore_regs(info, &gx_saved_regs);
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);
4178 + par->state = FB_POWER_STATE_ON;
4182 static int gx_blank_display(struct fb_info *info, int blank_mode)
4184 struct geodefb_par *par = info->par;
4185 @@ -315,6 +468,7 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
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);
4197 - /* Power on/off flat panel. */
4198 + /* Power on/off flat panel */
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)
4206 +extern struct fb_info *gxfb_info;
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
4213 +void gxfb_flatpanel_control(int state)
4215 + struct geodefb_par *par = gxfb_info->par;
4216 + u32 val, fp = readl(par->vid_regs + GX_FP_PM);
4219 + /* Turn on the panel if it isn't aleady */
4222 + if (!(val & 0x01))
4223 + val |= GX_FP_PM_P;
4226 + if (!(val & 0x02))
4227 + val &= ~GX_FP_PM_P;
4231 + writel(val, par->vid_regs + GX_FP_PM);
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,
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
4245 #ifndef __VIDEO_GX_H__
4246 #define __VIDEO_GX_H__
4248 +#include "geode_regs.h"
4250 extern struct geode_vid_ops gx_vid_ops;
4252 /* GX Flatpanel control MSR */
4253 @@ -20,6 +22,8 @@ extern struct geode_vid_ops gx_vid_ops;
4255 /* Geode GX video processor registers */
4257 +#define GX_VCFG 0x0000
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
4266 +/* Gamma correction RAM - address and data registers */
4268 +#define GX_GAR 0x038
4269 +#define GX_GDR 0x040
4271 +#define GXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
4272 +#define GXFB_GAMMA_SIZE (GXFB_GAMMA_DWORDS * sizeof(unsigned int))
4274 /* Geode GX flat panel display control registers */
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)
4281 +int gxfb_powerdown(struct fb_info *info);
4282 +int gxfb_powerup(struct fb_info *info);
4284 +void gx_set_dclk_frequency(struct fb_info *info);
4285 +unsigned int gx_get_dclk(struct fb_info *info);
4287 +void gx_save_regs(struct fb_info *info, struct geoderegs *regs);
4288 +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs);
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)
4299 +#define DEFAULT_MODEDB_INDEX 0
4301 static const struct fb_videomode modedb[] = {
4303 /* 640x400 @ 70 Hz, 31.5 kHz hsync */
4304 @@ -504,7 +506,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
4308 - default_mode = &db[0];
4309 + default_mode = (db == modedb) ?
4310 + &modedb[DEFAULT_MODEDB_INDEX] : &db[0];
4314 diff --git a/fs/Kconfig b/fs/Kconfig
4315 index f9eed6d..6fa3ea2 100644
4318 @@ -999,6 +999,23 @@ config HUGETLBFS
4323 + tristate "PromFS IEEE 1275 file system support"
4324 + depends on SPARC || PPC || OLPC
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.
4332 + The firmware device-tree is available as a virtual file system,
4333 + can be mounted under /prom with the command "mount -t promfs
4336 + To compile PromFS support as a module, choose M here; the module
4337 + will be called promfs. If unsure, choose M.
4342 @@ -1225,6 +1242,14 @@ config JFFS2_FS_WRITEBUFFER
4343 - NOR flash with transparent ECC
4346 +config JFFS2_FS_WBUF_VERIFY
4347 + bool "Verify JFFS2 write-buffer reads"
4348 + depends on JFFS2_FS_WRITEBUFFER
4351 + This causes JFFS2 to read back every page written through the
4352 + write-buffer, and check for errors.
4354 config JFFS2_SUMMARY
4355 bool "JFFS2 summary support (EXPERIMENTAL)"
4356 depends on JFFS2_FS && EXPERIMENTAL
4357 @@ -1295,52 +1320,52 @@ config JFFS2_ZLIB
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.
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.
4372 - Say 'Y' if unsure.
4373 + Say 'Y' if unsure.
4376 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
4380 - Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4382 + Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4385 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
4389 - RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4391 + RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4394 - prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4395 - default JFFS2_CMODE_PRIORITY
4396 - depends on JFFS2_FS
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
4404 + You can set here the default compression mode of JFFS2 from
4405 + the available compression modes. Don't touch if unsure.
4407 config JFFS2_CMODE_NONE
4408 - bool "no compression"
4410 - Uses no compression.
4411 + bool "no compression"
4413 + Uses no compression.
4415 config JFFS2_CMODE_PRIORITY
4418 - Tries the compressors in a predefined order and chooses the first
4422 + Tries the compressors in a predefined order and chooses the first
4425 config JFFS2_CMODE_SIZE
4426 - bool "size (EXPERIMENTAL)"
4428 - Tries all compressors and chooses the one which has the smallest
4430 + bool "size (EXPERIMENTAL)"
4432 + Tries all compressors and chooses the one which has the smallest
4437 diff --git a/fs/Makefile b/fs/Makefile
4438 index 720c29d..61f1a4d 100644
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)
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);
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
4469 * Created by Arjan van de Ven <arjanv@redhat.com>
4471 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4472 - * University of Szeged, Hungary
4473 + * University of Szeged, Hungary
4475 * For licensing information, see the file 'LICENCE' in this directory.
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.
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)
4486 int ret = JFFS2_COMPR_NONE;
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;
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;
4498 - switch (jffs2_compression_mode) {
4499 - case JFFS2_COMPR_MODE_NONE:
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");
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))
4514 + switch (jffs2_compression_mode) {
4515 + case JFFS2_COMPR_MODE_NONE:
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");
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))
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);
4539 - ret = this->compr;
4540 - this->stat_compr_blocks++;
4541 - this->stat_compr_orig_size += *datalen;
4542 - this->stat_compr_new_size += *cdatalen;
4546 - spin_unlock(&jffs2_compressor_list_lock);
4547 - if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
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))
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;
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);
4570 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4574 - this->compr_buf = tmp_buf;
4575 - this->compr_buf_size = orig_dlen;
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);
4586 - if ((!best_dlen)||(best_dlen>*cdatalen)) {
4587 - best_dlen = *cdatalen;
4588 - best_slen = *datalen;
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;
4604 - spin_unlock(&jffs2_compressor_list_lock);
4607 - printk(KERN_ERR "JFFS2: unknow compression mode.\n");
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);
4617 + ret = this->compr;
4618 + this->stat_compr_blocks++;
4619 + this->stat_compr_orig_size += *datalen;
4620 + this->stat_compr_new_size += *cdatalen;
4624 + spin_unlock(&jffs2_compressor_list_lock);
4625 + if (ret == JFFS2_COMPR_NONE)
4626 + kfree(output_buf);
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))
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;
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);
4649 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4653 + this->compr_buf = tmp_buf;
4654 + this->compr_buf_size = orig_dlen;
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);
4665 + if ((!best_dlen)||(best_dlen>*cdatalen)) {
4666 + best_dlen = *cdatalen;
4667 + best_slen = *datalen;
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;
4683 + spin_unlock(&jffs2_compressor_list_lock);
4686 + printk(KERN_ERR "JFFS2: unknow compression mode.\n");
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;
4696 - *cpage_out = output_buf;
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;
4705 + *cpage_out = output_buf;
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)
4714 - struct jffs2_compressor *this;
4716 + struct jffs2_compressor *this;
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++;
4728 case JFFS2_COMPR_ZERO:
4729 memset(data_out, 0, datalen);
4732 - spin_lock(&jffs2_compressor_list_lock);
4733 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4734 - if (comprtype == this->compr) {
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);
4740 - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4743 - this->stat_decompr_blocks++;
4746 - spin_unlock(&jffs2_compressor_list_lock);
4750 + spin_lock(&jffs2_compressor_list_lock);
4751 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4752 + if (comprtype == this->compr) {
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);
4758 + printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4761 + this->stat_decompr_blocks++;
4764 + spin_unlock(&jffs2_compressor_list_lock);
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);
4774 @@ -210,108 +211,108 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4776 int jffs2_register_compressor(struct jffs2_compressor *comp)
4778 - struct jffs2_compressor *this;
4779 + struct jffs2_compressor *this;
4781 - if (!comp->name) {
4782 - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4785 - comp->compr_buf_size=0;
4786 - comp->compr_buf=NULL;
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");
4797 + comp->compr_buf_size=0;
4798 + comp->compr_buf=NULL;
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));
4806 - spin_lock(&jffs2_compressor_list_lock);
4807 + spin_lock(&jffs2_compressor_list_lock);
4809 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4810 - if (this->priority < comp->priority) {
4811 - list_add(&comp->list, this->list.prev);
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);
4822 + list_add_tail(&comp->list, &jffs2_compressor_list);
4824 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4825 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4827 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4828 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4831 - spin_unlock(&jffs2_compressor_list_lock);
4832 + spin_unlock(&jffs2_compressor_list_lock);
4838 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
4840 - D2(struct jffs2_compressor *this;)
4841 + D2(struct jffs2_compressor *this;)
4843 - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4844 + D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4846 - spin_lock(&jffs2_compressor_list_lock);
4847 + spin_lock(&jffs2_compressor_list_lock);
4849 - if (comp->usecount) {
4850 - spin_unlock(&jffs2_compressor_list_lock);
4851 - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
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");
4860 + list_del(&comp->list);
4862 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4863 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4865 - spin_unlock(&jffs2_compressor_list_lock);
4867 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4868 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4870 + spin_unlock(&jffs2_compressor_list_lock);
4874 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
4876 - if (orig != comprbuf)
4878 + if (orig != comprbuf)
4882 int __init jffs2_compressors_init(void)
4884 /* Registering compressors */
4885 #ifdef CONFIG_JFFS2_ZLIB
4886 - jffs2_zlib_init();
4887 + jffs2_zlib_init();
4889 #ifdef CONFIG_JFFS2_RTIME
4890 - jffs2_rtime_init();
4891 + jffs2_rtime_init();
4893 #ifdef CONFIG_JFFS2_RUBIN
4894 - jffs2_rubinmips_init();
4895 - jffs2_dynrubin_init();
4896 + jffs2_rubinmips_init();
4897 + jffs2_dynrubin_init();
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");)
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");)
4912 - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4913 + D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4920 int jffs2_compressors_exit(void)
4922 /* Unregistering compressors */
4923 #ifdef CONFIG_JFFS2_RUBIN
4924 - jffs2_dynrubin_exit();
4925 - jffs2_rubinmips_exit();
4926 + jffs2_dynrubin_exit();
4927 + jffs2_rubinmips_exit();
4929 #ifdef CONFIG_JFFS2_RTIME
4930 - jffs2_rtime_exit();
4931 + jffs2_rtime_exit();
4933 #ifdef CONFIG_JFFS2_ZLIB
4934 - jffs2_zlib_exit();
4935 + jffs2_zlib_exit();
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
4945 * JFFS2 -- Journalling Flash File System, Version 2.
4947 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4948 - * University of Szeged, Hungary
4949 + * University of Szeged, Hungary
4951 * For licensing information, see the file 'LICENCE' in this directory.
4954 #define JFFS2_ZLIB_PRIORITY 60
4956 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
4957 -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4958 +#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4960 #define JFFS2_COMPR_MODE_NONE 0
4961 #define JFFS2_COMPR_MODE_PRIORITY 1
4962 #define JFFS2_COMPR_MODE_SIZE 2
4964 struct jffs2_compressor {
4965 - struct list_head list;
4966 - int priority; /* used by prirority comr. mode */
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);
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 */
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);
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;
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);
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);
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);
5015 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
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,
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,
5037 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
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];
5046 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
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,
5058 zlib_inflateEnd(&inf_strm);
5059 mutex_unlock(&inflate_mutex);
5064 static struct jffs2_compressor jffs2_zlib_comp = {
5065 @@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
5067 ret = alloc_workspaces();
5072 ret = jffs2_register_compressor(&jffs2_zlib_comp);
5074 - free_workspaces();
5075 + free_workspaces();
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 *);
5090 const struct file_operations jffs2_dir_operations =
5092 @@ -770,7 +770,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
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)
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,
5107 ret = jffs2_flash_erase(c, jeb);
5109 - jffs2_erase_succeeded(c, jeb);
5111 + jffs2_erase_succeeded(c, jeb);
5114 bad_offset = jeb->offset;
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);
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);
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);
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);
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);
5160 jffs2_erase_block(c, jeb);
5162 @@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
5168 + down(&c->erase_free_sem);
5169 spin_lock(&c->erase_completion_lock);
5172 spin_unlock(&c->erase_completion_lock);
5173 + up(&c->erase_free_sem);
5175 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
5177 - up(&c->erase_free_sem);
5180 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
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);
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);
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);
5218 @@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
5222 + if (c->mtd->point) {
5223 + unsigned long *wordebuf;
5225 + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
5227 + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
5228 + goto do_flash_read;
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;
5236 + wordebuf = ebuf-sizeof(*wordebuf);
5237 + retlen /= sizeof(*wordebuf);
5239 + if (*++wordebuf != ~0)
5241 + } while(--retlen);
5242 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
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));
5249 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
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);
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);
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);
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);
5289 diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
5290 index 2d99e06..eded819 100644
5293 @@ -556,7 +556,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
5295 node = kmalloc(rawlen, GFP_KERNEL);
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,
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);
5309 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
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 {
5317 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
5319 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5320 + unsigned char *wbuf_verify; /* read-back buffer for verification */
5322 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
5323 unsigned char *wbuf; /* Write-behind buffer for NAND flash */
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);
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
5342 -#define INOCACHE_HASHSIZE 128
5343 +#define INOCACHE_HASHSIZE 1024
5345 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
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);
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));
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);
5367 + printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
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);
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 *
5381 * Returns 0 if the node was handled (including marking it obsolete)
5382 - * < 0 an if error occurred
5383 + * < 0 an if error occurred
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",
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);
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)))
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)
5417 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
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
5433 * JFFS2 -- Journalling Flash File System, Version 2.
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>
5445 * For licensing information, see the file 'LICENCE' in this directory.
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
5452 * JFFS2 -- Journalling Flash File System, Version 2.
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
5462 * For licensing information, see the file 'LICENCE' in this directory.
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
5472 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5473 +static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
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);
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);
5488 + if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
5491 + if (ret == -EUCLEAN)
5492 + eccstr = "corrected";
5493 + else if (ret == -EBADMSG)
5494 + eccstr = "correction failed";
5496 + eccstr = "OK or unused";
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);
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);
5510 +#define jffs2_verify_write(c,b,o) (0)
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. */
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,
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");
5525 @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
5527 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
5529 - if (ret || retlen != c->wbuf_pagesize) {
5531 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
5533 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5534 - retlen, c->wbuf_pagesize);
5539 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
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);
5546 + } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
5548 jffs2_wbuf_recover(c);
5551 @@ -966,8 +1008,8 @@ exit:
5553 #define NR_OOB_SCAN_PAGES 4
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
5560 static const struct jffs2_unknown_node oob_cleanmarker =
5562 @@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
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
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)
5577 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5578 + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
5579 + if (!c->wbuf_verify) {
5588 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
5590 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5591 + kfree(c->wbuf_verify);
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);
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);
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
5614 #include "nodelist.h"
5616 static int jffs2_user_getxattr(struct inode *inode, const char *name,
5617 - void *buffer, size_t size)
5618 + void *buffer, size_t size)
5620 if (!strcmp(name, ""))
5622 @@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct inode *inode, const char *name,
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)
5629 if (!strcmp(name, ""))
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);
5641 +#define MFGPT_TIMER_ANY -1
5643 +#define MFGPT_DOMAIN_WORKING 1
5644 +#define MFGPT_DOMAIN_STANDBY 2
5645 +#define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY)
5647 +#define MFGPT_CMP1 0
5648 +#define MFGPT_CMP2 1
5650 +#define MFGPT_EVENT_IRQ 0
5651 +#define MFGPT_EVENT_NMI 1
5652 +#define MFGPT_EVENT_RESET 3
5654 +#define MFGPT_REG_CMP1 0
5655 +#define MFGPT_REG_CMP2 2
5656 +#define MFGPT_REG_COUNTER 4
5657 +#define MFGPT_REG_SETUP 6
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)
5668 +static inline void geode_mfgpt_write(int timer, u16 reg, u16 value)
5670 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5671 + outw(value, base + reg + (timer * 8));
5674 +static inline u16 geode_mfgpt_read(int timer, u16 reg)
5676 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5677 + return inw(base + reg + (timer * 8));
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);
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)
5688 /* Specific geode tests */
5690 static inline int is_geode_gx(void)
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
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 */
5702 #ifndef __ASSEMBLY__
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);
5712 -#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
5713 +extern int serial_console_suspend_enabled;
5715 /* Suspend and resume console messages over PM events */
5716 extern void suspend_console(void);
5717 extern void resume_console(void);
5719 -static inline void suspend_console(void) {}
5720 -static inline void resume_console(void) {}
5721 -#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
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);
5733 + /* Shut down the graphics engine to save power */
5734 + int (*fb_powerdown)(struct fb_info *info);
5736 + /* Power it back up */
5737 + int (*fb_powerup)(struct fb_info *info);
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);
5746 +extern int fb_powerdown(struct fb_info *info);
5747 +extern int fb_powerup(struct fb_info *info);
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;
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)
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)
5785 +#ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
5786 +#define ONENAND_IS_2PLANE(this) \
5787 + (this->options & ONENAND_HAS_2PLANE)
5789 +#define ONENAND_IS_2PLANE(this) (0)
5792 /* Check byte access in OneNAND */
5793 #define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
5795 @@ -157,6 +168,7 @@ struct onenand_chip {
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)
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
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)
5815 * Version ID Register F002h (R)
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 {
5831 extern struct vt_spawn_console vt_spawn_con;
5833 +/* A notifier list for console events */
5834 +extern struct raw_notifier_head console_notifier_list;
5836 +/* Called when the FG console switches to KD_TEXT mode */
5837 +#define CONSOLE_EVENT_SWITCH_TEXT 0x01
5839 +/* Called when the FG console switches to KD_GRAPHICS mode */
5840 +#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
5842 +static inline int console_event_register(struct notifier_block *n)
5844 + return raw_notifier_chain_register(&console_notifier_list, n);
5847 +static inline int console_event_unregister(struct notifier_block *n)
5849 + return raw_notifier_chain_unregister(&console_notifier_list, n);
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
5858 #include <linux/console.h>
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)
5865 static int orig_fgconsole, orig_kmsg;