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/card/block.c b/drivers/mmc/card/block.c
742 index 93fe2e5..e17eb8e 100644
743 --- a/drivers/mmc/card/block.c
744 +++ b/drivers/mmc/card/block.c
745 @@ -229,6 +229,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
746 if (brq.data.blocks > card->host->max_blk_count)
747 brq.data.blocks = card->host->max_blk_count;
749 + if (mmc_card_sd(card) && !card->host->ios.clock) {
750 + printk(KERN_ERR "%s: I/O to stopped card\n",
751 + req->rq_disk->disk_name);
754 mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
757 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
758 index 20a7d89..9abbb58 100644
759 --- a/drivers/mmc/host/sdhci.c
760 +++ b/drivers/mmc/host/sdhci.c
761 @@ -411,6 +411,12 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
766 + * There's an off-by-one error in the hw that we need to
772 printk(KERN_WARNING "%s: Too large timeout requested!\n",
773 mmc_hostname(host->mmc));
774 @@ -676,19 +682,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
775 if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
776 writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
778 - pwr = SDHCI_POWER_ON;
780 switch (1 << power) {
781 case MMC_VDD_165_195:
782 - pwr |= SDHCI_POWER_180;
783 + pwr = SDHCI_POWER_180;
787 - pwr |= SDHCI_POWER_300;
788 + pwr = SDHCI_POWER_300;
792 - pwr |= SDHCI_POWER_330;
793 + pwr = SDHCI_POWER_330;
797 @@ -696,6 +700,10 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
799 writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
801 + pwr |= SDHCI_POWER_ON;
803 + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
808 diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
809 index fbec8cd..8848e8a 100644
810 --- a/drivers/mtd/Kconfig
811 +++ b/drivers/mtd/Kconfig
812 @@ -278,6 +278,14 @@ config SSFDC
813 This enables read only access to SmartMedia formatted NAND
814 flash. You can mount it with FAT file system.
817 + tristate "Log panic/oops to an MTD buffer"
820 + This enables panic and oops messages to be logged to a circular
821 + buffer in a flash partition where it can be read back at some
824 source "drivers/mtd/chips/Kconfig"
826 source "drivers/mtd/maps/Kconfig"
827 diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
828 index 6d958a4..7f0b04b 100644
829 --- a/drivers/mtd/Makefile
830 +++ b/drivers/mtd/Makefile
831 @@ -22,6 +22,7 @@ obj-$(CONFIG_NFTL) += nftl.o
832 obj-$(CONFIG_INFTL) += inftl.o
833 obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
834 obj-$(CONFIG_SSFDC) += ssfdc.o
835 +obj-$(CONFIG_MTD_OOPS) += mtdoops.o
837 nftl-objs := nftlcore.o nftlmount.o
838 inftl-objs := inftlcore.o inftlmount.o
839 diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
840 index 2f19fa7..39eff9f 100644
841 --- a/drivers/mtd/chips/cfi_cmdset_0001.c
842 +++ b/drivers/mtd/chips/cfi_cmdset_0001.c
843 @@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
844 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
847 - * Probing of multi-partition flash ships.
848 + * Probing of multi-partition flash chips.
850 * To support multiple partitions when available, we simply arrange
851 * for each of them to have their own flchip structure even if they
852 @@ -1780,7 +1780,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
856 -int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
857 +static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
859 unsigned long ofs, len;
861 @@ -1930,7 +1930,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
862 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
863 __FUNCTION__, ofs, len);
864 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
869 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
870 @@ -1940,7 +1940,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
871 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
873 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
879 @@ -1954,7 +1954,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
880 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
881 __FUNCTION__, ofs, len);
882 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
887 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
888 @@ -1964,7 +1964,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
889 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
891 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
897 @@ -2255,7 +2255,7 @@ static void cfi_intelext_save_locks(struct mtd_info *mtd)
898 adr = region->offset + block * len;
900 status = cfi_varsize_frob(mtd,
901 - do_getlockstatus_oneblock, adr, len, 0);
902 + do_getlockstatus_oneblock, adr, len, NULL);
904 set_bit(block, region->lockmap);
906 diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
907 index 1f64458..389acc6 100644
908 --- a/drivers/mtd/chips/cfi_cmdset_0002.c
909 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c
910 @@ -1609,7 +1609,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
914 -int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
915 +static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
917 unsigned long ofs, len;
919 diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
920 index 58e561e..593e9d6 100644
921 --- a/drivers/mtd/chips/jedec_probe.c
922 +++ b/drivers/mtd/chips/jedec_probe.c
926 #define MBM29F040C 0x00A4
927 +#define MBM29F800BA 0x2258
928 #define MBM29LV650UE 0x22D7
929 #define MBM29LV320TE 0x22F6
930 #define MBM29LV320BE 0x22F9
932 #define LH28F640BF 0x00b0
934 /* ST - www.st.com */
935 +#define M29F800AB 0x0058
936 #define M29W800DT 0x00D7
937 #define M29W800DB 0x005B
938 #define M29W160DT 0x22C4
939 @@ -646,6 +648,23 @@ static const struct amd_flash_info jedec_table[] = {
942 .mfr_id = MANUFACTURER_FUJITSU,
943 + .dev_id = MBM29F800BA,
944 + .name = "Fujitsu MBM29F800BA",
946 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
947 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
949 + .DevSize = SIZE_1MiB,
950 + .CmdSet = P_ID_AMD_STD,
951 + .NumEraseRegions= 4,
953 + ERASEINFO(0x04000,1),
954 + ERASEINFO(0x02000,2),
955 + ERASEINFO(0x08000,1),
956 + ERASEINFO(0x10000,15),
959 + .mfr_id = MANUFACTURER_FUJITSU,
960 .dev_id = MBM29LV650UE,
961 .name = "Fujitsu MBM29LV650UE",
963 @@ -1510,6 +1529,23 @@ static const struct amd_flash_info jedec_table[] = {
964 ERASEINFO(0x1000,256)
968 + .mfr_id = MANUFACTURER_ST,
969 + .dev_id = M29F800AB,
970 + .name = "ST M29F800AB",
972 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
973 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
975 + .DevSize = SIZE_1MiB,
976 + .CmdSet = P_ID_AMD_STD,
977 + .NumEraseRegions= 4,
979 + ERASEINFO(0x04000,1),
980 + ERASEINFO(0x02000,2),
981 + ERASEINFO(0x08000,1),
982 + ERASEINFO(0x10000,15),
985 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
987 diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
988 index ff642f8..b4ea64d 100644
989 --- a/drivers/mtd/devices/Kconfig
990 +++ b/drivers/mtd/devices/Kconfig
991 @@ -69,12 +69,21 @@ config MTD_DATAFLASH26
992 If you have such a board and such a DataFlash, say 'Y'.
995 - tristate "Support for M25 SPI Flash"
996 + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
997 depends on SPI_MASTER && EXPERIMENTAL
999 - This enables access to ST M25P80 and similar SPI flash chips,
1000 - used for program and data storage. Set up your spi devices
1001 - with the right board-specific platform data.
1002 + This enables access to most modern SPI flash chips, used for
1003 + program and data storage. Series supported include Atmel AT26DF,
1004 + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
1005 + are supported as well. See the driver source for the current list,
1006 + or to add other chips.
1008 + Note that the original DataFlash chips (AT45 series, not AT26DF),
1009 + need an entirely different driver.
1011 + Set up your spi devices with the right board-specific platform data,
1012 + if you want to specify device partitioning or to use a device which
1013 + doesn't support the JEDEC ID instruction.
1016 tristate "Uncached system RAM"
1017 diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
1018 index 78c2511..98df5bc 100644
1019 --- a/drivers/mtd/devices/m25p80.c
1020 +++ b/drivers/mtd/devices/m25p80.c
1023 - * MTD SPI driver for ST M25Pxx flash chips
1024 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
1026 * Author: Mike Lavender, mike@steroidmicros.com
1029 #include <linux/module.h>
1030 #include <linux/device.h>
1031 #include <linux/interrupt.h>
1032 -#include <linux/interrupt.h>
1033 +#include <linux/mutex.h>
1035 #include <linux/mtd/mtd.h>
1036 #include <linux/mtd/partitions.h>
1038 #include <linux/spi/spi.h>
1039 #include <linux/spi/flash.h>
1041 -#include <asm/semaphore.h>
1044 -/* NOTE: AT 25F and SST 25LF series are very similar,
1045 - * but commands for sector erase and chip id differ...
1048 #define FLASH_PAGESIZE 256
1050 /* Flash opcodes. */
1051 -#define OPCODE_WREN 6 /* Write enable */
1052 -#define OPCODE_RDSR 5 /* Read status register */
1053 -#define OPCODE_READ 3 /* Read data bytes */
1054 -#define OPCODE_PP 2 /* Page program */
1055 -#define OPCODE_SE 0xd8 /* Sector erase */
1056 -#define OPCODE_RES 0xab /* Read Electronic Signature */
1057 +#define OPCODE_WREN 0x06 /* Write enable */
1058 +#define OPCODE_RDSR 0x05 /* Read status register */
1059 +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
1060 +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
1061 +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
1062 +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
1063 +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
1064 +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
1065 #define OPCODE_RDID 0x9f /* Read JEDEC ID */
1067 /* Status Register bits. */
1068 #define SR_WIP 1 /* Write in progress */
1069 #define SR_WEL 2 /* Write enable latch */
1070 +/* meaning of other SR_* bits may differ between vendors */
1071 #define SR_BP0 4 /* Block protect 0 */
1072 #define SR_BP1 8 /* Block protect 1 */
1073 #define SR_BP2 0x10 /* Block protect 2 */
1077 struct spi_device *spi;
1078 - struct semaphore lock;
1079 + struct mutex lock;
1080 struct mtd_info mtd;
1081 - unsigned partitioned;
1082 + unsigned partitioned:1;
1087 @@ -150,8 +150,9 @@ static int wait_till_ready(struct m25p *flash)
1089 static int erase_sector(struct m25p *flash, u32 offset)
1091 - DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
1092 - __FUNCTION__, offset);
1093 + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
1094 + flash->spi->dev.bus_id, __FUNCTION__,
1095 + flash->mtd.erasesize / 1024, offset);
1097 /* Wait until finished previous write command. */
1098 if (wait_till_ready(flash))
1099 @@ -161,7 +162,7 @@ static int erase_sector(struct m25p *flash, u32 offset)
1100 write_enable(flash);
1102 /* Set up command buffer. */
1103 - flash->command[0] = OPCODE_SE;
1104 + flash->command[0] = flash->erase_opcode;
1105 flash->command[1] = offset >> 16;
1106 flash->command[2] = offset >> 8;
1107 flash->command[3] = offset;
1108 @@ -201,13 +202,17 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
1112 - down(&flash->lock);
1113 + mutex_lock(&flash->lock);
1115 + /* REVISIT in some cases we could speed up erasing large regions
1116 + * by using OPCODE_SE instead of OPCODE_BE_4K
1119 /* now erase those sectors */
1121 if (erase_sector(flash, addr)) {
1122 instr->state = MTD_ERASE_FAILED;
1124 + mutex_unlock(&flash->lock);
1128 @@ -215,7 +220,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
1129 len -= mtd->erasesize;
1133 + mutex_unlock(&flash->lock);
1135 instr->state = MTD_ERASE_DONE;
1136 mtd_erase_callback(instr);
1137 @@ -260,16 +265,19 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
1141 - down(&flash->lock);
1142 + mutex_lock(&flash->lock);
1144 /* Wait till previous write/erase is done. */
1145 if (wait_till_ready(flash)) {
1146 /* REVISIT status return?? */
1148 + mutex_unlock(&flash->lock);
1152 - /* NOTE: OPCODE_FAST_READ (if available) is faster... */
1153 + /* FIXME switch to OPCODE_FAST_READ. It's required for higher
1154 + * clocks; and at this writing, every chip this driver handles
1155 + * supports that opcode.
1158 /* Set up the write data buffer. */
1159 flash->command[0] = OPCODE_READ;
1160 @@ -281,7 +289,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
1162 *retlen = m.actual_length - sizeof(flash->command);
1165 + mutex_unlock(&flash->lock);
1169 @@ -323,7 +331,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
1171 spi_message_add_tail(&t[1], &m);
1173 - down(&flash->lock);
1174 + mutex_lock(&flash->lock);
1176 /* Wait until finished previous write command. */
1177 if (wait_till_ready(flash))
1178 @@ -381,10 +389,10 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
1180 *retlen += m.actual_length
1181 - sizeof(flash->command);
1188 + mutex_unlock(&flash->lock);
1192 @@ -398,24 +406,118 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
1199 + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
1200 + * a high byte of zero plus three data bytes: the manufacturer id,
1201 + * then a two byte device id.
1205 + /* The size listed here is what works with OPCODE_SE, which isn't
1206 + * necessarily called a "sector" by the vendor.
1208 unsigned sector_size;
1209 - unsigned n_sectors;
1213 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
1217 +/* NOTE: double check command sets and memory organization when you add
1218 + * more flash chips. This current list focusses on newer chips, which
1219 + * have been converging on command sets which including JEDEC ID.
1221 static struct flash_info __devinitdata m25p_data [] = {
1222 - /* REVISIT: fill in JEDEC ids, for parts that have them */
1223 - { "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
1224 - { "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
1225 - { "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
1226 - { "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
1227 - { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
1228 - { "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
1229 - { "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
1230 - { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
1232 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
1233 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
1234 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
1236 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
1238 + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
1239 + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
1240 + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
1241 + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
1243 + /* Spansion -- single (large) sector size only, at least
1244 + * for the chips listed here (without boot sectors).
1246 + { "s25sl004a", 0x010212, 64 * 1024, 8, },
1247 + { "s25sl008a", 0x010213, 64 * 1024, 16, },
1248 + { "s25sl016a", 0x010214, 64 * 1024, 32, },
1249 + { "s25sl032a", 0x010215, 64 * 1024, 64, },
1250 + { "s25sl064a", 0x010216, 64 * 1024, 128, },
1252 + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
1253 + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
1254 + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
1255 + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
1256 + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
1258 + /* ST Microelectronics -- newer production may have feature updates */
1259 + { "m25p05", 0x202010, 32 * 1024, 2, },
1260 + { "m25p10", 0x202011, 32 * 1024, 4, },
1261 + { "m25p20", 0x202012, 64 * 1024, 4, },
1262 + { "m25p40", 0x202013, 64 * 1024, 8, },
1263 + { "m25p80", 0, 64 * 1024, 16, },
1264 + { "m25p16", 0x202015, 64 * 1024, 32, },
1265 + { "m25p32", 0x202016, 64 * 1024, 64, },
1266 + { "m25p64", 0x202017, 64 * 1024, 128, },
1267 + { "m25p128", 0x202018, 256 * 1024, 64, },
1269 + { "m45pe80", 0x204014, 64 * 1024, 16, },
1270 + { "m45pe16", 0x204015, 64 * 1024, 32, },
1272 + { "m25pe80", 0x208014, 64 * 1024, 16, },
1273 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
1275 + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
1276 + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
1277 + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
1278 + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
1279 + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
1280 + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
1281 + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
1282 + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
1285 +static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
1288 + u8 code = OPCODE_RDID;
1291 + struct flash_info *info;
1293 + /* JEDEC also defines an optional "extended device information"
1294 + * string for after vendor-specific data, after the three bytes
1295 + * we use here. Supporting some chips might require using it.
1297 + tmp = spi_write_then_read(spi, &code, 1, id, 3);
1299 + DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
1300 + spi->dev.bus_id, tmp);
1304 + jedec = jedec << 8;
1306 + jedec = jedec << 8;
1309 + for (tmp = 0, info = m25p_data;
1310 + tmp < ARRAY_SIZE(m25p_data);
1312 + if (info->jedec_id == jedec)
1315 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
1321 * board specific setup should have ensured the SPI clock used here
1322 * matches what the READ command supports, at least until this driver
1323 @@ -429,37 +531,51 @@ static int __devinit m25p_probe(struct spi_device *spi)
1326 /* Platform data helps sort out which chip type we have, as
1327 - * well as how this board partitions it.
1328 + * well as how this board partitions it. If we don't have
1329 + * a chip ID, try the JEDEC id commands; they'll work for most
1330 + * newer chips, even if we don't recognize the particular chip.
1332 data = spi->dev.platform_data;
1333 - if (!data || !data->type) {
1334 - /* FIXME some chips can identify themselves with RES
1335 - * or JEDEC get-id commands. Try them ...
1337 - DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
1341 + if (data && data->type) {
1342 + for (i = 0, info = m25p_data;
1343 + i < ARRAY_SIZE(m25p_data);
1345 + if (strcmp(data->type, info->name) == 0)
1349 - for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
1350 - if (strcmp(data->type, info->name) == 0)
1353 - if (i == ARRAY_SIZE(m25p_data)) {
1354 - DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
1355 - spi->dev.bus_id, data->type);
1356 + /* unrecognized chip? */
1357 + if (i == ARRAY_SIZE(m25p_data)) {
1358 + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
1359 + spi->dev.bus_id, data->type);
1362 + /* recognized; is that chip really what's there? */
1363 + } else if (info->jedec_id) {
1364 + struct flash_info *chip = jedec_probe(spi);
1366 + if (!chip || chip != info) {
1367 + dev_warn(&spi->dev, "found %s, expected %s\n",
1368 + chip ? chip->name : "UNKNOWN",
1374 + info = jedec_probe(spi);
1380 flash = kzalloc(sizeof *flash, GFP_KERNEL);
1385 - init_MUTEX(&flash->lock);
1386 + mutex_init(&flash->lock);
1387 dev_set_drvdata(&spi->dev, flash);
1390 + if (data && data->name)
1391 flash->mtd.name = data->name;
1393 flash->mtd.name = spi->dev.bus_id;
1394 @@ -468,17 +584,25 @@ static int __devinit m25p_probe(struct spi_device *spi)
1395 flash->mtd.writesize = 1;
1396 flash->mtd.flags = MTD_CAP_NORFLASH;
1397 flash->mtd.size = info->sector_size * info->n_sectors;
1398 - flash->mtd.erasesize = info->sector_size;
1399 flash->mtd.erase = m25p80_erase;
1400 flash->mtd.read = m25p80_read;
1401 flash->mtd.write = m25p80_write;
1403 + /* prefer "small sector" erase if possible */
1404 + if (info->flags & SECT_4K) {
1405 + flash->erase_opcode = OPCODE_BE_4K;
1406 + flash->mtd.erasesize = 4096;
1408 + flash->erase_opcode = OPCODE_SE;
1409 + flash->mtd.erasesize = info->sector_size;
1412 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
1413 flash->mtd.size / 1024);
1415 DEBUG(MTD_DEBUG_LEVEL2,
1416 - "mtd .name = %s, .size = 0x%.8x (%uM) "
1417 - ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
1418 + "mtd .name = %s, .size = 0x%.8x (%uMiB) "
1419 + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
1421 flash->mtd.size, flash->mtd.size / (1024*1024),
1422 flash->mtd.erasesize, flash->mtd.erasesize / 1024,
1423 @@ -488,7 +612,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
1424 for (i = 0; i < flash->mtd.numeraseregions; i++)
1425 DEBUG(MTD_DEBUG_LEVEL2,
1426 "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
1427 - ".erasesize = 0x%.8x (%uK), "
1428 + ".erasesize = 0x%.8x (%uKiB), "
1429 ".numblocks = %d }\n",
1430 i, flash->mtd.eraseregions[i].offset,
1431 flash->mtd.eraseregions[i].erasesize,
1432 @@ -516,14 +640,14 @@ static int __devinit m25p_probe(struct spi_device *spi)
1436 - for (i = 0; i < data->nr_parts; i++) {
1437 + for (i = 0; i < nr_parts; i++) {
1438 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
1439 "{.name = %s, .offset = 0x%.8x, "
1440 - ".size = 0x%.8x (%uK) }\n",
1441 - i, data->parts[i].name,
1442 - data->parts[i].offset,
1443 - data->parts[i].size,
1444 - data->parts[i].size / 1024);
1445 + ".size = 0x%.8x (%uKiB) }\n",
1449 + parts[i].size / 1024);
1451 flash->partitioned = 1;
1452 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
1453 @@ -560,6 +684,11 @@ static struct spi_driver m25p80_driver = {
1455 .probe = m25p_probe,
1456 .remove = __devexit_p(m25p_remove),
1458 + /* REVISIT: many of these chips have deep power-down modes, which
1459 + * should clearly be entered on suspend() to minimize power use.
1460 + * And also when they're otherwise idle...
1465 diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
1466 index a987e91..a5ed6d2 100644
1467 --- a/drivers/mtd/devices/mtd_dataflash.c
1468 +++ b/drivers/mtd/devices/mtd_dataflash.c
1470 #include <linux/slab.h>
1471 #include <linux/delay.h>
1472 #include <linux/device.h>
1473 +#include <linux/mutex.h>
1474 #include <linux/spi/spi.h>
1475 #include <linux/spi/flash.h>
1477 @@ -89,7 +90,7 @@ struct dataflash {
1478 unsigned short page_offset; /* offset in flash address */
1479 unsigned int page_size; /* of bytes per page */
1481 - struct semaphore lock;
1482 + struct mutex lock;
1483 struct spi_device *spi;
1485 struct mtd_info mtd;
1486 @@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
1488 spi_message_add_tail(&x, &msg);
1490 - down(&priv->lock);
1491 + mutex_lock(&priv->lock);
1492 while (instr->len > 0) {
1493 unsigned int pageaddr;
1495 @@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
1496 instr->len -= priv->page_size;
1500 + mutex_unlock(&priv->lock);
1502 /* Inform MTD subsystem that erase is complete */
1503 instr->state = MTD_ERASE_DONE;
1504 @@ -266,7 +267,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
1506 spi_message_add_tail(&x[1], &msg);
1508 - down(&priv->lock);
1509 + mutex_lock(&priv->lock);
1511 /* Continuous read, max clock = f(car) which may be less than
1512 * the peak rate available. Some chips support commands with
1513 @@ -279,7 +280,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
1514 /* plus 4 "don't care" bytes */
1516 status = spi_sync(priv->spi, &msg);
1518 + mutex_unlock(&priv->lock);
1521 *retlen = msg.actual_length - 8;
1522 @@ -336,7 +337,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
1526 - down(&priv->lock);
1527 + mutex_lock(&priv->lock);
1528 while (remaining > 0) {
1529 DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
1530 pageaddr, offset, writelen);
1531 @@ -441,7 +442,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
1533 writelen = remaining;
1536 + mutex_unlock(&priv->lock);
1540 @@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, char *name,
1544 - init_MUTEX(&priv->lock);
1545 + mutex_init(&priv->lock);
1547 priv->page_size = pagesize;
1548 priv->page_offset = pageoffset;
1549 diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
1550 index e8f686f..7060a08 100644
1551 --- a/drivers/mtd/devices/pmc551.c
1552 +++ b/drivers/mtd/devices/pmc551.c
1556 * Due to what I assume is more buggy SROM, the 64M PMC551 I
1557 - * have available claims that all 4 of it's DRAM banks have 64M
1558 - * of ram configured (making a grand total of 256M onboard).
1559 + * have available claims that all 4 of its DRAM banks have 64MiB
1560 + * of ram configured (making a grand total of 256MiB onboard).
1561 * This is slightly annoying since the BAR0 size reflects the
1562 * aperture size, not the dram size, and the V370PDC supplies no
1563 * other method for memory size discovery. This problem is
1565 * made the memory unusable, added a fix to code to touch up
1570 * * MUST fix the init function to not spin on a register
1571 * waiting for it to set .. this does not safely handle busted
1572 * devices that never reset the register correctly which will
1573 @@ -562,10 +562,10 @@ static u32 fixup_pmc551(struct pci_dev *dev)
1577 - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
1578 + printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
1579 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
1580 size >> 10 : size >> 20,
1581 - (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
1582 + (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
1583 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
1584 (unsigned long long)pci_resource_start(dev, 0));
1586 @@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
1587 * Stuff these outside the ifdef so as to not bust compiled in driver support
1589 static int msize = 0;
1590 -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
1591 -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
1593 static int asize = 0;
1596 module_param(msize, int, 0);
1597 -MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
1598 +MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
1599 module_param(asize, int, 0);
1600 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
1602 @@ -799,8 +795,7 @@ static int __init init_pmc551(void)
1603 mtd->owner = THIS_MODULE;
1605 if (add_mtd_device(mtd)) {
1606 - printk(KERN_NOTICE "pmc551: Failed to register new "
1608 + printk(KERN_NOTICE "pmc551: Failed to register new device\n");
1609 pci_iounmap(PCI_Device, priv->start);
1612 @@ -811,13 +806,13 @@ static int __init init_pmc551(void)
1613 pci_dev_get(PCI_Device);
1615 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
1616 - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
1617 + printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
1619 priv->start, priv->start + priv->asize);
1620 - printk(KERN_NOTICE "Total memory is %d%c\n",
1621 + printk(KERN_NOTICE "Total memory is %d%sB\n",
1622 (length < 1024) ? length :
1623 (length < 1048576) ? length >> 10 : length >> 20,
1624 - (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
1625 + (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
1626 priv->nextpmc551 = pmc551list;
1629 @@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
1630 pmc551list = priv->nextpmc551;
1633 - printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
1634 + printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
1635 "0x%p\n", priv->asize >> 20, priv->start);
1636 pci_iounmap(priv->dev, priv->start);
1638 diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
1639 index 7b96cd0..0c9b305 100644
1640 --- a/drivers/mtd/maps/nettel.c
1641 +++ b/drivers/mtd/maps/nettel.c
1642 @@ -158,68 +158,11 @@ static struct notifier_block nettel_notifier_block = {
1643 nettel_reboot_notifier, NULL, 0
1647 - * Erase the configuration file system.
1648 - * Used to support the software reset button.
1650 -static void nettel_erasecallback(struct erase_info *done)
1652 - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
1656 -static struct erase_info nettel_erase;
1658 -int nettel_eraseconfig(void)
1660 - struct mtd_info *mtd;
1661 - DECLARE_WAITQUEUE(wait, current);
1662 - wait_queue_head_t wait_q;
1665 - init_waitqueue_head(&wait_q);
1666 - mtd = get_mtd_device(NULL, 2);
1667 - if (!IS_ERR(mtd)) {
1668 - nettel_erase.mtd = mtd;
1669 - nettel_erase.callback = nettel_erasecallback;
1670 - nettel_erase.callback = NULL;
1671 - nettel_erase.addr = 0;
1672 - nettel_erase.len = mtd->size;
1673 - nettel_erase.priv = (u_long) &wait_q;
1674 - nettel_erase.priv = 0;
1676 - set_current_state(TASK_INTERRUPTIBLE);
1677 - add_wait_queue(&wait_q, &wait);
1679 - ret = mtd->erase(mtd, &nettel_erase);
1681 - set_current_state(TASK_RUNNING);
1682 - remove_wait_queue(&wait_q, &wait);
1683 - put_mtd_device(mtd);
1687 - schedule(); /* Wait for erase to finish. */
1688 - remove_wait_queue(&wait_q, &wait);
1690 - put_mtd_device(mtd);
1698 -int nettel_eraseconfig(void)
1705 /****************************************************************************/
1707 -int __init nettel_init(void)
1708 +static int __init nettel_init(void)
1710 volatile unsigned long *amdpar;
1711 unsigned long amdaddr, maxsize;
1712 @@ -421,10 +364,6 @@ int __init nettel_init(void)
1714 intel_mtd->owner = THIS_MODULE;
1716 -#ifndef CONFIG_BLK_DEV_INITRD
1717 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
1720 num_intel_partitions = sizeof(nettel_intel_partitions) /
1721 sizeof(nettel_intel_partitions[0]);
1723 @@ -477,7 +416,7 @@ out_unmap2:
1725 /****************************************************************************/
1727 -void __exit nettel_cleanup(void)
1728 +static void __exit nettel_cleanup(void)
1730 #ifdef CONFIG_MTD_CFI_INTELEXT
1731 unregister_reboot_notifier(&nettel_notifier_block);
1732 diff --git a/drivers/mtd/maps/pmcmsp-ramroot.c b/drivers/mtd/maps/pmcmsp-ramroot.c
1733 index 18049bc..30de5c0 100644
1734 --- a/drivers/mtd/maps/pmcmsp-ramroot.c
1735 +++ b/drivers/mtd/maps/pmcmsp-ramroot.c
1736 @@ -79,7 +79,6 @@ static int __init init_rrmap(void)
1737 rr_mtd->owner = THIS_MODULE;
1739 add_mtd_device(rr_mtd);
1740 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
1744 diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
1745 index ef89780..74d9d30 100644
1746 --- a/drivers/mtd/mtd_blkdevs.c
1747 +++ b/drivers/mtd/mtd_blkdevs.c
1749 #include <linux/kthread.h>
1750 #include <asm/uaccess.h>
1752 -static LIST_HEAD(blktrans_majors);
1753 +#include "mtdcore.h"
1755 -extern struct mutex mtd_table_mutex;
1756 -extern struct mtd_info *mtd_table[];
1757 +static LIST_HEAD(blktrans_majors);
1759 struct mtd_blkcore_priv {
1760 struct task_struct *thread;
1761 @@ -202,7 +201,7 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
1765 -struct block_device_operations mtd_blktrans_ops = {
1766 +static struct block_device_operations mtd_blktrans_ops = {
1767 .owner = THIS_MODULE,
1768 .open = blktrans_open,
1769 .release = blktrans_release,
1770 diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
1771 index d091b24..22ed96c 100644
1772 --- a/drivers/mtd/mtdchar.c
1773 +++ b/drivers/mtd/mtdchar.c
1774 @@ -136,7 +136,8 @@ static int mtd_close(struct inode *inode, struct file *file)
1776 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
1779 + /* Only sync if opened RW */
1780 + if ((file->f_mode & 2) && mtd->sync)
1783 put_mtd_device(mtd);
1784 diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
1785 index c153b64..6c2645e 100644
1786 --- a/drivers/mtd/mtdcore.c
1787 +++ b/drivers/mtd/mtdcore.c
1790 #include <linux/mtd/mtd.h>
1792 +#include "mtdcore.h"
1794 /* These are exported solely for the purpose of mtd_blkdevs.c. You
1795 should not use them for _anything_ else */
1796 DEFINE_MUTEX(mtd_table_mutex);
1797 diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
1798 index f1d60b6..df25cab 100644
1799 --- a/drivers/mtd/nand/Kconfig
1800 +++ b/drivers/mtd/nand/Kconfig
1801 @@ -134,10 +134,10 @@ config MTD_NAND_S3C2410_HWECC
1803 config MTD_NAND_NDFC
1804 tristate "NDFC NanD Flash Controller"
1807 select MTD_NAND_ECC_SMC
1809 - NDFC Nand Flash Controllers are integrated in EP44x SoCs
1810 + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
1812 config MTD_NAND_S3C2410_CLKSTOP
1813 bool "S3C2410 NAND IDLE clock stop"
1814 @@ -237,7 +237,7 @@ config MTD_NAND_CAFE
1816 select REED_SOLOMON_DEC16
1818 - Use NAND flash attached to the CAFÉ chip designed for the $100
1819 + Use NAND flash attached to the CAFÉ chip designed for the OLPC
1822 config MTD_NAND_CS553X
1823 diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
1824 index cff969d..cca69b3 100644
1825 --- a/drivers/mtd/nand/cafe_nand.c
1826 +++ b/drivers/mtd/nand/cafe_nand.c
1827 @@ -821,14 +821,53 @@ static struct pci_device_id cafe_nand_tbl[] = {
1829 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
1831 +static int cafe_nand_resume(struct pci_dev *pdev)
1833 + uint32_t timing1, timing2, timing3;
1835 + struct mtd_info *mtd = pci_get_drvdata(pdev);
1836 + struct cafe_priv *cafe = mtd->priv;
1838 + timing1 = timing2 = timing3 = 0xffffffff;
1839 + /* Start off by resetting the NAND controller completely */
1840 + cafe_writel(cafe, 1, NAND_RESET);
1841 + cafe_writel(cafe, 0, NAND_RESET);
1842 + cafe_writel(cafe, timing1, NAND_TIMING1);
1843 + cafe_writel(cafe, timing2, NAND_TIMING2);
1844 + cafe_writel(cafe, timing3, NAND_TIMING3);
1845 + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
1847 + /* Disable master reset, enable NAND clock */
1848 + ctrl = cafe_readl(cafe, GLOBAL_CTRL);
1849 + ctrl &= 0xffffeff0;
1850 + ctrl |= 0x00007000;
1851 + cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
1852 + cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
1853 + cafe_writel(cafe, 0, NAND_DMA_CTRL);
1854 + cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
1855 + cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
1857 + /* Set up DMA address */
1858 + cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
1859 + if (sizeof(cafe->dmaaddr) > 4)
1860 + /* Shift in two parts to shut the compiler up */
1861 + cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
1863 + cafe_writel(cafe, 0, NAND_DMA_ADDR1);
1865 + /* Enable NAND IRQ in global IRQ mask register */
1866 + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
1870 static struct pci_driver cafe_nand_pci_driver = {
1871 .name = "CAFÉ NAND",
1872 .id_table = cafe_nand_tbl,
1873 .probe = cafe_nand_probe,
1874 .remove = __devexit_p(cafe_nand_remove),
1875 + .resume = cafe_nand_resume,
1877 .suspend = cafe_nand_suspend,
1878 - .resume = cafe_nand_resume,
1882 diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
1883 index fd7a8d5..1c0e89f 100644
1884 --- a/drivers/mtd/nand/ndfc.c
1885 +++ b/drivers/mtd/nand/ndfc.c
1887 #include <linux/platform_device.h>
1891 +#include <asm/ibm405.h>
1893 #include <asm/ibm44x.h>
1896 struct ndfc_nand_mtd {
1897 struct mtd_info mtd;
1898 @@ -230,7 +234,11 @@ static int ndfc_nand_probe(struct platform_device *pdev)
1899 struct ndfc_controller *ndfc = &ndfc_ctrl;
1900 unsigned long long phys = settings->ndfc_erpn | res->start;
1902 +#ifndef CONFIG_PHYS_64BIT
1903 + ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
1905 ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
1907 if (!ndfc->ndfcbase) {
1908 printk(KERN_ERR "NDFC: ioremap failed\n");
1910 diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
1911 index c257d39..cb41cbc 100644
1912 --- a/drivers/mtd/onenand/Kconfig
1913 +++ b/drivers/mtd/onenand/Kconfig
1914 @@ -40,4 +40,27 @@ config MTD_ONENAND_OTP
1916 OTP block is fully-guaranteed to be a valid block.
1918 +config MTD_ONENAND_2X_PROGRAM
1919 + bool "OneNAND 2X program support"
1921 + The 2X Program is an extension of Program Operation.
1922 + Since the device is equipped with two DataRAMs, and two-plane NAND
1923 + Flash memory array, these two component enables simultaneous program
1924 + of 4KiB. Plane1 has only even blocks such as block0, block2, block4
1925 + while Plane2 has only odd blocks such as block1, block3, block5.
1926 + So MTD regards it as 4KiB page size and 256KiB block size
1928 + Now the following chips support it. (KFXXX16Q2M)
1929 + Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
1930 + Mux: KFM2G16Q2M, KFN4G16Q2M,
1932 + And more recent chips
1934 +config MTD_ONENAND_SIM
1935 + tristate "OneNAND simulator support"
1936 + depends on MTD_PARTITIONS
1938 + The simulator may simulate various OneNAND flash chips for the
1939 + OneNAND MTD layer.
1942 diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
1943 index 269cfe4..4d2eacf 100644
1944 --- a/drivers/mtd/onenand/Makefile
1945 +++ b/drivers/mtd/onenand/Makefile
1946 @@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
1948 obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
1951 +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
1953 onenand-objs = onenand_base.o onenand_bbt.o
1954 diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
1955 index 0537fac..7d194cf 100644
1956 --- a/drivers/mtd/onenand/onenand_base.c
1957 +++ b/drivers/mtd/onenand/onenand_base.c
1958 @@ -206,6 +206,15 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
1960 block = (int) (addr >> this->erase_shift);
1961 page = (int) (addr >> this->page_shift);
1963 + if (ONENAND_IS_2PLANE(this)) {
1964 + /* Make the even block number */
1966 + /* Is it the odd plane? */
1967 + if (addr & this->writesize)
1971 page &= this->page_mask;
1974 @@ -216,8 +225,12 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
1975 value = onenand_bufferram_address(this, block);
1976 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1978 - /* Switch to the next data buffer */
1979 - ONENAND_SET_NEXT_BUFFERRAM(this);
1980 + if (ONENAND_IS_2PLANE(this))
1981 + /* It is always BufferRAM0 */
1982 + ONENAND_SET_BUFFERRAM0(this);
1984 + /* Switch to the next data buffer */
1985 + ONENAND_SET_NEXT_BUFFERRAM(this);
1989 @@ -247,6 +260,8 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
1993 + if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
1994 + cmd = ONENAND_CMD_2X_PROG;
1995 dataram = ONENAND_CURRENT_BUFFERRAM(this);
1998 @@ -445,8 +460,9 @@ static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area)
1999 struct onenand_chip *this = mtd->priv;
2001 if (ONENAND_CURRENT_BUFFERRAM(this)) {
2002 + /* Note: the 'this->writesize' is a real page size */
2003 if (area == ONENAND_DATARAM)
2004 - return mtd->writesize;
2005 + return this->writesize;
2006 if (area == ONENAND_SPARERAM)
2007 return mtd->oobsize;
2009 @@ -572,6 +588,30 @@ static int onenand_write_bufferram(struct mtd_info *mtd, int area,
2013 + * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode
2014 + * @param mtd MTD data structure
2015 + * @param addr address to check
2016 + * @return blockpage address
2018 + * Get blockpage address at 2x program mode
2020 +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
2022 + struct onenand_chip *this = mtd->priv;
2023 + int blockpage, block, page;
2025 + /* Calculate the even block number */
2026 + block = (int) (addr >> this->erase_shift) & ~1;
2027 + /* Is it the odd plane? */
2028 + if (addr & this->writesize)
2030 + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
2031 + blockpage = (block << 7) | page;
2037 * onenand_check_bufferram - [GENERIC] Check BufferRAM information
2038 * @param mtd MTD data structure
2039 * @param addr address to check
2040 @@ -585,7 +625,10 @@ static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr)
2041 int blockpage, found = 0;
2044 - blockpage = (int) (addr >> this->page_shift);
2045 + if (ONENAND_IS_2PLANE(this))
2046 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2048 + blockpage = (int) (addr >> this->page_shift);
2050 /* Is there valid data? */
2051 i = ONENAND_CURRENT_BUFFERRAM(this);
2052 @@ -625,7 +668,10 @@ static void onenand_update_bufferram(struct mtd_info *mtd, loff_t addr,
2056 - blockpage = (int) (addr >> this->page_shift);
2057 + if (ONENAND_IS_2PLANE(this))
2058 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2060 + blockpage = (int) (addr >> this->page_shift);
2062 /* Invalidate another BufferRAM */
2063 i = ONENAND_NEXT_BUFFERRAM(this);
2064 @@ -734,6 +780,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
2065 int read = 0, column;
2067 int ret = 0, boundary = 0;
2068 + int writesize = this->writesize;
2070 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
2072 @@ -754,22 +801,22 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
2073 /* Do first load to bufferRAM */
2075 if (!onenand_check_bufferram(mtd, from)) {
2076 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2077 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2078 ret = this->wait(mtd, FL_READING);
2079 onenand_update_bufferram(mtd, from, !ret);
2083 - thislen = min_t(int, mtd->writesize, len - read);
2084 - column = from & (mtd->writesize - 1);
2085 - if (column + thislen > mtd->writesize)
2086 - thislen = mtd->writesize - column;
2087 + thislen = min_t(int, writesize, len - read);
2088 + column = from & (writesize - 1);
2089 + if (column + thislen > writesize)
2090 + thislen = writesize - column;
2093 /* If there is more to load then start next load */
2095 if (read + thislen < len) {
2096 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2097 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2099 * Chip boundary handling in DDP
2100 * Now we issued chip 1 read and pointed chip 1
2101 @@ -794,7 +841,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
2102 this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
2103 ONENAND_SET_NEXT_BUFFERRAM(this);
2105 - thislen = min_t(int, mtd->writesize, len - read);
2106 + thislen = min_t(int, writesize, len - read);
2109 /* Now wait for load */
2110 @@ -1079,7 +1126,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
2113 /* Update Page size */
2114 - from += mtd->writesize;
2115 + from += this->writesize;
2119 @@ -1135,12 +1182,12 @@ static int onenand_verify(struct mtd_info *mtd, const u_char *buf, loff_t addr,
2120 int thislen, column;
2123 - thislen = min_t(int, mtd->writesize, len);
2124 - column = addr & (mtd->writesize - 1);
2125 - if (column + thislen > mtd->writesize)
2126 - thislen = mtd->writesize - column;
2127 + thislen = min_t(int, this->writesize, len);
2128 + column = addr & (this->writesize - 1);
2129 + if (column + thislen > this->writesize)
2130 + thislen = this->writesize - column;
2132 - this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
2133 + this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
2135 onenand_update_bufferram(mtd, addr, 0);
2137 @@ -1236,6 +1283,10 @@ static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
2139 /* In partial page write we don't update bufferram */
2140 onenand_update_bufferram(mtd, to, !ret && !subpage);
2141 + if (ONENAND_IS_2PLANE(this)) {
2142 + ONENAND_SET_BUFFERRAM1(this);
2143 + onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
2147 printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
2148 @@ -1384,6 +1435,10 @@ static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
2149 this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
2151 onenand_update_bufferram(mtd, to, 0);
2152 + if (ONENAND_IS_2PLANE(this)) {
2153 + ONENAND_SET_BUFFERRAM1(this);
2154 + onenand_update_bufferram(mtd, to + this->writesize, 0);
2157 ret = this->wait(mtd, FL_WRITING);
2159 @@ -2107,6 +2162,7 @@ static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
2161 * Check and set OneNAND features
2165 static void onenand_check_features(struct mtd_info *mtd)
2167 @@ -2118,19 +2174,35 @@ static void onenand_check_features(struct mtd_info *mtd)
2168 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2171 - if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
2172 + switch (density) {
2173 + case ONENAND_DEVICE_DENSITY_4Gb:
2174 + this->options |= ONENAND_HAS_2PLANE;
2176 + case ONENAND_DEVICE_DENSITY_2Gb:
2177 + /* 2Gb DDP don't have 2 plane */
2178 + if (!ONENAND_IS_DDP(this))
2179 + this->options |= ONENAND_HAS_2PLANE;
2180 + this->options |= ONENAND_HAS_UNLOCK_ALL;
2182 + case ONENAND_DEVICE_DENSITY_1Gb:
2183 /* A-Die has all block unlock */
2185 - printk(KERN_DEBUG "Chip support all block unlock\n");
2187 this->options |= ONENAND_HAS_UNLOCK_ALL;
2190 - /* Some OneNAND has continues lock scheme */
2192 - printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
2196 + /* Some OneNAND has continuous lock scheme */
2198 this->options |= ONENAND_HAS_CONT_LOCK;
2203 + if (this->options & ONENAND_HAS_CONT_LOCK)
2204 + printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2205 + if (this->options & ONENAND_HAS_UNLOCK_ALL)
2206 + printk(KERN_DEBUG "Chip support all block unlock\n");
2207 + if (this->options & ONENAND_HAS_2PLANE)
2208 + printk(KERN_DEBUG "Chip has 2 plane\n");
2212 @@ -2257,6 +2329,8 @@ static int onenand_probe(struct mtd_info *mtd)
2213 this->erase_shift = ffs(mtd->erasesize) - 1;
2214 this->page_shift = ffs(mtd->writesize) - 1;
2215 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
2216 + /* It's real page size */
2217 + this->writesize = mtd->writesize;
2219 /* REVIST: Multichip handling */
2221 @@ -2265,6 +2339,17 @@ static int onenand_probe(struct mtd_info *mtd)
2222 /* Check OneNAND features */
2223 onenand_check_features(mtd);
2226 + * We emulate the 4KiB page and 256KiB erase block size
2227 + * But oobsize is still 64 bytes.
2228 + * It is only valid if you turn on 2X program support,
2229 + * Otherwise it will be ignored by compiler.
2231 + if (ONENAND_IS_2PLANE(this)) {
2232 + mtd->writesize <<= 1;
2233 + mtd->erasesize <<= 1;
2239 diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
2240 index 1938d6d..cc01dbd 100644
2241 --- a/drivers/net/forcedeth.c
2242 +++ b/drivers/net/forcedeth.c
2243 @@ -3556,10 +3556,12 @@ static int nv_request_irq(struct net_device *dev, int intr_test)
2245 if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
2246 if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
2247 + pci_intx(np->pci_dev, 0);
2248 np->msi_flags |= NV_MSI_ENABLED;
2249 if (request_irq(np->pci_dev->irq, handler, IRQF_SHARED, dev->name, dev) != 0) {
2250 printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
2251 pci_disable_msi(np->pci_dev);
2252 + pci_intx(np->pci_dev, 1);
2253 np->msi_flags &= ~NV_MSI_ENABLED;
2256 @@ -3601,6 +3603,7 @@ static void nv_free_irq(struct net_device *dev)
2257 free_irq(np->pci_dev->irq, dev);
2258 if (np->msi_flags & NV_MSI_ENABLED) {
2259 pci_disable_msi(np->pci_dev);
2260 + pci_intx(np->pci_dev, 1);
2261 np->msi_flags &= ~NV_MSI_ENABLED;
2264 diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
2265 index 7dcaa09..eb69d4d 100644
2266 --- a/drivers/pci/quirks.c
2267 +++ b/drivers/pci/quirks.c
2268 @@ -1390,6 +1390,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm);
2269 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
2272 + * According to Tom Sylla, the Geode does not support PCI power management
2273 + * transition, so we shouldn't need the D3hot delay.
2275 +static void __init quirk_geode_pci_pm(struct pci_dev *dev)
2277 + pci_pm_d3_delay = 0;
2279 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, quirk_geode_pci_pm);
2280 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_geode_pci_pm);
2283 * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size
2284 * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
2285 * Re-allocate the region if needed...
2286 diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
2287 index 5216c11..3e3df7e 100644
2288 --- a/drivers/video/Kconfig
2289 +++ b/drivers/video/Kconfig
2290 @@ -594,7 +594,7 @@ config FB_TGA
2293 bool "VESA VGA graphics support"
2294 - depends on (FB = y) && X86
2295 + depends on (FB = y) && X86 && !VGA_NOPROBE
2296 select FB_CFB_FILLRECT
2297 select FB_CFB_COPYAREA
2298 select FB_CFB_IMAGEBLIT
2299 @@ -1028,7 +1028,7 @@ config FB_CARILLO_RANCH
2302 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
2303 - depends on FB && EXPERIMENTAL && PCI && X86
2304 + depends on FB && EXPERIMENTAL && PCI && X86 && !VGA_NOPROBE
2307 select FB_MODE_HELPERS
2308 @@ -1383,7 +1383,7 @@ config FB_SAVAGE_ACCEL
2311 tristate "SiS/XGI display support"
2312 - depends on FB && PCI
2313 + depends on FB && PCI && !VGA_NOPROBE
2314 select FB_CFB_FILLRECT
2315 select FB_CFB_COPYAREA
2316 select FB_CFB_IMAGEBLIT
2317 @@ -1822,6 +1822,15 @@ config FB_PS3_DEFAULT_SIZE_M
2318 The default value can be overridden on the kernel command line
2319 using the "ps3fb" option (e.g. "ps3fb=9M");
2321 +config FB_OLPC_DCON
2322 + tristate "One Laptop Per Child Display CONtroller support"
2326 + Add support for the OLPC DCON controller. This controller is only
2327 + available on OLPC platforms. Unless you have one of these
2328 + platforms, you will want to say 'N'.
2331 tristate "Xilinx frame buffer support"
2332 depends on FB && XILINX_VIRTEX
2333 diff --git a/drivers/video/Makefile b/drivers/video/Makefile
2334 index 06eec7b..fc535fb 100644
2335 --- a/drivers/video/Makefile
2336 +++ b/drivers/video/Makefile
2337 @@ -111,6 +111,7 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
2338 obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
2339 obj-$(CONFIG_FB_PS3) += ps3fb.o
2340 obj-$(CONFIG_FB_SM501) += sm501fb.o
2341 +obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon.o
2342 obj-$(CONFIG_FB_XILINX) += xilinxfb.o
2343 obj-$(CONFIG_FB_OMAP) += omap/
2345 diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
2346 index 0740272..4ac6a95 100644
2347 --- a/drivers/video/fbmem.c
2348 +++ b/drivers/video/fbmem.c
2349 @@ -820,6 +820,53 @@ static void try_to_load(int fb)
2350 #endif /* CONFIG_KMOD */
2353 +fb_powerup(struct fb_info *info)
2357 + if (!info || info->state == FBINFO_STATE_RUNNING)
2360 + if (info->fbops->fb_powerup)
2361 + ret = info->fbops->fb_powerup(info);
2364 + acquire_console_sem();
2365 + fb_set_suspend(info, 0);
2366 + release_console_sem();
2373 +fb_powerdown(struct fb_info *info)
2377 + if (!info || info->state == FBINFO_STATE_SUSPENDED)
2380 + /* Tell everybody that the fbdev is going down */
2381 + acquire_console_sem();
2382 + fb_set_suspend(info, 1);
2383 + release_console_sem();
2385 + if (info->fbops->fb_powerdown)
2386 + ret = info->fbops->fb_powerdown(info);
2388 + /* If the power down failed, then un-notify */
2391 + acquire_console_sem();
2392 + fb_set_suspend(info, 0);
2393 + release_console_sem();
2400 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
2402 struct fb_fix_screeninfo *fix = &info->fix;
2403 diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
2404 index 957304b..5c98da1 100644
2405 --- a/drivers/video/geode/Makefile
2406 +++ b/drivers/video/geode/Makefile
2407 @@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
2408 obj-$(CONFIG_FB_GEODE_LX) += lxfb.o
2410 gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
2411 -gxfb-objs := gxfb_core.o display_gx.o video_gx.o
2412 +gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
2413 lxfb-objs := lxfb_core.o lxfb_ops.o
2414 diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c
2415 index 0f16e4b..a432b99 100644
2416 --- a/drivers/video/geode/display_gx.c
2417 +++ b/drivers/video/geode/display_gx.c
2419 * Free Software Foundation; either version 2 of the License, or * (at your
2420 * option) any later version.
2423 +#include <linux/kernel.h>
2424 #include <linux/spinlock.h>
2425 #include <linux/fb.h>
2426 #include <linux/delay.h>
2428 #include <asm/div64.h>
2429 #include <asm/delay.h>
2430 +#include <asm/olpc.h>
2432 #include "geodefb.h"
2433 #include "display_gx.h"
2435 -#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
2436 -unsigned int gx_frame_buffer_size(void)
2437 +static inline void rmwl(u32 val, u32 *reg)
2439 - return CONFIG_FB_GEODE_GX_FBSIZE;
2440 + u32 in = readl(reg);
2446 unsigned int gx_frame_buffer_size(void)
2451 + if (machine_is_olpc() && !olpc_has_vsa()) {
2453 + rdmsr(GLIU0_P2D_RO0, lo, hi);
2455 + /* Top page number */
2456 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
2458 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
2459 + val += 1; /* Adjust page count */
2460 + return (val << 12);
2464 /* FB size is reported by a virtual register */
2465 /* Virtual register class = 0x02 */
2466 /* VG_MEM_SIZE(512Kb units) = 0x00 */
2467 @@ -41,7 +59,6 @@ unsigned int gx_frame_buffer_size(void)
2468 val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
2473 int gx_line_delta(int xres, int bpp)
2475 @@ -63,23 +80,23 @@ static void gx_set_mode(struct fb_info *info)
2476 gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
2477 dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
2479 - /* Disable the timing generator. */
2480 - dcfg &= ~(DC_DCFG_TGEN);
2481 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2482 + /* Programming the clock is costly and ugly, so avoid if if we can */
2484 - /* Wait for pending memory requests before disabling the FIFO load. */
2486 + if (par->curdclk != info->var.pixclock) {
2487 + /* Disable the timing generator. */
2488 + dcfg &= ~(DC_DCFG_TGEN);
2489 + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2491 - /* Disable FIFO load and compression. */
2492 - gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2493 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2494 + /* Wait for pending memory requests before disabling the FIFO load. */
2497 - /* Setup DCLK and its divisor. */
2498 - par->vid_ops->set_dclk(info);
2499 + /* Disable FIFO load and compression. */
2500 + gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2501 + writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2506 + /* Setup DCLK and its divisor. */
2507 + par->vid_ops->set_dclk(info);
2510 /* Clear all unused feature bits. */
2511 gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
2512 @@ -90,12 +107,13 @@ static void gx_set_mode(struct fb_info *info)
2513 gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
2515 /* Framebuffer start offset. */
2516 - writel(0, par->dc_regs + DC_FB_ST_OFFSET);
2517 + rmwl(0, par->dc_regs + DC_FB_ST_OFFSET);
2519 /* Line delta and line buffer length. */
2520 - writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2521 - writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2522 - par->dc_regs + DC_LINE_SIZE);
2523 + rmwl(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2525 + rmwl(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2526 + par->dc_regs + DC_LINE_SIZE);
2529 /* Enable graphics and video data and unmask address lines. */
2530 @@ -134,17 +152,16 @@ static void gx_set_mode(struct fb_info *info)
2531 vblankend = vsyncend + info->var.upper_margin;
2534 - writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2535 - writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2536 - writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2538 - writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2539 - writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2540 - writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2541 + rmwl((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2542 + rmwl((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2543 + rmwl((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2544 + rmwl((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2545 + rmwl((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2546 + rmwl((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2548 /* Write final register values. */
2549 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2550 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2551 + rmwl(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2552 + rmwl(gcfg, par->dc_regs + DC_GENERAL_CFG);
2554 par->vid_ops->configure_display(info);
2556 diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h
2557 index 0af33f3..d20b877 100644
2558 --- a/drivers/video/geode/display_gx.h
2559 +++ b/drivers/video/geode/display_gx.h
2560 @@ -20,6 +20,9 @@ extern struct geode_dc_ops gx_dc_ops;
2561 #define GLD_MSR_CONFIG 0xC0002001
2562 #define GLD_MSR_CONFIG_DM_FP 0x40
2564 +/* Used for memory dection on the OLPC */
2565 +#define GLIU0_P2D_RO0 0x10000029
2567 /* Display controller registers */
2569 #define DC_UNLOCK 0x00
2570 diff --git a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
2571 index ae04820..0214d11 100644
2572 --- a/drivers/video/geode/geodefb.h
2573 +++ b/drivers/video/geode/geodefb.h
2575 #ifndef __GEODEFB_H__
2576 #define __GEODEFB_H__
2578 +#define FB_POWER_STATE_OFF 0
2579 +#define FB_POWER_STATE_SUSPEND 1
2580 +#define FB_POWER_STATE_ON 2
2582 struct geodefb_info;
2584 struct geode_dc_ops {
2585 @@ -21,18 +25,24 @@ struct geode_dc_ops {
2587 struct geode_vid_ops {
2588 void (*set_dclk)(struct fb_info *);
2589 + unsigned int (*get_dclk)(struct fb_info *);
2590 void (*configure_display)(struct fb_info *);
2591 int (*blank_display)(struct fb_info *, int blank_mode);
2594 struct geodefb_par {
2596 + int fbactive; /* True if the current console is in KD_GRAPHICS mode */
2597 int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
2599 + unsigned int curdclk; /* Used by GX to avoid unnessesary clock switching */
2600 void __iomem *dc_regs;
2601 void __iomem *vid_regs;
2602 + void __iomem *gp_regs;
2603 struct geode_dc_ops *dc_ops;
2604 struct geode_vid_ops *vid_ops;
2609 #endif /* !__GEODEFB_H__ */
2610 diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
2611 index cf841ef..3eabc53 100644
2612 --- a/drivers/video/geode/gxfb_core.c
2613 +++ b/drivers/video/geode/gxfb_core.c
2615 #include <linux/fb.h>
2616 #include <linux/init.h>
2617 #include <linux/pci.h>
2618 +#include <linux/notifier.h>
2619 +#include <linux/vt_kern.h>
2620 +#include <linux/console.h>
2621 +#include <asm/uaccess.h>
2622 +#include <asm/olpc.h>
2624 #include "geodefb.h"
2625 #include "display_gx.h"
2626 #include "video_gx.h"
2628 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
2629 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
2633 +#define FBIODUMPGP _IOW('F', 0x22, void *)
2634 +#define FBIODUMPDC _IOW('F', 0x23, void *)
2635 +#define FBIODUMPVP _IOW('F', 0x24, void *)
2636 +#define FBIODUMPFP _IOW('F', 0x25, void *)
2640 static char *mode_option;
2641 +static int noclear;
2642 +struct fb_info *gxfb_info;
2644 /* Modes relevant to the GX (taken from modedb.c) */
2645 static const struct fb_videomode gx_modedb[] __initdata = {
2646 @@ -103,8 +122,20 @@ static const struct fb_videomode gx_modedb[] __initdata = {
2647 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
2648 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
2649 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
2650 + /* 1200x900-75 - CRT timings for the OLPC mode */
2651 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
2652 + 0, FB_VMODE_NONINTERLACED, 0 }
2656 +static const struct fb_videomode gx_dcon_modedb[] __initdata = {
2657 + /* The only mode the DCON has is 1200x900 */
2658 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
2659 + 0, FB_VMODE_NONINTERLACED, 0 }
2664 static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2666 if (var->xres > 1600 || var->yres > 1200)
2667 @@ -137,7 +168,7 @@ static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2671 -static int gxfb_set_par(struct fb_info *info)
2672 +int gxfb_set_par(struct fb_info *info)
2674 struct geodefb_par *par = info->par;
2676 @@ -204,16 +235,26 @@ static int gxfb_blank(int blank_mode, struct fb_info *info)
2677 return par->vid_ops->blank_display(info, blank_mode);
2682 static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
2684 struct geodefb_par *par = info->par;
2688 ret = pci_enable_device(dev);
2692 + ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
2696 + par->gp_regs = ioremap(pci_resource_start(dev, 1),
2697 + pci_resource_len(dev, 1));
2698 + if (!par->gp_regs)
2701 ret = pci_request_region(dev, 3, "gxfb (video processor)");
2704 @@ -232,36 +273,118 @@ static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *de
2705 ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
2708 - if ((fb_len = gx_frame_buffer_size()) < 0)
2711 + /* If the fbsize wasn't specified then try to probe it */
2714 + fbsize = gx_frame_buffer_size();
2719 info->fix.smem_start = pci_resource_start(dev, 0);
2720 - info->fix.smem_len = fb_len;
2721 + info->fix.smem_len = fbsize;
2722 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2723 if (!info->screen_base)
2726 - /* Set the 16MB aligned base address of the graphics memory region
2727 + /* Set the 16MiB aligned base address of the graphics memory region
2728 * in the display controller */
2730 writel(info->fix.smem_start & 0xFF000000,
2731 par->dc_regs + DC_GLIU0_MEM_OFFSET);
2733 - dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
2734 + dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
2735 info->fix.smem_len / 1024, info->fix.smem_start);
2740 +static int gxfb_ioctl( struct fb_info *info, unsigned int cmd,
2741 + unsigned long arg)
2743 + unsigned int gamma[GXFB_GAMMA_DWORDS];
2744 + int ret = -EINVAL;
2745 + struct geodefb_par *par = info->par;
2750 + /* Read the gamma information from the user - 256 dwords */
2752 + if (copy_from_user(gamma, (void * __user) arg, GXFB_GAMMA_SIZE))
2755 + writel(0, par->vid_regs + GX_GAR);
2757 + /* Sequential writes to the data register will increment the
2758 + address automatically */
2760 + for(i = 0; i < GXFB_GAMMA_DWORDS; i++)
2761 + writel(gamma[i] & 0xFFFFFF, par->vid_regs + GX_GDR);
2763 + writel(readl(par->vid_regs + GX_MISC) & ~GX_MISC_GAM_EN,
2764 + par->vid_regs + GX_MISC);
2770 + if (readl(par->vid_regs + GX_MISC) & GX_MISC_GAM_EN)
2773 + memset(gamma, 0, GXFB_GAMMA_SIZE);
2774 + writel(0, par->vid_regs + GX_GAR);
2776 + for(i = 0; i < GXFB_GAMMA_DWORDS;i++)
2777 + gamma[i] = readl(par->vid_regs + GX_GDR);
2779 + if (copy_to_user((void * __user) arg, gamma, GXFB_GAMMA_SIZE))
2789 + dump_regs(info, 0);
2794 + dump_regs(info, 1);
2799 + dump_regs(info, 2);
2804 + dump_regs(info, 3);
2812 static struct fb_ops gxfb_ops = {
2813 .owner = THIS_MODULE,
2814 .fb_check_var = gxfb_check_var,
2815 .fb_set_par = gxfb_set_par,
2816 .fb_setcolreg = gxfb_setcolreg,
2817 .fb_blank = gxfb_blank,
2818 + .fb_ioctl = gxfb_ioctl,
2819 /* No HW acceleration for now. */
2820 .fb_fillrect = cfb_fillrect,
2821 .fb_copyarea = cfb_copyarea,
2822 .fb_imageblit = cfb_imageblit,
2823 + .fb_powerdown = gxfb_powerdown,
2824 + .fb_powerup = gxfb_powerup,
2827 static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
2828 @@ -303,23 +426,86 @@ static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
2832 -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2833 +static int gxfb_console_notify(struct notifier_block *self,
2834 + unsigned long action, void *data)
2836 + if (gxfb_info != NULL) {
2837 + struct geodefb_par *par = gxfb_info->par;
2838 + par->fbactive = (action == CONSOLE_EVENT_SWITCH_TEXT) ? 0 : 1;
2844 +static struct notifier_block gxfb_console_notifier = {
2845 + .notifier_call = gxfb_console_notify
2850 +static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
2852 + struct fb_info *info = pci_get_drvdata(pdev);
2853 + struct geodefb_par *par = info->par;
2855 + if (pdev->dev.power.power_state.event == state.event)
2858 + if (state.event == PM_EVENT_SUSPEND) {
2860 + acquire_console_sem();
2861 + gxfb_powerdown(info);
2863 + par->state = FB_POWER_STATE_OFF;
2864 + fb_set_suspend(info, 1);
2866 + release_console_sem();
2869 + pdev->dev.power.power_state = state;
2873 +static int gxfb_resume(struct pci_dev *pdev)
2875 + struct fb_info *info = pci_get_drvdata(pdev);
2877 + acquire_console_sem();
2879 + /* Turn the engine completely on */
2881 + if (gxfb_powerup(info))
2882 + printk(KERN_ERR "gxfb: Powerup failed\n");
2884 + fb_set_suspend(info, 0);
2885 + release_console_sem();
2887 + pdev->dev.power.power_state = PMSG_ON;
2892 +static int __init gxfb_probe(struct pci_dev *pdev,
2893 + const struct pci_device_id *id)
2895 struct geodefb_par *par;
2896 - struct fb_info *info;
2900 - info = gxfb_init_fbinfo(&pdev->dev);
2902 + struct fb_videomode *modedb_ptr;
2905 + gxfb_info = gxfb_init_fbinfo(&pdev->dev);
2906 + if (gxfb_info == NULL)
2910 + par = gxfb_info->par;
2912 /* GX display controller and GX video device. */
2913 par->dc_ops = &gx_dc_ops;
2914 par->vid_ops = &gx_vid_ops;
2916 - if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
2917 + if ((ret = gxfb_map_video_memory(gxfb_info, pdev)) < 0) {
2918 dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
2921 @@ -333,32 +519,60 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
2923 par->enable_crt = 1;
2925 - ret = fb_find_mode(&info->var, info, mode_option,
2926 - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
2927 + /* Get the current dotclock */
2929 + par->curdclk = (par->vid_ops->get_dclk) ? par->vid_ops->get_dclk(gxfb_info) : 0;
2931 + /* We need to determine a display mode right now, so we will
2932 + * check to see if the DCON was previously detected by the BIOS
2933 + * and use that to make our mode database decision.
2936 + modedb_ptr = (struct fb_videomode *) gx_modedb;
2937 + modedb_size = ARRAY_SIZE(gx_modedb);
2940 + if (olpc_has_dcon()) {
2941 + modedb_ptr = (struct fb_videomode *) gx_dcon_modedb;
2942 + modedb_size = ARRAY_SIZE(gx_dcon_modedb);
2946 + ret = fb_find_mode(&gxfb_info->var, gxfb_info, mode_option,
2947 + modedb_ptr, modedb_size, NULL, 16);
2949 if (ret == 0 || ret == 4) {
2950 dev_err(&pdev->dev, "could not find valid video mode\n");
2955 + /* Clear the screen of garbage, unless noclear was specified,
2956 + * in which case we assume the user knows what he is doing */
2959 + memset_io(gxfb_info->screen_base, 0, gxfb_info->fix.smem_len);
2961 + gxfb_check_var(&gxfb_info->var, gxfb_info);
2962 + gxfb_set_par(gxfb_info);
2964 + /* We are powered up */
2965 + par->state = FB_POWER_STATE_ON;
2967 - /* Clear the frame buffer of garbage. */
2968 - memset_io(info->screen_base, 0, info->fix.smem_len);
2970 - gxfb_check_var(&info->var, info);
2971 - gxfb_set_par(info);
2972 + console_event_register(&gxfb_console_notifier);
2974 - if (register_framebuffer(info) < 0) {
2975 + if (register_framebuffer(gxfb_info) < 0) {
2979 - pci_set_drvdata(pdev, info);
2980 - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
2981 + pci_set_drvdata(pdev, gxfb_info);
2982 + printk(KERN_INFO "fb%d: %s frame buffer device\n", gxfb_info->node, gxfb_info->fix.id);
2986 - if (info->screen_base) {
2987 - iounmap(info->screen_base);
2988 + if (gxfb_info->screen_base) {
2989 + iounmap(gxfb_info->screen_base);
2990 pci_release_region(pdev, 0);
2992 if (par->vid_regs) {
2993 @@ -370,8 +584,9 @@ static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *i
2994 pci_release_region(pdev, 2);
2998 - framebuffer_release(info);
3000 + framebuffer_release(gxfb_info);
3005 @@ -397,9 +612,7 @@ static void gxfb_remove(struct pci_dev *pdev)
3008 static struct pci_device_id gxfb_id_table[] = {
3009 - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
3010 - PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
3012 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
3016 @@ -410,22 +623,30 @@ static struct pci_driver gxfb_driver = {
3017 .id_table = gxfb_id_table,
3018 .probe = gxfb_probe,
3019 .remove = gxfb_remove,
3021 + .suspend = gxfb_suspend,
3022 + .resume = gxfb_resume
3027 -static int __init gxfb_setup(char *options)
3029 +static int __init gxfb_setup(char *options) {
3033 if (!options || !*options)
3036 - while ((opt = strsep(&options, ",")) != NULL) {
3037 + while((opt = strsep(&options, ",")) != NULL) {
3041 - mode_option = opt;
3042 + if (!strncmp(opt, "fbsize:", 7))
3043 + fbsize = simple_strtoul(opt+7, NULL, 0);
3044 + else if (!strcmp(opt, "noclear"))
3047 + mode_option = opt;
3051 @@ -444,7 +665,6 @@ static int __init gxfb_init(void)
3053 return pci_register_driver(&gxfb_driver);
3056 static void __exit gxfb_cleanup(void)
3058 pci_unregister_driver(&gxfb_driver);
3059 @@ -456,5 +676,8 @@ module_exit(gxfb_cleanup);
3060 module_param(mode_option, charp, 0);
3061 MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
3063 +module_param(fbsize, int, 0);
3064 +MODULE_PARM_DESC(fbsize, "video memory size");
3066 MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
3067 MODULE_LICENSE("GPL");
3068 diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h
3069 index 6c227f9..5be8a4d 100644
3070 --- a/drivers/video/geode/lxfb.h
3071 +++ b/drivers/video/geode/lxfb.h
3072 @@ -25,10 +25,23 @@ void lx_set_mode(struct fb_info *);
3073 void lx_get_gamma(struct fb_info *, unsigned int *, int);
3074 void lx_set_gamma(struct fb_info *, unsigned int *, int);
3075 unsigned int lx_framebuffer_size(void);
3076 +int lx_shutdown(struct fb_info *);
3077 +int lx_powerup(struct fb_info *);
3078 int lx_blank_display(struct fb_info *, int);
3079 void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
3080 unsigned int, unsigned int);
3084 +/* ioctl() defines */
3086 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
3087 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
3089 +/* General definitions */
3090 +#define LXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
3091 +#define LXFB_GAMMA_SIZE (LXFB_GAMMA_DWORDS * sizeof(unsigned int))
3095 #define MSR_LX_GLD_CONFIG 0x48002001
3096 diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c
3097 index 5e30b40..c9060ed 100644
3098 --- a/drivers/video/geode/lxfb_core.c
3099 +++ b/drivers/video/geode/lxfb_core.c
3101 #include <linux/init.h>
3102 #include <linux/pci.h>
3103 #include <linux/uaccess.h>
3104 +#include <asm/olpc.h>
3108 @@ -35,186 +36,84 @@ static int fbsize;
3111 const struct fb_videomode geode_modedb[] __initdata = {
3113 - { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
3114 + /* 640x480-60 VESA */
3115 + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
3116 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3117 + /* 640x480-75 VESA */
3118 + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
3119 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3120 + /* 640x480-85 VESA */
3121 + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
3122 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3123 + /* 800x600-60 VESA */
3124 + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
3125 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3126 - FB_VMODE_NONINTERLACED, 0 },
3128 - { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2,
3129 - FB_SYNC_HOR_HIGH_ACT,
3130 - FB_VMODE_NONINTERLACED, 0 },
3132 - { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3,
3133 - 0, FB_VMODE_NONINTERLACED, 0 },
3135 - { NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3,
3136 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3137 + /* 800x600-75 VESA */
3138 + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
3139 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3140 - FB_VMODE_NONINTERLACED, 0 },
3142 - { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
3143 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3144 + /* 800x600-85 VESA */
3145 + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
3146 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3147 - FB_VMODE_NONINTERLACED, 0 },
3149 - { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
3150 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3151 + /* 1024x768-60 VESA */
3152 + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
3153 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3154 + /* 1024x768-75 VESA */
3155 + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
3156 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3157 - FB_VMODE_NONINTERLACED, 0 },
3159 - { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
3160 - 0, FB_VMODE_NONINTERLACED, 0 },
3162 - { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
3163 - 0, FB_VMODE_NONINTERLACED, 0 },
3165 - { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
3166 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3167 + /* 1024x768-85 VESA */
3168 + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
3169 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3170 - FB_VMODE_NONINTERLACED, 0 },
3172 - { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
3173 - 0, FB_VMODE_NONINTERLACED, 0 },
3175 - { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
3176 - 0, FB_VMODE_NONINTERLACED, 0 },
3178 - { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
3179 - 0, FB_VMODE_NONINTERLACED, 0 },
3181 - { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
3182 - 0, FB_VMODE_NONINTERLACED, 0 },
3184 - { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
3185 - 0, FB_VMODE_NONINTERLACED, 0 },
3187 - { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
3188 - 0, FB_VMODE_NONINTERLACED, 0 },
3190 - { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
3191 - 0, FB_VMODE_NONINTERLACED, 0 },
3193 - { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
3194 - 0, FB_VMODE_NONINTERLACED, 0 },
3196 - { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
3197 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3198 + /* 1280x960-60 VESA */
3199 + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
3200 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3201 - FB_VMODE_NONINTERLACED, 0 },
3203 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3204 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3205 + /* 1280x960-85 VESA */
3206 + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
3207 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3208 - FB_VMODE_NONINTERLACED, 0 },
3210 - { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
3211 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3212 + /* 1280x1024-60 VESA */
3213 + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
3214 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3215 - FB_VMODE_NONINTERLACED, 0 },
3217 - { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
3218 - 0, FB_VMODE_NONINTERLACED, 0 },
3220 - { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
3221 - 0, FB_VMODE_NONINTERLACED, 0 },
3223 - { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
3224 - 0, FB_VMODE_NONINTERLACED, 0 },
3226 - { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
3227 - 0, FB_VMODE_NONINTERLACED, 0 },
3228 - /* 1024x768-100 */
3229 - { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
3230 - 0, FB_VMODE_NONINTERLACED, 0 },
3232 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3233 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3234 + /* 1280x1024-75 VESA */
3235 + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
3236 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3237 - FB_VMODE_NONINTERLACED, 0 },
3239 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3240 - 0, FB_VMODE_NONINTERLACED, 0 },
3242 - { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
3243 - 0, FB_VMODE_NONINTERLACED, 0 },
3245 - { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
3246 - 0, FB_VMODE_NONINTERLACED, 0 },
3248 - { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
3249 - 0, FB_VMODE_NONINTERLACED, 0 },
3251 - { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
3252 - 0, FB_VMODE_NONINTERLACED, 0 },
3254 - { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
3255 - 0, FB_VMODE_NONINTERLACED, 0 },
3256 - /* 1152x864-100 */
3257 - { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
3258 - 0, FB_VMODE_NONINTERLACED, 0 },
3260 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3261 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3262 + /* 1280x1024-85 VESA */
3263 + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
3264 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3265 - FB_VMODE_NONINTERLACED, 0 },
3266 - /* 1280x1024-60 */
3267 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3268 - 0, FB_VMODE_NONINTERLACED, 0 },
3269 - /* 1280x1024-70 */
3270 - { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
3271 - 0, FB_VMODE_NONINTERLACED, 0 },
3272 - /* 1280x1024-72 */
3273 - { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
3274 - 0, FB_VMODE_NONINTERLACED, 0 },
3275 - /* 1280x1024-75 */
3276 - { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
3277 - 0, FB_VMODE_NONINTERLACED, 0 },
3278 - /* 1280x1024-85 */
3279 - { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
3280 - 0, FB_VMODE_NONINTERLACED, 0 },
3281 - /* 1280x1024-90 */
3282 - { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
3283 - 0, FB_VMODE_NONINTERLACED, 0 },
3284 - /* 1280x1024-100 */
3285 - { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
3286 - 0, FB_VMODE_NONINTERLACED, 0 },
3287 - /* 1280x1024-60 */
3288 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3289 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3290 - FB_VMODE_NONINTERLACED, 0 },
3291 - /* 1600x1200-60 */
3292 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3293 + /* 1600x1200-60 VESA */
3294 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3295 - 0, FB_VMODE_NONINTERLACED, 0 },
3296 - /* 1600x1200-70 */
3297 - { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
3298 - 0, FB_VMODE_NONINTERLACED, 0 },
3299 - /* 1600x1200-72 */
3300 - { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
3301 - 0, FB_VMODE_NONINTERLACED, 0 },
3302 - /* 1600x1200-75 */
3303 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3304 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3305 + /* 1600x1200-75 VESA */
3306 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
3307 - 0, FB_VMODE_NONINTERLACED, 0 },
3308 - /* 1600x1200-85 */
3309 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3310 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3311 + /* 1600x1200-85 VESA */
3312 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
3313 - 0, FB_VMODE_NONINTERLACED, 0 },
3314 - /* 1600x1200-90 */
3315 - { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
3316 - 0, FB_VMODE_NONINTERLACED, 0 },
3317 - /* 1600x1200-100 */
3318 - { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
3319 - 0, FB_VMODE_NONINTERLACED, 0 },
3320 - /* 1600x1200-60 */
3321 - { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3322 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3323 - FB_VMODE_NONINTERLACED, 0 },
3324 - /* 1920x1440-60 */
3325 - { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
3326 - 0, FB_VMODE_NONINTERLACED, 0 },
3327 - /* 1920x1440-70 */
3328 - { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
3329 - 0, FB_VMODE_NONINTERLACED, 0 },
3330 - /* 1920x1440-72 */
3331 - { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
3332 - 0, FB_VMODE_NONINTERLACED, 0 },
3333 - /* 1920x1440-75 */
3334 - { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
3335 - 0, FB_VMODE_NONINTERLACED, 0 },
3336 - /* 1920x1440-85 */
3337 - { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
3338 - 0, FB_VMODE_NONINTERLACED, 0 },
3339 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3340 + /* 1200x900-75 - CRT timings for the OLPC mode */
3341 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
3342 + 0, FB_VMODE_NONINTERLACED, 0 }
3346 +const struct fb_videomode olpc_dcon_modedb[] __initdata = {
3347 + /* The only mode the DCON has is 1200x900 */
3348 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
3349 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3350 + FB_VMODE_NONINTERLACED, 0 }
3354 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
3356 if (var->xres > 1920 || var->yres > 1440)
3357 @@ -379,16 +278,55 @@ static int __init lxfb_map_video_memory(struct fb_info *info,
3361 +static int lxfb_set_gamma(struct fb_info *info, void * __user data)
3363 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3365 + if (copy_from_user(gamma, data, LXFB_GAMMA_SIZE))
3368 + lx_set_gamma(info, gamma, LXFB_GAMMA_SIZE);
3372 +static int lxfb_get_gamma(struct fb_info *info, void * __user data)
3374 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3375 + memset(gamma, 0, sizeof(gamma));
3377 + lx_get_gamma(info, gamma, LXFB_GAMMA_DWORDS);
3379 + return copy_to_user(data, gamma, LXFB_GAMMA_SIZE) ?
3383 +static int lxfb_ioctl( struct fb_info *info, unsigned int cmd,
3384 + unsigned long arg)
3388 + return lxfb_set_gamma(info, (void * __user) arg);
3391 + return lxfb_get_gamma(info, (void * __user) arg);
3397 static struct fb_ops lxfb_ops = {
3398 .owner = THIS_MODULE,
3399 .fb_check_var = lxfb_check_var,
3400 .fb_set_par = lxfb_set_par,
3401 .fb_setcolreg = lxfb_setcolreg,
3402 .fb_blank = lxfb_blank,
3403 + .fb_ioctl = lxfb_ioctl,
3404 /* No HW acceleration for now. */
3405 .fb_fillrect = cfb_fillrect,
3406 .fb_copyarea = cfb_copyarea,
3407 .fb_imageblit = cfb_imageblit,
3408 + .fb_powerdown = lx_shutdown,
3409 + .fb_powerup = lx_powerup,
3412 static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
3413 @@ -431,6 +369,45 @@ static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
3419 +static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
3421 + struct fb_info *info = pci_get_drvdata(pdev);
3423 + if (pdev->dev.power.power_state.event == state.event)
3426 + if (state.event == PM_EVENT_SUSPEND) {
3428 + acquire_console_sem();
3429 + lx_shutdown(info);
3430 + fb_set_suspend(info, 1);
3431 + release_console_sem();
3434 + pdev->dev.power.power_state = state;
3438 +static int lxfb_resume(struct pci_dev *pdev)
3440 + struct fb_info *info = pci_get_drvdata(pdev);
3442 + acquire_console_sem();
3444 + /* Turn the engine completely on */
3447 + fb_set_suspend(info, 0);
3448 + release_console_sem();
3450 + pdev->dev.power.power_state = PMSG_ON;
3456 static int __init lxfb_probe(struct pci_dev *pdev,
3457 const struct pci_device_id *id)
3459 @@ -467,6 +444,13 @@ static int __init lxfb_probe(struct pci_dev *pdev,
3460 modedb_ptr = (struct fb_videomode *) geode_modedb;
3461 modedb_size = ARRAY_SIZE(geode_modedb);
3464 + if (olpc_has_dcon()) {
3465 + modedb_ptr = (struct fb_videomode *) olpc_dcon_modedb;
3466 + modedb_size = ARRAY_SIZE(olpc_dcon_modedb);
3470 ret = fb_find_mode(&info->var, info, mode_option,
3471 modedb_ptr, modedb_size, NULL, 16);
3473 @@ -556,6 +540,10 @@ static struct pci_driver lxfb_driver = {
3474 .id_table = lxfb_id_table,
3475 .probe = lxfb_probe,
3476 .remove = lxfb_remove,
3478 + .suspend = lxfb_suspend,
3479 + .resume = lxfb_resume
3484 diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c
3485 index 4fbc99b..47ed9de 100644
3486 --- a/drivers/video/geode/lxfb_ops.c
3487 +++ b/drivers/video/geode/lxfb_ops.c
3489 #include <linux/fb.h>
3490 #include <linux/uaccess.h>
3491 #include <linux/delay.h>
3492 +#include <asm/olpc.h>
3497 +#include "geode_regs.h"
3500 * Support panel scaling
3502 @@ -290,6 +294,19 @@ unsigned int lx_framebuffer_size(void)
3507 + if (machine_is_olpc() && !olpc_has_vsa()) {
3509 + rdmsr(MSR_LX_GLIU0_P2D_RO0, lo, hi);
3511 + /* Top page number */
3512 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
3513 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
3514 + val += 1; /* Adjust page count */
3515 + return (val << 12);
3519 /* The frame buffer size is reported by a VSM in VSA II */
3520 /* Virtual Register Class = 0x02 */
3521 /* VG_MEM_SIZE (1MB units) = 0x00 */
3522 @@ -301,6 +318,34 @@ unsigned int lx_framebuffer_size(void)
3526 +void lx_set_gamma(struct fb_info *info, unsigned int *gamma, int len)
3529 + struct lxfb_par *par = info->par;
3531 + writel(0, par->df_regs + DF_PAR);
3533 + /* Sequential writes to the data register will increment the
3534 + address automatically */
3536 + for(i = 0; i < len; i++)
3537 + writel(gamma[i] & 0xFFFFFF, par->df_regs + DF_PDR);
3539 + writel(readl(par->df_regs + DF_MISC) & ~DF_MISC_GAM_BYPASS,
3540 + par->df_regs + DF_MISC);
3543 +void lx_get_gamma(struct fb_info *info, unsigned int *gamma, int len)
3546 + struct lxfb_par *par = info->par;
3548 + writel(0, par->df_regs + DF_PAR);
3550 + for(i = 0; i < len;i++)
3551 + gamma[i] = readl(par->df_regs + DF_PDR);
3554 void lx_set_mode(struct fb_info *info)
3556 struct lxfb_par *par = info->par;
3557 @@ -313,6 +358,7 @@ void lx_set_mode(struct fb_info *info)
3558 int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
3560 /* Unlock the DC registers */
3561 + readl(par->dc_regs + DC_UNLOCK);
3562 writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3564 lx_graphics_disable(info);
3565 @@ -534,3 +580,285 @@ int lx_blank_display(struct fb_info *info, int blank_mode)
3570 +static struct geoderegs saved_regs;
3572 +static void lx_save_regs(struct fb_info *info, struct geoderegs *regs)
3574 + struct lxfb_par *par = info->par;
3577 + /* Wait for the command buffer to empty */
3578 + while(!(readl(par->gp_regs + 0x44) & (1 << 4)));
3580 + rdmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3581 + rdmsrl(MSR_LX_GLCP_DOTPLL, regs->msr.dotpll);
3582 + rdmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3583 + rdmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3585 + writel(0x4758, par->dc_regs + 0x00);
3587 + memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE);
3588 + memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE);
3589 + memcpy(regs->vp.b, par->df_regs, VP_REG_SIZE);
3590 + memcpy(regs->fp.b, par->df_regs + VP_FP_START, FP_REG_SIZE);
3592 + /* Save the palettes */
3593 + writel(0, par->dc_regs + 0x70);
3595 + for(i = 0; i < DC_PAL_SIZE; i++)
3596 + regs->pal[i] = readl(par->dc_regs + 0x74);
3598 + writel(0, par->df_regs + 0x38);
3600 + for(i = 0; i <= 0xFF; i++)
3601 + regs->gamma[i] = readl(par->df_regs + 0x40);
3604 +static void lx_restore_regs(struct fb_info *info, struct geoderegs *regs)
3606 + struct lxfb_par *par = info->par;
3609 + /* == DOTPLL == */
3611 + lx_set_dotpll((u32) (regs->msr.dotpll >> 32));
3615 + wrmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3619 + writel(regs->gp.r.dst_offset, par->gp_regs + 0x00);
3620 + writel(regs->gp.r.src_offset, par->gp_regs + 0x04);
3621 + writel(regs->gp.r.stride, par->gp_regs + 0x08);
3622 + writel(regs->gp.r.wid_height, par->gp_regs + 0x0C);
3623 + writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10);
3624 + writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14);
3625 + writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18);
3626 + writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C);
3627 + writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20);
3628 + writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24);
3629 + writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28);
3630 + writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C);
3631 + writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30);
3632 + writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34);
3634 + /* Writing to these registers would cause a blt to happen */
3635 + /* 0x38, 0x3c, 0x40 */
3637 + /* Status register (0x44) is read only */
3639 + writel(regs->gp.r.hst_src, par->gp_regs + 0x48);
3640 + writel(regs->gp.r.base_offset, par->gp_regs + 0x4c);
3641 + writel(regs->gp.r.cmd_top, par->gp_regs + 0x50);
3642 + writel(regs->gp.r.cmd_bot, par->gp_regs + 0x54);
3643 + writel(regs->gp.r.cmd_read, par->gp_regs + 0x58);
3644 + writel(regs->gp.r.cmd_write, par->gp_regs + 0x5C);
3645 + writel(regs->gp.r.ch3_offset, par->gp_regs + 0x60);
3646 + writel(regs->gp.r.ch3_mode_str, par->gp_regs + 0x64);
3647 + writel(regs->gp.r.ch3_width, par->gp_regs + 0x6C);
3648 + writel(regs->gp.r.ch3_hsrc, par->gp_regs + 0x70);
3650 + /* FIXME: Restore the LUT data here */
3652 + writel(regs->gp.r.int_cntrl, par->gp_regs + 0x70);
3656 + /* Write the unlock value */
3657 + writel(0x4758, par->dc_regs + 0x00);
3659 + /* Write the palette data first */
3661 + writel(0, par->dc_regs + 0x70);
3663 + for(i = 0; i < DC_PAL_SIZE; i++)
3664 + writel(regs->pal[i], par->dc_regs + 0x74);
3667 + wrmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3669 + /* Write the gcfg register without the enables */
3670 + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
3672 + /* Write the vcfg register without the enables */
3673 + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
3675 + /* Write the rest of the active registers */
3676 + writel(regs->dc.r.arb, par->dc_regs + 0x0C);
3677 + writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10);
3678 + writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14);
3679 + writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18);
3680 + writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C);
3681 + writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20);
3682 + writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24);
3683 + writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28);
3684 + writel(regs->dc.r.dctop, par->dc_regs + 0x2c);
3685 + writel(regs->dc.r.line_size, par->dc_regs + 0x30);
3686 + writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34);
3687 + writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38);
3688 + writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40);
3689 + writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44);
3690 + writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48);
3691 + writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50);
3692 + writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54);
3693 + writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58);
3694 + writel(regs->dc.r.fbactive, par->dc_regs + 0x5c);
3695 + writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60);
3696 + writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64);
3697 + writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68);
3699 + /* Skip register 0x6C (line_cnt), 0x70/0x74 (palette),
3700 + 0x78 (diagnostic), and 0x7c (diagnostic)
3703 + writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80);
3704 + writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84);
3705 + writel(regs->dc.r.dv_ctl, par->dc_regs + 0x88);
3706 + writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C);
3708 + writel(regs->dc.r.gfx_scale, par->dc_regs + 0x90);
3709 + writel(regs->dc.r.irq_filt_ctl, par->dc_regs + 0x94);
3710 + writel(regs->dc.r.filt_coeff1, par->dc_regs + 0x98);
3711 + writel(regs->dc.r.filt_coeff2, par->dc_regs + 0x9C);
3712 + writel(regs->dc.r.vbi_event_ctl, par->dc_regs + 0xA0);
3714 + writel(regs->dc.r.vbi_odd_ctl, par->dc_regs + 0xA4);
3715 + writel(regs->dc.r.vbi_hor, par->dc_regs + 0xA8);
3716 + writel(regs->dc.r.vbi_ln_odd, par->dc_regs + 0xAC);
3717 + writel(regs->dc.r.vbi_ln_event, par->dc_regs + 0xB0);
3718 + writel(regs->dc.r.vbi_pitch, par->dc_regs + 0xB4);
3719 + writel(regs->dc.r.clr_key, par->dc_regs + 0xB8);
3720 + writel(regs->dc.r.clr_key_mask, par->dc_regs + 0xBC);
3722 + writel(regs->dc.r.clr_key_x, par->dc_regs + 0xC0);
3723 + writel(regs->dc.r.clr_key_y, par->dc_regs + 0xC4);
3724 + writel(regs->dc.r.irq, par->dc_regs + 0xC8);
3725 + writel(regs->dc.r.genlk_ctrl, par->dc_regs + 0xD4);
3727 + writel(regs->dc.r.vid_even_y_st_offset, par->dc_regs + 0xD8);
3728 + writel(regs->dc.r.vid_even_u_st_offset, par->dc_regs + 0xDC);
3729 + writel(regs->dc.r.vid_even_v_st_offset, par->dc_regs + 0xE0);
3731 + writel(regs->dc.r.v_active_even_timing, par->dc_regs + 0xE4);
3732 + writel(regs->dc.r.v_blank_even_timing, par->dc_regs + 0xE8);
3733 + writel(regs->dc.r.v_sync_even_timing, par->dc_regs + 0xEC);
3738 + wrmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3740 + /* Write gamma information first */
3742 + writel(0, par->df_regs + 0x38);
3744 + for(i = 0; i <= 0xFF; i++)
3745 + writel((u32) regs->gamma[i], par->df_regs + 0x40);
3747 + /* Don't enable video yet */
3748 + writel((u32) regs->vp.r.vcfg & ~0x01, par->df_regs + 0x00);
3750 + /* Don't enable the CRT yet */
3751 + writel((u32) regs->vp.r.dcfg & ~0x0F, par->df_regs + 0x08);
3753 + /* Write the rest of the VP registers */
3755 + writel((u32) regs->vp.r.vx, par->df_regs + 0x10);
3756 + writel((u32) regs->vp.r.vy, par->df_regs + 0x18);
3757 + writel((u32) regs->vp.r.vs, par->df_regs + 0x20);
3758 + writel((u32) regs->vp.r.vck, par->df_regs + 0x28);
3759 + writel((u32) regs->vp.r.vcm, par->df_regs + 0x30);
3760 + writel((u32) regs->vp.r.misc, par->df_regs + 0x50);
3761 + writel((u32) regs->vp.r.ccs, par->df_regs + 0x58);
3762 + writel((u32) regs->vp.r.vdc, par->df_regs + 0x78);
3763 + writel((u32) regs->vp.r.vco, par->df_regs + 0x80);
3764 + writel((u32) regs->vp.r.crc, par->df_regs + 0x88);
3765 + writel((u32) regs->vp.r.vde, par->df_regs + 0x98);
3766 + writel((u32) regs->vp.r.cck, par->df_regs + 0xA0);
3767 + writel((u32) regs->vp.r.ccm, par->df_regs + 0xA8);
3768 + writel((u32) regs->vp.r.cc1, par->df_regs + 0xB0);
3769 + writel((u32) regs->vp.r.cc2, par->df_regs + 0xB8);
3770 + writel((u32) regs->vp.r.a1x, par->df_regs + 0xC0);
3771 + writel((u32) regs->vp.r.a1y, par->df_regs + 0xC8);
3772 + writel((u32) regs->vp.r.a1c, par->df_regs + 0xD0);
3773 + writel((u32) regs->vp.r.a1t, par->df_regs + 0xD8);
3774 + writel((u32) regs->vp.r.a2x, par->df_regs + 0xE0);
3775 + writel((u32) regs->vp.r.a2y, par->df_regs + 0xE8);
3776 + writel((u32) regs->vp.r.a2c, par->df_regs + 0xF0);
3777 + writel((u32) regs->vp.r.a2t, par->df_regs + 0xF8);
3778 + writel((u32) regs->vp.r.a3x, par->df_regs + 0x100);
3779 + writel((u32) regs->vp.r.a3y, par->df_regs + 0x108);
3780 + writel((u32) regs->vp.r.a3c, par->df_regs + 0x110);
3781 + writel((u32) regs->vp.r.a3t, par->df_regs + 0x118);
3782 + writel((u32) regs->vp.r.vrr, par->df_regs + 0x120);
3784 + writel((u32) regs->vp.r.vye, par->df_regs + 0x138);
3785 + writel((u32) regs->vp.r.a1ye, par->df_regs + 0x140);
3786 + writel((u32) regs->vp.r.a2ye, par->df_regs + 0x148);
3787 + writel((u32) regs->vp.r.a3ye, par->df_regs + 0x150);
3791 + writel((u32) regs->fp.r.pt1, par->df_regs + 0x400);
3792 + writel((u32) regs->fp.r.pt2, par->df_regs + 0x408);
3793 + writel((u32) regs->fp.r.dfc, par->df_regs + 0x418);
3794 + writel(regs->fp.r.dca, par->df_regs + 0x448);
3795 + writel(regs->fp.r.dmd, par->df_regs + 0x450);
3796 + writel(regs->fp.r.crc, par->df_regs + 0x458);
3798 + /* Final enables */
3800 + val = readl(par->df_regs + 0x410);
3802 + /* Control the panel */
3803 + if (regs->fp.r.pm & (1 << 24)) {
3805 + if (!(val & 0x09))
3806 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3809 + if (!(val & 0x05))
3810 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3813 + /* Turn everything on */
3815 + writel(regs->dc.r.gcfg, par->dc_regs + 0x04);
3816 + writel((u32) regs->vp.r.vcfg, par->df_regs + 0x00);
3817 + writel((u32) regs->vp.r.dcfg, par->df_regs + 0x08);
3818 + writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
3821 +static int lx_power_on = 1;
3823 +int lx_shutdown(struct fb_info *info)
3825 + struct lxfb_par *par = info->par;
3827 + if (lx_power_on == 0)
3830 + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3831 + lx_save_regs(info, &saved_regs);
3832 + lx_graphics_disable(info);
3838 +int lx_powerup(struct fb_info *info)
3840 + struct lxfb_par *par = info->par;
3842 + if (lx_power_on == 1)
3845 + lx_restore_regs(info, &saved_regs);
3846 + writel(0, par->dc_regs + DC_UNLOCK);
3851 diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c
3852 index 7f3f18d..e282e74 100644
3853 --- a/drivers/video/geode/video_gx.c
3854 +++ b/drivers/video/geode/video_gx.c
3857 #include <asm/delay.h>
3858 #include <asm/msr.h>
3859 +#include <asm/olpc.h>
3861 #include "geodefb.h"
3862 #include "video_gx.h"
3863 +#include "display_gx.h"
3865 +/* This structure is used to store the saved registers during suspend */
3866 +static struct geoderegs gx_saved_regs;
3869 * Tables of register settings for various DOTCLKs.
3870 @@ -58,7 +62,7 @@ static const struct gx_pll_entry gx_pll_table_48MHz[] = {
3871 { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
3872 { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
3873 { 13333, 0, 0x00000052 }, /* 75.0000 */
3874 - { 12698, 0, 0x00000056 }, /* 78.7500 */
3875 + { 12698, 0, 0x00000056 }, /* 78.7500 */
3876 { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
3877 { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
3878 { 10582, 0, 0x000002D2 }, /* 94.5000 */
3879 @@ -117,8 +121,9 @@ static const struct gx_pll_entry gx_pll_table_14MHz[] = {
3880 { 4357, 0, 0x0000057D }, /* 229.5000 */
3883 -static void gx_set_dclk_frequency(struct fb_info *info)
3884 +void gx_set_dclk_frequency(struct fb_info *info)
3886 + struct geodefb_par *par = info->par;
3887 const struct gx_pll_entry *pll_table;
3890 @@ -173,115 +178,169 @@ static void gx_set_dclk_frequency(struct fb_info *info)
3892 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3893 } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
3895 + par->curdclk = pll_table[best_i].dotpll_value;
3899 -gx_configure_tft(struct fb_info *info)
3900 +/* Find out the current clock - we will use this information to avoid
3901 + re-programming it if we don't need to */
3903 +unsigned int gx_get_dclk(struct fb_info *info)
3905 - struct geodefb_par *par = info->par;
3906 - unsigned long val;
3908 + const struct gx_pll_entry *pll_table;
3909 + int pll_table_len;
3913 - /* Set up the DF pad select MSR */
3914 + if (cpu_data->x86_mask == 1) {
3915 + pll_table = gx_pll_table_14MHz;
3916 + pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
3918 + pll_table = gx_pll_table_48MHz;
3919 + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
3922 - rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3923 - val &= ~GX_VP_PAD_SELECT_MASK;
3924 - val |= GX_VP_PAD_SELECT_TFT;
3925 - wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3926 + rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3928 - /* Turn off the panel */
3929 + for(i = 0; i < pll_table_len; i++) {
3930 + if (pll_table[i].dotpll_value == (u32) (dotpll >> 32))
3934 - fp = readl(par->vid_regs + GX_FP_PM);
3935 - fp &= ~GX_FP_PM_P;
3936 - writel(fp, par->vid_regs + GX_FP_PM);
3937 + return (i == pll_table_len) ? 0 : pll_table[i].pixclock;
3941 +#define CMP(val, mask, res) (((val) & (mask)) == (res))
3943 - /* Set timing 1 */
3945 +gx_configure_tft(struct fb_info *info) {
3947 - fp = readl(par->vid_regs + GX_FP_PT1);
3948 - fp &= GX_FP_PT1_VSIZE_MASK;
3949 - fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
3950 - writel(fp, par->vid_regs + GX_FP_PT1);
3951 + struct geodefb_par *par = info->par;
3952 + u32 val, fp = 0, fp1, fp2, sync = 0;
3955 - /* Set bits that are always on for TFT */
3956 + /* Set up the DF pad select MSR */
3959 + rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3961 - /* Add sync polarity */
3962 + if ((val & GX_VP_PAD_SELECT_MASK) != GX_VP_PAD_SELECT_TFT) {
3963 + val &= ~GX_VP_PAD_SELECT_MASK;
3964 + val |= GX_VP_PAD_SELECT_TFT;
3965 + wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3968 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
3969 - fp |= GX_FP_PT2_VSP;
3970 + sync |= GX_FP_PT2_VSP;
3972 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
3973 - fp |= GX_FP_PT2_HSP;
3974 + sync |= GX_FP_PT2_HSP;
3976 - writel(fp, par->vid_regs + GX_FP_PT2);
3977 + /* We only need to turn off the panel if something changed */
3979 - /* Set the dither control */
3980 - writel(0x70, par->vid_regs + GX_FP_DFC);
3981 + fp1 = readl(par->vid_regs + GX_FP_PT1);
3982 + fp2 = readl(par->vid_regs + GX_FP_PT2);
3984 + if (!CMP(fp1, GX_FP_PT1_VSIZE_MASK, info->var.yres << GX_FP_PT1_VSIZE_SHIFT) ||
3985 + (fp2 != (0x0F100000 | sync))) {
3987 - /* Enable the FP data and power (in case the BIOS didn't) */
3988 + /* Turn off the panel */
3990 - fp = readl(par->vid_regs + GX_DCFG);
3991 - fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
3992 - writel(fp, par->vid_regs + GX_DCFG);
3994 + /* Do we really need to turn off the panel? */
3995 + /* Possibly - we have a glitch somewhere */
3997 - /* Unblank the panel */
3998 + fp = readl(par->vid_regs + GX_FP_PM);
3999 + fp &= ~GX_FP_PM_P;
4000 + writel(fp, par->vid_regs + GX_FP_PM);
4004 + fp1 &= GX_FP_PT1_VSIZE_MASK;
4005 + fp1 |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
4006 + writel(fp, par->vid_regs + GX_FP_PT1);
4009 + writel(0x0F100000 | sync, par->vid_regs + GX_FP_PT2);
4012 + /* Set the dither control */
4013 + if (readl(par->vid_regs + GX_FP_DFC) != 0x70) {
4014 + writel(0x70, par->vid_regs + GX_FP_DFC);
4017 + /* Turn on the panel */
4019 fp = readl(par->vid_regs + GX_FP_PM);
4021 - writel(fp, par->vid_regs + GX_FP_PM);
4024 + writel(fp | GX_FP_PM_P, par->vid_regs + GX_FP_PM);
4027 +#define DCFG_DEFAULT_VAL GX_DCFG_CRT_SYNC_SKW_DFLT | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN | \
4028 +GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN
4030 static void gx_configure_display(struct fb_info *info)
4032 struct geodefb_par *par = info->par;
4034 + u32 dcfg, misc, sync = 0;
4036 /* Set up the MISC register */
4038 misc = readl(par->vid_regs + GX_MISC);
4040 - /* Power up the DAC */
4041 - misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4042 + /* We leave gamma enabled if it was already enabled.
4043 + Although the hardware enables it without setting
4044 + up the gamma table, the BIOS or bootloader ought
4045 + to have either disabled it or loaded a table by now */
4047 - /* Disable gamma correction */
4048 - misc |= GX_MISC_GAM_EN;
4050 - writel(misc, par->vid_regs + GX_MISC);
4052 - /* Write the display configuration */
4053 - dcfg = readl(par->vid_regs + GX_DCFG);
4054 + if (par->enable_crt) {
4055 + /* Power up the CRT DACs */
4056 + if (misc & ( GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN)) {
4057 + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4058 + writel(misc, par->vid_regs + GX_MISC);
4061 - /* Disable hsync and vsync */
4062 - dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4063 - writel(dcfg, par->vid_regs + GX_DCFG);
4064 + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
4065 + sync |= GX_DCFG_CRT_HSYNC_POL;
4067 - /* Clear bits from existing mode. */
4068 - dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4069 - | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4070 - | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4071 + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
4072 + sync |= GX_DCFG_CRT_VSYNC_POL;
4075 + /* Turn off the CRT DACs in FP mode - we don't need them */
4076 + if ((misc & (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN))) {
4077 + misc |= (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4078 + writel(misc, par->vid_regs + GX_MISC);
4082 - /* Set default sync skew. */
4083 - dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4084 + /* Write the display configuration */
4085 + dcfg = readl(par->vid_regs + GX_DCFG);
4087 - /* Enable hsync and vsync. */
4088 - dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4089 + if (!CMP(dcfg, DCFG_DEFAULT_VAL | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL,
4090 + DCFG_DEFAULT_VAL | sync)) {
4092 - /* Sync polarities. */
4093 - if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
4094 - dcfg |= GX_DCFG_CRT_HSYNC_POL;
4095 - if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
4096 - dcfg |= GX_DCFG_CRT_VSYNC_POL;
4097 + /* Disable hsync and vsync */
4098 + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4099 + writel(dcfg, par->vid_regs + GX_DCFG);
4101 - /* Enable the display logic */
4102 - /* Set up the DACS to blank normally */
4103 + /* Clear bits from existing mode. */
4104 + dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4105 + | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4106 + | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4108 - dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4109 + /* Set default sync skew. */
4110 + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4112 - /* Enable the external DAC VREF? */
4113 + /* Enable hsync and vsync. */
4114 + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4116 - writel(dcfg, par->vid_regs + GX_DCFG);
4117 + /* Enable the display logic */
4118 + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4120 + writel(dcfg, par->vid_regs + GX_DCFG);
4123 /* Set up the flat panel (if it is enabled) */
4125 @@ -289,6 +348,100 @@ static void gx_configure_display(struct fb_info *info)
4126 gx_configure_tft(info);
4129 +int gxfb_powerdown(struct fb_info *info)
4131 + struct geodefb_par *par = info->par;
4133 + /* We're already suspended */
4135 + if (par->state != FB_POWER_STATE_ON)
4138 + /* Save the registers */
4139 + gx_save_regs(info, &gx_saved_regs);
4141 + /* Shut down the engine */
4143 + writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + GX_VCFG);
4144 + writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + GX_DCFG);
4146 + /* Turn off the flat panel unless we are attached to a DCON */
4147 + if (!olpc_has_dcon())
4148 + writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, par->vid_regs + GX_FP_PM);
4150 + writel(0x4758, par->dc_regs + DC_UNLOCK);
4152 + writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
4153 + par->dc_regs + DC_GENERAL_CFG);
4155 + writel(gx_saved_regs.dc.r.dcfg & ~0x19,
4156 + par->dc_regs + DC_DISPLAY_CFG);
4158 + par->state = FB_POWER_STATE_SUSPEND;
4163 +int gxfb_powerup(struct fb_info *info)
4165 + struct geodefb_par *par = info->par;
4168 + if (par->state == FB_POWER_STATE_SUSPEND) {
4170 + writel(gx_saved_regs.dc.r.dcfg,
4171 + par->dc_regs + DC_DISPLAY_CFG);
4173 + writel(gx_saved_regs.vp.r.vcfg, par->vid_regs + GX_VCFG);
4174 + writel(gx_saved_regs.vp.r.dcfg, par->vid_regs + GX_DCFG);
4176 + val = readl(par->vid_regs + GX_FP_PM);
4178 + /* power up the panel if it needs it; we don't always power it down */
4179 + if (!(val & 0x09)) {
4180 + writel(gx_saved_regs.fp.r.pm, par->vid_regs + GX_FP_PM);
4185 + /* If the panel is currently on its way up, then wait up to 100ms
4188 + if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
4191 + for(i = 0; i < 10; i++) {
4192 + if (readl(par->vid_regs + GX_FP_PM) & 0x01)
4199 + printk(KERN_ERR "gxfb: Panel power up timed out\n");
4202 + if (par->state == FB_POWER_STATE_ON)
4205 + switch(par->state) {
4206 + case FB_POWER_STATE_OFF:
4207 + gx_restore_regs(info, &gx_saved_regs);
4210 + case FB_POWER_STATE_SUSPEND:
4211 + /* Do this because it will turn on the FIFO which will
4212 + start the line count */
4213 + writel(gx_saved_regs.dc.r.gcfg,
4214 + par->dc_regs + DC_GENERAL_CFG);
4215 + writel(0x0, par->dc_regs + DC_UNLOCK);
4219 + par->state = FB_POWER_STATE_ON;
4223 static int gx_blank_display(struct fb_info *info, int blank_mode)
4225 struct geodefb_par *par = info->par;
4226 @@ -315,6 +468,7 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
4231 dcfg = readl(par->vid_regs + GX_DCFG);
4232 dcfg &= ~(GX_DCFG_DAC_BL_EN
4233 | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
4234 @@ -326,7 +480,7 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
4235 dcfg |= GX_DCFG_VSYNC_EN;
4236 writel(dcfg, par->vid_regs + GX_DCFG);
4238 - /* Power on/off flat panel. */
4239 + /* Power on/off flat panel */
4241 if (par->enable_crt == 0) {
4242 fp_pm = readl(par->vid_regs + GX_FP_PM);
4243 @@ -340,8 +494,37 @@ static int gx_blank_display(struct fb_info *info, int blank_mode)
4247 +extern struct fb_info *gxfb_info;
4249 +/* This function controls the flatpanel power sequencing - this is used
4250 + by the OLPC power management engine to enable the FP sequencing much
4251 + earlier in the resume process
4254 +void gxfb_flatpanel_control(int state)
4256 + struct geodefb_par *par = gxfb_info->par;
4257 + u32 val, fp = readl(par->vid_regs + GX_FP_PM);
4260 + /* Turn on the panel if it isn't aleady */
4263 + if (!(val & 0x01))
4264 + val |= GX_FP_PM_P;
4267 + if (!(val & 0x02))
4268 + val &= ~GX_FP_PM_P;
4272 + writel(val, par->vid_regs + GX_FP_PM);
4275 struct geode_vid_ops gx_vid_ops = {
4276 .set_dclk = gx_set_dclk_frequency,
4277 + .get_dclk = gx_get_dclk,
4278 .configure_display = gx_configure_display,
4279 .blank_display = gx_blank_display,
4281 diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h
4282 index ce28d8f..c57b36b 100644
4283 --- a/drivers/video/geode/video_gx.h
4284 +++ b/drivers/video/geode/video_gx.h
4286 #ifndef __VIDEO_GX_H__
4287 #define __VIDEO_GX_H__
4289 +#include "geode_regs.h"
4291 extern struct geode_vid_ops gx_vid_ops;
4293 /* GX Flatpanel control MSR */
4294 @@ -20,6 +22,8 @@ extern struct geode_vid_ops gx_vid_ops;
4296 /* Geode GX video processor registers */
4298 +#define GX_VCFG 0x0000
4300 #define GX_DCFG 0x0008
4301 # define GX_DCFG_CRT_EN 0x00000001
4302 # define GX_DCFG_HSYNC_EN 0x00000002
4303 @@ -42,6 +46,14 @@ extern struct geode_vid_ops gx_vid_ops;
4304 #define GX_MISC_DAC_PWRDN 0x00000400
4305 #define GX_MISC_A_PWRDN 0x00000800
4307 +/* Gamma correction RAM - address and data registers */
4309 +#define GX_GAR 0x038
4310 +#define GX_GDR 0x040
4312 +#define GXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
4313 +#define GXFB_GAMMA_SIZE (GXFB_GAMMA_DWORDS * sizeof(unsigned int))
4315 /* Geode GX flat panel display control registers */
4317 #define GX_FP_PT1 0x0400
4318 @@ -69,4 +81,13 @@ extern struct geode_vid_ops gx_vid_ops;
4319 # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
4320 # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
4322 +int gxfb_powerdown(struct fb_info *info);
4323 +int gxfb_powerup(struct fb_info *info);
4325 +void gx_set_dclk_frequency(struct fb_info *info);
4326 +unsigned int gx_get_dclk(struct fb_info *info);
4328 +void gx_save_regs(struct fb_info *info, struct geoderegs *regs);
4329 +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs);
4331 #endif /* !__VIDEO_GX_H__ */
4332 diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
4333 index 3741ad7..49f6db5 100644
4334 --- a/drivers/video/modedb.c
4335 +++ b/drivers/video/modedb.c
4336 @@ -33,6 +33,8 @@ const char *global_mode_option;
4337 * Standard video mode definitions (taken from XFree86)
4340 +#define DEFAULT_MODEDB_INDEX 0
4342 static const struct fb_videomode modedb[] = {
4344 /* 640x400 @ 70 Hz, 31.5 kHz hsync */
4345 @@ -504,7 +506,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
4349 - default_mode = &db[0];
4350 + default_mode = (db == modedb) ?
4351 + &modedb[DEFAULT_MODEDB_INDEX] : &db[0];
4355 diff --git a/fs/Kconfig b/fs/Kconfig
4356 index f9eed6d..6fa3ea2 100644
4359 @@ -999,6 +999,23 @@ config HUGETLBFS
4364 + tristate "PromFS IEEE 1275 file system support"
4365 + depends on SPARC || PPC || OLPC
4367 + PromFS is a file system interface to various IEEE-1275 compatible
4368 + firmwares. If you have such a firmware (Sparc64, PowerPC, and
4369 + some other architectures and embedded systems have such firmwares,
4370 + with names like "OpenBoot (tm)" and "OpenFirmware"), say Y here
4371 + to be able to access the firmware's device-tree from Linux.
4373 + The firmware device-tree is available as a virtual file system,
4374 + can be mounted under /prom with the command "mount -t promfs
4377 + To compile PromFS support as a module, choose M here; the module
4378 + will be called promfs. If unsure, choose M.
4383 @@ -1225,6 +1242,14 @@ config JFFS2_FS_WRITEBUFFER
4384 - NOR flash with transparent ECC
4387 +config JFFS2_FS_WBUF_VERIFY
4388 + bool "Verify JFFS2 write-buffer reads"
4389 + depends on JFFS2_FS_WRITEBUFFER
4392 + This causes JFFS2 to read back every page written through the
4393 + write-buffer, and check for errors.
4395 config JFFS2_SUMMARY
4396 bool "JFFS2 summary support (EXPERIMENTAL)"
4397 depends on JFFS2_FS && EXPERIMENTAL
4398 @@ -1295,52 +1320,52 @@ config JFFS2_ZLIB
4403 - Zlib is designed to be a free, general-purpose, legally unencumbered,
4404 - lossless data-compression library for use on virtually any computer
4405 - hardware and operating system. See <http://www.gzip.org/zlib/> for
4406 - further information.
4408 + Zlib is designed to be a free, general-purpose, legally unencumbered,
4409 + lossless data-compression library for use on virtually any computer
4410 + hardware and operating system. See <http://www.gzip.org/zlib/> for
4411 + further information.
4413 - Say 'Y' if unsure.
4414 + Say 'Y' if unsure.
4417 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
4421 - Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4423 + Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4426 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
4430 - RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4432 + RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4435 - prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4436 - default JFFS2_CMODE_PRIORITY
4437 - depends on JFFS2_FS
4439 - You can set here the default compression mode of JFFS2 from
4440 - the available compression modes. Don't touch if unsure.
4441 + prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4442 + default JFFS2_CMODE_PRIORITY
4443 + depends on JFFS2_FS
4445 + You can set here the default compression mode of JFFS2 from
4446 + the available compression modes. Don't touch if unsure.
4448 config JFFS2_CMODE_NONE
4449 - bool "no compression"
4451 - Uses no compression.
4452 + bool "no compression"
4454 + Uses no compression.
4456 config JFFS2_CMODE_PRIORITY
4459 - Tries the compressors in a predefined order and chooses the first
4463 + Tries the compressors in a predefined order and chooses the first
4466 config JFFS2_CMODE_SIZE
4467 - bool "size (EXPERIMENTAL)"
4469 - Tries all compressors and chooses the one which has the smallest
4471 + bool "size (EXPERIMENTAL)"
4473 + Tries all compressors and chooses the one which has the smallest
4478 diff --git a/fs/Makefile b/fs/Makefile
4479 index 720c29d..61f1a4d 100644
4482 @@ -108,6 +108,7 @@ obj-$(CONFIG_ADFS_FS) += adfs/
4483 obj-$(CONFIG_FUSE_FS) += fuse/
4484 obj-$(CONFIG_UDF_FS) += udf/
4485 obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
4486 +obj-$(CONFIG_PROMFS_FS) += promfs/
4487 obj-$(CONFIG_JFS_FS) += jfs/
4488 obj-$(CONFIG_XFS_FS) += xfs/
4489 obj-$(CONFIG_9P_FS) += 9p/
4490 diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
4491 index 504643f..d568ae8 100644
4492 --- a/fs/jffs2/background.c
4493 +++ b/fs/jffs2/background.c
4494 @@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(void *);
4495 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
4497 spin_lock(&c->erase_completion_lock);
4498 - if (c->gc_task && jffs2_thread_should_wake(c))
4499 - send_sig(SIGHUP, c->gc_task, 1);
4500 + if (c->gc_task && jffs2_thread_should_wake(c))
4501 + send_sig(SIGHUP, c->gc_task, 1);
4502 spin_unlock(&c->erase_completion_lock);
4505 diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
4506 index 485d065..d90ca05 100644
4507 --- a/fs/jffs2/compr.c
4508 +++ b/fs/jffs2/compr.c
4510 * Created by Arjan van de Ven <arjanv@redhat.com>
4512 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4513 - * University of Szeged, Hungary
4514 + * University of Szeged, Hungary
4516 * For licensing information, see the file 'LICENCE' in this directory.
4518 @@ -43,121 +43,122 @@ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_co
4519 * *datalen accordingly to show the amount of data which were compressed.
4521 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4522 - unsigned char *data_in, unsigned char **cpage_out,
4523 - uint32_t *datalen, uint32_t *cdatalen)
4524 + unsigned char *data_in, unsigned char **cpage_out,
4525 + uint32_t *datalen, uint32_t *cdatalen)
4527 int ret = JFFS2_COMPR_NONE;
4529 - struct jffs2_compressor *this, *best=NULL;
4530 - unsigned char *output_buf = NULL, *tmp_buf;
4531 - uint32_t orig_slen, orig_dlen;
4532 - uint32_t best_slen=0, best_dlen=0;
4534 + struct jffs2_compressor *this, *best=NULL;
4535 + unsigned char *output_buf = NULL, *tmp_buf;
4536 + uint32_t orig_slen, orig_dlen;
4537 + uint32_t best_slen=0, best_dlen=0;
4539 - switch (jffs2_compression_mode) {
4540 - case JFFS2_COMPR_MODE_NONE:
4542 - case JFFS2_COMPR_MODE_PRIORITY:
4543 - output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4544 - if (!output_buf) {
4545 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4548 - orig_slen = *datalen;
4549 - orig_dlen = *cdatalen;
4550 - spin_lock(&jffs2_compressor_list_lock);
4551 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4552 - /* Skip decompress-only backwards-compatibility and disabled modules */
4553 - if ((!this->compress)||(this->disabled))
4555 + switch (jffs2_compression_mode) {
4556 + case JFFS2_COMPR_MODE_NONE:
4558 + case JFFS2_COMPR_MODE_PRIORITY:
4559 + output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4560 + if (!output_buf) {
4561 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4564 + orig_slen = *datalen;
4565 + orig_dlen = *cdatalen;
4566 + spin_lock(&jffs2_compressor_list_lock);
4567 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4568 + /* Skip decompress-only backwards-compatibility and disabled modules */
4569 + if ((!this->compress)||(this->disabled))
4573 - spin_unlock(&jffs2_compressor_list_lock);
4574 - *datalen = orig_slen;
4575 - *cdatalen = orig_dlen;
4576 - compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4577 - spin_lock(&jffs2_compressor_list_lock);
4580 - ret = this->compr;
4581 - this->stat_compr_blocks++;
4582 - this->stat_compr_orig_size += *datalen;
4583 - this->stat_compr_new_size += *cdatalen;
4587 - spin_unlock(&jffs2_compressor_list_lock);
4588 - if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
4590 - case JFFS2_COMPR_MODE_SIZE:
4591 - orig_slen = *datalen;
4592 - orig_dlen = *cdatalen;
4593 - spin_lock(&jffs2_compressor_list_lock);
4594 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4595 - /* Skip decompress-only backwards-compatibility and disabled modules */
4596 - if ((!this->compress)||(this->disabled))
4598 - /* Allocating memory for output buffer if necessary */
4599 - if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4600 - spin_unlock(&jffs2_compressor_list_lock);
4601 - kfree(this->compr_buf);
4602 - spin_lock(&jffs2_compressor_list_lock);
4603 - this->compr_buf_size=0;
4604 - this->compr_buf=NULL;
4606 - if (!this->compr_buf) {
4607 - spin_unlock(&jffs2_compressor_list_lock);
4608 - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4609 - spin_lock(&jffs2_compressor_list_lock);
4611 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4615 - this->compr_buf = tmp_buf;
4616 - this->compr_buf_size = orig_dlen;
4620 - spin_unlock(&jffs2_compressor_list_lock);
4621 - *datalen = orig_slen;
4622 - *cdatalen = orig_dlen;
4623 - compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4624 - spin_lock(&jffs2_compressor_list_lock);
4627 - if ((!best_dlen)||(best_dlen>*cdatalen)) {
4628 - best_dlen = *cdatalen;
4629 - best_slen = *datalen;
4635 - *cdatalen = best_dlen;
4636 - *datalen = best_slen;
4637 - output_buf = best->compr_buf;
4638 - best->compr_buf = NULL;
4639 - best->compr_buf_size = 0;
4640 - best->stat_compr_blocks++;
4641 - best->stat_compr_orig_size += best_slen;
4642 - best->stat_compr_new_size += best_dlen;
4643 - ret = best->compr;
4645 - spin_unlock(&jffs2_compressor_list_lock);
4648 - printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4651 + spin_unlock(&jffs2_compressor_list_lock);
4652 + *datalen = orig_slen;
4653 + *cdatalen = orig_dlen;
4654 + compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4655 + spin_lock(&jffs2_compressor_list_lock);
4658 + ret = this->compr;
4659 + this->stat_compr_blocks++;
4660 + this->stat_compr_orig_size += *datalen;
4661 + this->stat_compr_new_size += *cdatalen;
4665 + spin_unlock(&jffs2_compressor_list_lock);
4666 + if (ret == JFFS2_COMPR_NONE)
4667 + kfree(output_buf);
4669 + case JFFS2_COMPR_MODE_SIZE:
4670 + orig_slen = *datalen;
4671 + orig_dlen = *cdatalen;
4672 + spin_lock(&jffs2_compressor_list_lock);
4673 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4674 + /* Skip decompress-only backwards-compatibility and disabled modules */
4675 + if ((!this->compress)||(this->disabled))
4677 + /* Allocating memory for output buffer if necessary */
4678 + if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4679 + spin_unlock(&jffs2_compressor_list_lock);
4680 + kfree(this->compr_buf);
4681 + spin_lock(&jffs2_compressor_list_lock);
4682 + this->compr_buf_size=0;
4683 + this->compr_buf=NULL;
4685 + if (!this->compr_buf) {
4686 + spin_unlock(&jffs2_compressor_list_lock);
4687 + tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4688 + spin_lock(&jffs2_compressor_list_lock);
4690 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4694 + this->compr_buf = tmp_buf;
4695 + this->compr_buf_size = orig_dlen;
4699 + spin_unlock(&jffs2_compressor_list_lock);
4700 + *datalen = orig_slen;
4701 + *cdatalen = orig_dlen;
4702 + compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4703 + spin_lock(&jffs2_compressor_list_lock);
4706 + if ((!best_dlen)||(best_dlen>*cdatalen)) {
4707 + best_dlen = *cdatalen;
4708 + best_slen = *datalen;
4714 + *cdatalen = best_dlen;
4715 + *datalen = best_slen;
4716 + output_buf = best->compr_buf;
4717 + best->compr_buf = NULL;
4718 + best->compr_buf_size = 0;
4719 + best->stat_compr_blocks++;
4720 + best->stat_compr_orig_size += best_slen;
4721 + best->stat_compr_new_size += best_dlen;
4722 + ret = best->compr;
4724 + spin_unlock(&jffs2_compressor_list_lock);
4727 + printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4730 - if (ret == JFFS2_COMPR_NONE) {
4731 - *cpage_out = data_in;
4732 - *datalen = *cdatalen;
4733 - none_stat_compr_blocks++;
4734 - none_stat_compr_size += *datalen;
4737 - *cpage_out = output_buf;
4739 + if (ret == JFFS2_COMPR_NONE) {
4740 + *cpage_out = data_in;
4741 + *datalen = *cdatalen;
4742 + none_stat_compr_blocks++;
4743 + none_stat_compr_size += *datalen;
4746 + *cpage_out = output_buf;
4751 @@ -165,8 +166,8 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4752 uint16_t comprtype, unsigned char *cdata_in,
4753 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
4755 - struct jffs2_compressor *this;
4757 + struct jffs2_compressor *this;
4760 /* Older code had a bug where it would write non-zero 'usercompr'
4761 fields. Deal with it. */
4762 @@ -177,32 +178,32 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4763 case JFFS2_COMPR_NONE:
4764 /* This should be special-cased elsewhere, but we might as well deal with it */
4765 memcpy(data_out, cdata_in, datalen);
4766 - none_stat_decompr_blocks++;
4767 + none_stat_decompr_blocks++;
4769 case JFFS2_COMPR_ZERO:
4770 memset(data_out, 0, datalen);
4773 - spin_lock(&jffs2_compressor_list_lock);
4774 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4775 - if (comprtype == this->compr) {
4777 - spin_unlock(&jffs2_compressor_list_lock);
4778 - ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4779 - spin_lock(&jffs2_compressor_list_lock);
4781 - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4784 - this->stat_decompr_blocks++;
4787 - spin_unlock(&jffs2_compressor_list_lock);
4791 + spin_lock(&jffs2_compressor_list_lock);
4792 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4793 + if (comprtype == this->compr) {
4795 + spin_unlock(&jffs2_compressor_list_lock);
4796 + ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4797 + spin_lock(&jffs2_compressor_list_lock);
4799 + printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4802 + this->stat_decompr_blocks++;
4805 + spin_unlock(&jffs2_compressor_list_lock);
4809 printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
4810 - spin_unlock(&jffs2_compressor_list_lock);
4811 + spin_unlock(&jffs2_compressor_list_lock);
4815 @@ -210,108 +211,108 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4817 int jffs2_register_compressor(struct jffs2_compressor *comp)
4819 - struct jffs2_compressor *this;
4820 + struct jffs2_compressor *this;
4822 - if (!comp->name) {
4823 - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4826 - comp->compr_buf_size=0;
4827 - comp->compr_buf=NULL;
4829 - comp->stat_compr_orig_size=0;
4830 - comp->stat_compr_new_size=0;
4831 - comp->stat_compr_blocks=0;
4832 - comp->stat_decompr_blocks=0;
4833 - D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4834 + if (!comp->name) {
4835 + printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4838 + comp->compr_buf_size=0;
4839 + comp->compr_buf=NULL;
4841 + comp->stat_compr_orig_size=0;
4842 + comp->stat_compr_new_size=0;
4843 + comp->stat_compr_blocks=0;
4844 + comp->stat_decompr_blocks=0;
4845 + D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4847 - spin_lock(&jffs2_compressor_list_lock);
4848 + spin_lock(&jffs2_compressor_list_lock);
4850 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4851 - if (this->priority < comp->priority) {
4852 - list_add(&comp->list, this->list.prev);
4856 - list_add_tail(&comp->list, &jffs2_compressor_list);
4857 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4858 + if (this->priority < comp->priority) {
4859 + list_add(&comp->list, this->list.prev);
4863 + list_add_tail(&comp->list, &jffs2_compressor_list);
4865 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4866 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4868 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4869 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4872 - spin_unlock(&jffs2_compressor_list_lock);
4873 + spin_unlock(&jffs2_compressor_list_lock);
4879 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
4881 - D2(struct jffs2_compressor *this;)
4882 + D2(struct jffs2_compressor *this;)
4884 - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4885 + D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4887 - spin_lock(&jffs2_compressor_list_lock);
4888 + spin_lock(&jffs2_compressor_list_lock);
4890 - if (comp->usecount) {
4891 - spin_unlock(&jffs2_compressor_list_lock);
4892 - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4895 - list_del(&comp->list);
4896 + if (comp->usecount) {
4897 + spin_unlock(&jffs2_compressor_list_lock);
4898 + printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4901 + list_del(&comp->list);
4903 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4904 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4906 - spin_unlock(&jffs2_compressor_list_lock);
4908 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4909 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4911 + spin_unlock(&jffs2_compressor_list_lock);
4915 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
4917 - if (orig != comprbuf)
4919 + if (orig != comprbuf)
4923 int __init jffs2_compressors_init(void)
4925 /* Registering compressors */
4926 #ifdef CONFIG_JFFS2_ZLIB
4927 - jffs2_zlib_init();
4928 + jffs2_zlib_init();
4930 #ifdef CONFIG_JFFS2_RTIME
4931 - jffs2_rtime_init();
4932 + jffs2_rtime_init();
4934 #ifdef CONFIG_JFFS2_RUBIN
4935 - jffs2_rubinmips_init();
4936 - jffs2_dynrubin_init();
4937 + jffs2_rubinmips_init();
4938 + jffs2_dynrubin_init();
4940 /* Setting default compression mode */
4941 #ifdef CONFIG_JFFS2_CMODE_NONE
4942 - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4943 - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4944 + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4945 + D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4947 #ifdef CONFIG_JFFS2_CMODE_SIZE
4948 - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4949 - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4950 + jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4951 + D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4953 - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4954 + D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4961 int jffs2_compressors_exit(void)
4963 /* Unregistering compressors */
4964 #ifdef CONFIG_JFFS2_RUBIN
4965 - jffs2_dynrubin_exit();
4966 - jffs2_rubinmips_exit();
4967 + jffs2_dynrubin_exit();
4968 + jffs2_rubinmips_exit();
4970 #ifdef CONFIG_JFFS2_RTIME
4971 - jffs2_rtime_exit();
4972 + jffs2_rtime_exit();
4974 #ifdef CONFIG_JFFS2_ZLIB
4975 - jffs2_zlib_exit();
4976 + jffs2_zlib_exit();
4981 diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
4982 index 68cc701..1070275 100644
4983 --- a/fs/jffs2/compr.h
4984 +++ b/fs/jffs2/compr.h
4986 * JFFS2 -- Journalling Flash File System, Version 2.
4988 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4989 - * University of Szeged, Hungary
4990 + * University of Szeged, Hungary
4992 * For licensing information, see the file 'LICENCE' in this directory.
4995 #define JFFS2_ZLIB_PRIORITY 60
4997 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
4998 -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4999 +#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
5001 #define JFFS2_COMPR_MODE_NONE 0
5002 #define JFFS2_COMPR_MODE_PRIORITY 1
5003 #define JFFS2_COMPR_MODE_SIZE 2
5005 struct jffs2_compressor {
5006 - struct list_head list;
5007 - int priority; /* used by prirority comr. mode */
5009 - char compr; /* JFFS2_COMPR_XXX */
5010 - int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
5011 - uint32_t *srclen, uint32_t *destlen, void *model);
5012 - int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
5013 - uint32_t cdatalen, uint32_t datalen, void *model);
5015 - int disabled; /* if seted the compressor won't compress */
5016 - unsigned char *compr_buf; /* used by size compr. mode */
5017 - uint32_t compr_buf_size; /* used by size compr. mode */
5018 - uint32_t stat_compr_orig_size;
5019 - uint32_t stat_compr_new_size;
5020 - uint32_t stat_compr_blocks;
5021 - uint32_t stat_decompr_blocks;
5022 + struct list_head list;
5023 + int priority; /* used by prirority comr. mode */
5025 + char compr; /* JFFS2_COMPR_XXX */
5026 + int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
5027 + uint32_t *srclen, uint32_t *destlen, void *model);
5028 + int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
5029 + uint32_t cdatalen, uint32_t datalen, void *model);
5031 + int disabled; /* if set the compressor won't compress */
5032 + unsigned char *compr_buf; /* used by size compr. mode */
5033 + uint32_t compr_buf_size; /* used by size compr. mode */
5034 + uint32_t stat_compr_orig_size;
5035 + uint32_t stat_compr_new_size;
5036 + uint32_t stat_compr_blocks;
5037 + uint32_t stat_decompr_blocks;
5040 int jffs2_register_compressor(struct jffs2_compressor *comp);
5041 @@ -64,12 +64,12 @@ int jffs2_compressors_init(void);
5042 int jffs2_compressors_exit(void);
5044 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5045 - unsigned char *data_in, unsigned char **cpage_out,
5046 - uint32_t *datalen, uint32_t *cdatalen);
5047 + unsigned char *data_in, unsigned char **cpage_out,
5048 + uint32_t *datalen, uint32_t *cdatalen);
5050 int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5051 - uint16_t comprtype, unsigned char *cdata_in,
5052 - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5053 + uint16_t comprtype, unsigned char *cdata_in,
5054 + unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5056 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
5058 diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
5059 index 0d0bfd2..546d153 100644
5060 --- a/fs/jffs2/compr_rtime.c
5061 +++ b/fs/jffs2/compr_rtime.c
5062 @@ -104,7 +104,7 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
5070 static struct jffs2_compressor jffs2_rtime_comp = {
5071 diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
5072 index ea0431e..c73fa89 100644
5073 --- a/fs/jffs2/compr_rubin.c
5074 +++ b/fs/jffs2/compr_rubin.c
5075 @@ -384,7 +384,7 @@ static int jffs2_rubinmips_decompress(unsigned char *data_in,
5078 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
5083 static int jffs2_dynrubin_decompress(unsigned char *data_in,
5084 @@ -399,7 +399,7 @@ static int jffs2_dynrubin_decompress(unsigned char *data_in,
5085 bits[c] = data_in[c];
5087 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
5092 static struct jffs2_compressor jffs2_rubinmips_comp = {
5093 diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
5094 index 2b87fcc..cfd301a 100644
5095 --- a/fs/jffs2/compr_zlib.c
5096 +++ b/fs/jffs2/compr_zlib.c
5097 @@ -181,7 +181,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
5099 zlib_inflateEnd(&inf_strm);
5100 mutex_unlock(&inflate_mutex);
5105 static struct jffs2_compressor jffs2_zlib_comp = {
5106 @@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
5108 ret = alloc_workspaces();
5113 ret = jffs2_register_compressor(&jffs2_zlib_comp);
5115 - free_workspaces();
5116 + free_workspaces();
5120 diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
5121 index c1dfca3..d293a1f 100644
5122 --- a/fs/jffs2/dir.c
5123 +++ b/fs/jffs2/dir.c
5124 @@ -32,7 +32,7 @@ static int jffs2_mkdir (struct inode *,struct dentry *,int);
5125 static int jffs2_rmdir (struct inode *,struct dentry *);
5126 static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
5127 static int jffs2_rename (struct inode *, struct dentry *,
5128 - struct inode *, struct dentry *);
5129 + struct inode *, struct dentry *);
5131 const struct file_operations jffs2_dir_operations =
5133 @@ -770,7 +770,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
5136 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
5137 - struct inode *new_dir_i, struct dentry *new_dentry)
5138 + struct inode *new_dir_i, struct dentry *new_dentry)
5141 struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
5142 diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
5143 index 66e7c2f..efd83f3 100644
5144 --- a/fs/jffs2/erase.c
5145 +++ b/fs/jffs2/erase.c
5146 @@ -38,8 +38,8 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
5148 ret = jffs2_flash_erase(c, jeb);
5150 - jffs2_erase_succeeded(c, jeb);
5152 + jffs2_erase_succeeded(c, jeb);
5155 bad_offset = jeb->offset;
5157 @@ -50,12 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
5158 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
5160 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
5161 + down(&c->erase_free_sem);
5162 spin_lock(&c->erase_completion_lock);
5163 list_move(&jeb->list, &c->erase_pending_list);
5164 c->erasing_size -= c->sector_size;
5165 c->dirty_size += c->sector_size;
5166 jeb->dirty_size = c->sector_size;
5167 spin_unlock(&c->erase_completion_lock);
5168 + up(&c->erase_free_sem);
5172 @@ -82,12 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
5173 if (ret == -ENOMEM || ret == -EAGAIN) {
5174 /* Erase failed immediately. Refile it on the list */
5175 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
5176 + down(&c->erase_free_sem);
5177 spin_lock(&c->erase_completion_lock);
5178 list_move(&jeb->list, &c->erase_pending_list);
5179 c->erasing_size -= c->sector_size;
5180 c->dirty_size += c->sector_size;
5181 jeb->dirty_size = c->sector_size;
5182 spin_unlock(&c->erase_completion_lock);
5183 + up(&c->erase_free_sem);
5187 @@ -114,6 +118,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
5188 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
5189 list_del(&jeb->list);
5190 spin_unlock(&c->erase_completion_lock);
5191 + up(&c->erase_free_sem);
5192 jffs2_mark_erased_block(c, jeb);
5195 @@ -134,6 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
5196 jffs2_free_jeb_node_refs(c, jeb);
5197 list_add(&jeb->list, &c->erasing_list);
5198 spin_unlock(&c->erase_completion_lock);
5199 + up(&c->erase_free_sem);
5201 jffs2_erase_block(c, jeb);
5203 @@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count)
5209 + down(&c->erase_free_sem);
5210 spin_lock(&c->erase_completion_lock);
5213 spin_unlock(&c->erase_completion_lock);
5214 + up(&c->erase_free_sem);
5216 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
5218 - up(&c->erase_free_sem);
5221 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
5223 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
5224 + down(&c->erase_free_sem);
5225 spin_lock(&c->erase_completion_lock);
5226 list_move_tail(&jeb->list, &c->erase_complete_list);
5227 spin_unlock(&c->erase_completion_lock);
5228 + up(&c->erase_free_sem);
5229 /* Ensure that kupdated calls us again to mark them clean */
5230 jffs2_erase_pending_trigger(c);
5232 @@ -172,22 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
5233 failed too many times. */
5234 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
5235 /* We'd like to give this block another try. */
5236 + down(&c->erase_free_sem);
5237 spin_lock(&c->erase_completion_lock);
5238 list_move(&jeb->list, &c->erase_pending_list);
5239 c->erasing_size -= c->sector_size;
5240 c->dirty_size += c->sector_size;
5241 jeb->dirty_size = c->sector_size;
5242 spin_unlock(&c->erase_completion_lock);
5243 + up(&c->erase_free_sem);
5248 + down(&c->erase_free_sem);
5249 spin_lock(&c->erase_completion_lock);
5250 c->erasing_size -= c->sector_size;
5251 c->bad_size += c->sector_size;
5252 list_move(&jeb->list, &c->bad_list);
5253 c->nr_erasing_blocks--;
5254 spin_unlock(&c->erase_completion_lock);
5255 + up(&c->erase_free_sem);
5256 wake_up(&c->erase_wait);
5259 @@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
5263 + if (c->mtd->point) {
5264 + unsigned long *wordebuf;
5266 + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
5268 + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
5269 + goto do_flash_read;
5271 + if (retlen < c->sector_size) {
5272 + /* Don't muck about if it won't let us point to the whole erase sector */
5273 + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
5274 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5275 + goto do_flash_read;
5277 + wordebuf = ebuf-sizeof(*wordebuf);
5278 + retlen /= sizeof(*wordebuf);
5280 + if (*++wordebuf != ~0)
5282 + } while(--retlen);
5283 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5285 + printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n",
5286 + *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
5290 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
5292 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
5293 @@ -417,6 +456,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
5294 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
5297 + down(&c->erase_free_sem);
5298 spin_lock(&c->erase_completion_lock);
5299 c->erasing_size -= c->sector_size;
5300 c->free_size += jeb->free_size;
5301 @@ -429,23 +469,28 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb
5302 c->nr_erasing_blocks--;
5303 c->nr_free_blocks++;
5304 spin_unlock(&c->erase_completion_lock);
5305 + up(&c->erase_free_sem);
5306 wake_up(&c->erase_wait);
5310 + down(&c->erase_free_sem);
5311 spin_lock(&c->erase_completion_lock);
5312 /* Stick it on a list (any list) so erase_failed can take it
5313 right off again. Silly, but shouldn't happen often. */
5314 list_add(&jeb->list, &c->erasing_list);
5315 spin_unlock(&c->erase_completion_lock);
5316 + up(&c->erase_free_sem);
5317 jffs2_erase_failed(c, jeb, bad_offset);
5321 /* Stick it back on the list from whence it came and come back later */
5322 jffs2_erase_pending_trigger(c);
5323 + down(&c->erase_free_sem);
5324 spin_lock(&c->erase_completion_lock);
5325 list_add(&jeb->list, &c->erase_complete_list);
5326 spin_unlock(&c->erase_completion_lock);
5327 + up(&c->erase_free_sem);
5330 diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
5331 index 2d99e06..eded819 100644
5334 @@ -556,7 +556,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
5336 node = kmalloc(rawlen, GFP_KERNEL);
5341 ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
5342 if (!ret && retlen != rawlen)
5343 @@ -624,7 +624,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c,
5345 if (ret || (retlen != rawlen)) {
5346 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
5347 - rawlen, phys_ofs, ret, retlen);
5348 + rawlen, phys_ofs, ret, retlen);
5350 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
5352 diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
5353 index b13298a..ae99cd7 100644
5354 --- a/fs/jffs2/jffs2_fs_sb.h
5355 +++ b/fs/jffs2/jffs2_fs_sb.h
5356 @@ -106,6 +106,9 @@ struct jffs2_sb_info {
5358 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
5360 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5361 + unsigned char *wbuf_verify; /* read-back buffer for verification */
5363 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
5364 unsigned char *wbuf; /* Write-behind buffer for NAND flash */
5366 diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
5367 index bc5509f..8b4955a 100644
5368 --- a/fs/jffs2/nodelist.h
5369 +++ b/fs/jffs2/nodelist.h
5370 @@ -127,7 +127,7 @@ static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_nod
5371 return ((struct jffs2_inode_cache *)raw);
5374 - /* flash_offset & 3 always has to be zero, because nodes are
5375 + /* flash_offset & 3 always has to be zero, because nodes are
5376 always aligned at 4 bytes. So we have a couple of extra bits
5377 to play with, which indicate the node's status; see below: */
5378 #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
5379 @@ -197,7 +197,7 @@ struct jffs2_inode_cache {
5380 #define RAWNODE_CLASS_XATTR_DATUM 1
5381 #define RAWNODE_CLASS_XATTR_REF 2
5383 -#define INOCACHE_HASHSIZE 128
5384 +#define INOCACHE_HASHSIZE 1024
5386 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
5388 diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
5389 index dbc908a..5b49bff 100644
5390 --- a/fs/jffs2/nodemgmt.c
5391 +++ b/fs/jffs2/nodemgmt.c
5392 @@ -154,7 +154,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
5393 while(ret == -EAGAIN) {
5394 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
5396 - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5397 + D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5400 spin_unlock(&c->erase_completion_lock);
5401 @@ -423,7 +423,12 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
5402 even after refiling c->nextblock */
5403 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
5404 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
5405 - printk(KERN_WARNING "argh. node added in wrong place\n");
5406 + printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
5408 + printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
5410 + printk(KERN_WARNING "No nextblock");
5411 + printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
5412 return ERR_PTR(-EINVAL);
5415 diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
5416 index b5baa35..8d4319c 100644
5417 --- a/fs/jffs2/readinode.c
5418 +++ b/fs/jffs2/readinode.c
5419 @@ -211,7 +211,7 @@ static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info *
5422 * Returns 0 if the node was handled (including marking it obsolete)
5423 - * < 0 an if error occurred
5424 + * < 0 an if error occurred
5426 static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
5427 struct jffs2_readinode_info *rii,
5428 @@ -862,8 +862,8 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re
5429 JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
5431 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
5432 - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5433 - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5434 + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5435 + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5436 jffs2_mark_node_obsolete(c, ref);
5439 diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
5440 index 6c75cd4..59dd408 100644
5441 --- a/fs/jffs2/scan.c
5442 +++ b/fs/jffs2/scan.c
5443 @@ -863,7 +863,7 @@ scan_more:
5444 switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
5445 case JFFS2_FEATURE_ROCOMPAT:
5446 printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
5447 - c->flags |= JFFS2_SB_FLAG_RO;
5448 + c->flags |= JFFS2_SB_FLAG_RO;
5449 if (!(jffs2_is_readonly(c)))
5451 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
5452 diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
5453 index bc9f6ba..02c39c6 100644
5454 --- a/fs/jffs2/security.c
5455 +++ b/fs/jffs2/security.c
5456 @@ -38,9 +38,9 @@ int jffs2_init_security(struct inode *inode, struct inode *dir)
5458 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
5468 /* ---- XATTR Handler for "security.*" ----------------- */
5469 diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
5470 index d828b29..2a77d3f 100644
5471 --- a/fs/jffs2/summary.c
5472 +++ b/fs/jffs2/summary.c
5474 * JFFS2 -- Journalling Flash File System, Version 2.
5476 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5477 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5478 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5479 - * University of Szeged, Hungary
5480 - * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5481 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5482 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5483 + * University of Szeged, Hungary
5484 + * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5486 * For licensing information, see the file 'LICENCE' in this directory.
5488 diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
5489 index 0c6669e..8bf34f2 100644
5490 --- a/fs/jffs2/summary.h
5491 +++ b/fs/jffs2/summary.h
5493 * JFFS2 -- Journalling Flash File System, Version 2.
5495 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5496 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5497 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5498 - * University of Szeged, Hungary
5499 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5500 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5501 + * University of Szeged, Hungary
5503 * For licensing information, see the file 'LICENCE' in this directory.
5505 diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
5506 index 91d1d0f..d1d4f27 100644
5507 --- a/fs/jffs2/wbuf.c
5508 +++ b/fs/jffs2/wbuf.c
5509 @@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
5513 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5514 +static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
5521 + ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
5522 + if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
5523 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
5525 + } else if (retlen != c->wbuf_pagesize) {
5526 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
5529 + if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
5532 + if (ret == -EUCLEAN)
5533 + eccstr = "corrected";
5534 + else if (ret == -EBADMSG)
5535 + eccstr = "correction failed";
5537 + eccstr = "OK or unused";
5539 + printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
5540 + eccstr, c->wbuf_ofs);
5541 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5542 + c->wbuf, c->wbuf_pagesize, 0);
5544 + printk(KERN_WARNING "Read back:\n");
5545 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5546 + c->wbuf_verify, c->wbuf_pagesize, 0);
5551 +#define jffs2_verify_write(c,b,o) (0)
5554 /* Recover from failure to write wbuf. Recover the nodes up to the
5555 * wbuf, not the one which we were starting to try to write. */
5557 @@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
5558 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
5561 - if (ret || retlen != towrite) {
5562 + if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
5563 /* Argh. We tried. Really we did. */
5564 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
5566 @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
5568 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
5570 - if (ret || retlen != c->wbuf_pagesize) {
5572 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
5574 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5575 - retlen, c->wbuf_pagesize);
5580 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
5582 + } else if (retlen != c->wbuf_pagesize) {
5583 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5584 + retlen, c->wbuf_pagesize);
5587 + } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
5589 jffs2_wbuf_recover(c);
5592 @@ -966,8 +1008,8 @@ exit:
5594 #define NR_OOB_SCAN_PAGES 4
5596 -/* For historical reasons we use only 12 bytes for OOB clean marker */
5597 -#define OOB_CM_SIZE 12
5598 +/* For historical reasons we use only 8 bytes for OOB clean marker */
5599 +#define OOB_CM_SIZE 8
5601 static const struct jffs2_unknown_node oob_cleanmarker =
5603 @@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c,
5605 * Check for a valid cleanmarker.
5606 * Returns: 0 if a valid cleanmarker was found
5607 - * 1 if no cleanmarker was found
5608 - * negative error code if an error occurred
5609 + * 1 if no cleanmarker was found
5610 + * negative error code if an error occurred
5612 int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
5613 struct jffs2_eraseblock *jeb)
5614 @@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
5618 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5619 + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
5620 + if (!c->wbuf_verify) {
5629 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
5631 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5632 + kfree(c->wbuf_verify);
5637 diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
5638 index 3b0ff29..6e3b5dd 100644
5639 --- a/fs/jffs2/xattr.h
5640 +++ b/fs/jffs2/xattr.h
5641 @@ -75,7 +75,7 @@ extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
5642 extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
5644 extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
5645 - uint32_t xid, uint32_t version);
5646 + uint32_t xid, uint32_t version);
5648 extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5649 extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5650 diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
5651 index 40942bc..8bbeab9 100644
5652 --- a/fs/jffs2/xattr_user.c
5653 +++ b/fs/jffs2/xattr_user.c
5655 #include "nodelist.h"
5657 static int jffs2_user_getxattr(struct inode *inode, const char *name,
5658 - void *buffer, size_t size)
5659 + void *buffer, size_t size)
5661 if (!strcmp(name, ""))
5663 @@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct inode *inode, const char *name,
5666 static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
5667 - size_t size, int flags)
5668 + size_t size, int flags)
5670 if (!strcmp(name, ""))
5672 diff --git a/include/asm-i386/geode.h b/include/asm-i386/geode.h
5673 index 6da4bbb..f18ebe2 100644
5674 --- a/include/asm-i386/geode.h
5675 +++ b/include/asm-i386/geode.h
5676 @@ -135,6 +135,55 @@ static inline void geode_gpio_event_pme(unsigned int gpio, int pair)
5677 geode_gpio_setup_event(gpio, pair, 1);
5682 +#define MFGPT_TIMER_ANY -1
5684 +#define MFGPT_DOMAIN_WORKING 1
5685 +#define MFGPT_DOMAIN_STANDBY 2
5686 +#define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY)
5688 +#define MFGPT_CMP1 0
5689 +#define MFGPT_CMP2 1
5691 +#define MFGPT_EVENT_IRQ 0
5692 +#define MFGPT_EVENT_NMI 1
5693 +#define MFGPT_EVENT_RESET 3
5695 +#define MFGPT_REG_CMP1 0
5696 +#define MFGPT_REG_CMP2 2
5697 +#define MFGPT_REG_COUNTER 4
5698 +#define MFGPT_REG_SETUP 6
5700 +#define MFGPT_SETUP_CNTEN (1 << 15)
5701 +#define MFGPT_SETUP_CMP2 (1 << 14)
5702 +#define MFGPT_SETUP_CMP1 (1 << 13)
5703 +#define MFGPT_SETUP_SETUP (1 << 12)
5704 +#define MFGPT_SETUP_STOPEN (1 << 11)
5705 +#define MFGPT_SETUP_EXTEN (1 << 10)
5706 +#define MFGPT_SETUP_REVEN (1 << 5)
5707 +#define MFGPT_SETUP_CLKSEL (1 << 4)
5709 +static inline void geode_mfgpt_write(int timer, u16 reg, u16 value)
5711 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5712 + outw(value, base + reg + (timer * 8));
5715 +static inline u16 geode_mfgpt_read(int timer, u16 reg)
5717 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5718 + return inw(base + reg + (timer * 8));
5721 +extern int __init geode_mfgpt_detect(void);
5722 +extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable);
5723 +extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable);
5724 +extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner);
5726 +#define geode_mfgpt_setup_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),1)
5727 +#define geode_mfgpt_release_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),0)
5729 /* Specific geode tests */
5731 static inline int is_geode_gx(void)
5733 diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
5734 index 7862fe8..d7146c0 100644
5735 --- a/include/asm-i386/setup.h
5736 +++ b/include/asm-i386/setup.h
5738 #define OLD_CL_BASE_ADDR 0x90000
5739 #define OLD_CL_OFFSET 0x90022
5740 #define NEW_CL_POINTER 0x228 /* Relative to real mode data */
5741 +#define OFW_INFO_OFFSET 0xb0 /* Relative to real mode data */
5743 #ifndef __ASSEMBLY__
5745 diff --git a/include/linux/console.h b/include/linux/console.h
5746 index 56a7bcd..1a8b034 100644
5747 --- a/include/linux/console.h
5748 +++ b/include/linux/console.h
5749 @@ -121,14 +121,11 @@ extern void console_stop(struct console *);
5750 extern void console_start(struct console *);
5751 extern int is_console_locked(void);
5753 -#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
5754 +extern int serial_console_suspend_enabled;
5756 /* Suspend and resume console messages over PM events */
5757 extern void suspend_console(void);
5758 extern void resume_console(void);
5760 -static inline void suspend_console(void) {}
5761 -static inline void resume_console(void) {}
5762 -#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
5764 int mda_console_init(void);
5765 void prom_con_init(void);
5766 diff --git a/include/linux/fb.h b/include/linux/fb.h
5767 index cec5410..6b59db5 100644
5768 --- a/include/linux/fb.h
5769 +++ b/include/linux/fb.h
5770 @@ -664,6 +664,12 @@ struct fb_ops {
5771 /* restore saved state */
5772 void (*fb_restore_state)(struct fb_info *info);
5774 + /* Shut down the graphics engine to save power */
5775 + int (*fb_powerdown)(struct fb_info *info);
5777 + /* Power it back up */
5778 + int (*fb_powerup)(struct fb_info *info);
5780 /* get capability given var */
5781 void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
5782 struct fb_var_screeninfo *var);
5783 @@ -943,6 +949,9 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var,
5784 extern int fb_get_options(char *name, char **option);
5785 extern int fb_new_modelist(struct fb_info *info);
5787 +extern int fb_powerdown(struct fb_info *info);
5788 +extern int fb_powerup(struct fb_info *info);
5790 extern struct fb_info *registered_fb[FB_MAX];
5791 extern int num_registered_fb;
5792 extern struct class *fb_class;
5793 diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
5794 index a56d24a..fd0a260 100644
5795 --- a/include/linux/mtd/onenand.h
5796 +++ b/include/linux/mtd/onenand.h
5797 @@ -60,6 +60,7 @@ struct onenand_bufferram {
5798 * @erase_shift: [INTERN] number of address bits in a block
5799 * @page_shift: [INTERN] number of address bits in a page
5800 * @page_mask: [INTERN] a page per block mask
5801 + * @writesize: [INTERN] a real page size
5802 * @bufferram_index: [INTERN] BufferRAM index
5803 * @bufferram: [INTERN] BufferRAM info
5804 * @readw: [REPLACEABLE] hardware specific function for read short
5805 @@ -100,6 +101,7 @@ struct onenand_chip {
5806 unsigned int erase_shift;
5807 unsigned int page_shift;
5808 unsigned int page_mask;
5809 + unsigned int writesize;
5811 unsigned int bufferram_index;
5812 struct onenand_bufferram bufferram[MAX_BUFFERRAM];
5813 @@ -140,6 +142,8 @@ struct onenand_chip {
5814 #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
5815 #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
5816 #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
5817 +#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
5818 +#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
5820 #define ONENAND_GET_SYS_CFG1(this) \
5821 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
5822 @@ -149,6 +153,13 @@ struct onenand_chip {
5823 #define ONENAND_IS_DDP(this) \
5824 (this->device_id & ONENAND_DEVICE_IS_DDP)
5826 +#ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
5827 +#define ONENAND_IS_2PLANE(this) \
5828 + (this->options & ONENAND_HAS_2PLANE)
5830 +#define ONENAND_IS_2PLANE(this) (0)
5833 /* Check byte access in OneNAND */
5834 #define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
5836 @@ -157,6 +168,7 @@ struct onenand_chip {
5838 #define ONENAND_HAS_CONT_LOCK (0x0001)
5839 #define ONENAND_HAS_UNLOCK_ALL (0x0002)
5840 +#define ONENAND_HAS_2PLANE (0x0004)
5841 #define ONENAND_PAGEBUF_ALLOC (0x1000)
5842 #define ONENAND_OOBBUF_ALLOC (0x2000)
5844 diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
5845 index af94719..c46161f 100644
5846 --- a/include/linux/mtd/onenand_regs.h
5847 +++ b/include/linux/mtd/onenand_regs.h
5850 #define ONENAND_DEVICE_DENSITY_512Mb (0x002)
5851 #define ONENAND_DEVICE_DENSITY_1Gb (0x003)
5852 +#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
5853 +#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
5856 * Version ID Register F002h (R)
5858 #define ONENAND_CMD_READOOB (0x13)
5859 #define ONENAND_CMD_PROG (0x80)
5860 #define ONENAND_CMD_PROGOOB (0x1A)
5861 +#define ONENAND_CMD_2X_PROG (0x7D)
5862 +#define ONENAND_CMD_2X_CACHE_PROG (0x7F)
5863 #define ONENAND_CMD_UNLOCK (0x23)
5864 #define ONENAND_CMD_LOCK (0x2A)
5865 #define ONENAND_CMD_LOCK_TIGHT (0x2C)
5866 diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
5867 index 699b7e9..b44facf 100644
5868 --- a/include/linux/vt_kern.h
5869 +++ b/include/linux/vt_kern.h
5870 @@ -95,4 +95,23 @@ struct vt_spawn_console {
5872 extern struct vt_spawn_console vt_spawn_con;
5874 +/* A notifier list for console events */
5875 +extern struct raw_notifier_head console_notifier_list;
5877 +/* Called when the FG console switches to KD_TEXT mode */
5878 +#define CONSOLE_EVENT_SWITCH_TEXT 0x01
5880 +/* Called when the FG console switches to KD_GRAPHICS mode */
5881 +#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
5883 +static inline int console_event_register(struct notifier_block *n)
5885 + return raw_notifier_chain_register(&console_notifier_list, n);
5888 +static inline int console_event_unregister(struct notifier_block *n)
5890 + return raw_notifier_chain_unregister(&console_notifier_list, n);
5893 #endif /* _VT_KERN_H */
5894 diff --git a/kernel/power/console.c b/kernel/power/console.c
5895 index 89bcf49..dca98f5 100644
5896 --- a/kernel/power/console.c
5897 +++ b/kernel/power/console.c
5899 #include <linux/console.h>
5902 -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
5903 +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) && !defined(CONFIG_DISABLE_SUSPEND_VT_SWITCH)
5904 #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
5906 static int orig_fgconsole, orig_kmsg;