1 Index: linux-2.6.23.17/arch/i386/Kconfig
2 ===================================================================
3 --- linux-2.6.23.17.orig/arch/i386/Kconfig
4 +++ linux-2.6.23.17/arch/i386/Kconfig
5 @@ -796,6 +796,15 @@ config SECCOMP
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 Index: linux-2.6.23.17/arch/i386/kernel/Makefile
97 ===================================================================
98 --- linux-2.6.23.17.orig/arch/i386/kernel/Makefile
99 +++ linux-2.6.23.17/arch/i386/kernel/Makefile
100 @@ -39,13 +39,17 @@ obj-$(CONFIG_VM86) += vm86.o
101 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
102 obj-$(CONFIG_HPET_TIMER) += hpet.o
103 obj-$(CONFIG_K8_NB) += k8.o
104 -obj-$(CONFIG_MGEODE_LX) += geode.o
105 +obj-$(CONFIG_MGEODE_LX) += geode.o mfgpt.o
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 Index: linux-2.6.23.17/arch/i386/kernel/geode.c
120 ===================================================================
121 --- linux-2.6.23.17.orig/arch/i386/kernel/geode.c
122 +++ linux-2.6.23.17/arch/i386/kernel/geode.c
123 @@ -145,10 +145,14 @@ EXPORT_SYMBOL_GPL(geode_gpio_setup_event
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 Index: linux-2.6.23.17/arch/i386/kernel/head.S
139 ===================================================================
140 --- linux-2.6.23.17.orig/arch/i386/kernel/head.S
141 +++ linux-2.6.23.17/arch/i386/kernel/head.S
142 @@ -117,8 +117,34 @@ ENTRY(startup_32)
143 movl $(COMMAND_LINE_SIZE/4),%ecx
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
185 Index: linux-2.6.23.17/arch/i386/kernel/setup.c
186 ===================================================================
187 --- linux-2.6.23.17.orig/arch/i386/kernel/setup.c
188 +++ linux-2.6.23.17/arch/i386/kernel/setup.c
189 @@ -362,8 +362,10 @@ void __init zone_sizes_init(void)
191 unsigned long max_zone_pfns[MAX_NR_ZONES];
192 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
193 +#ifdef CONFIG_ZONE_DMA
194 max_zone_pfns[ZONE_DMA] =
195 virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
197 max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
198 #ifdef CONFIG_HIGHMEM
199 max_zone_pfns[ZONE_HIGHMEM] = highend_pfn;
200 @@ -428,6 +430,9 @@ void __init setup_bootmem_allocator(void
202 acpi_reserve_bootmem();
204 +#ifdef CONFIG_OLPC_PM
205 + reserve_bootmem(0xf0000, PAGE_SIZE);
207 #ifdef CONFIG_X86_FIND_SMP_CONFIG
209 * Find and reserve possible boot-time SMP configuration:
210 Index: linux-2.6.23.17/arch/i386/pci/Makefile
211 ===================================================================
212 --- linux-2.6.23.17.orig/arch/i386/pci/Makefile
213 +++ linux-2.6.23.17/arch/i386/pci/Makefile
214 @@ -3,6 +3,7 @@ obj-y := i386.o init.o
215 obj-$(CONFIG_PCI_BIOS) += pcbios.o
216 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o mmconfig-shared.o
217 obj-$(CONFIG_PCI_DIRECT) += direct.o
218 +obj-$(CONFIG_PCI_OLPC) += olpc.o
221 pci-$(CONFIG_ACPI) += acpi.o
222 Index: linux-2.6.23.17/arch/i386/pci/init.c
223 ===================================================================
224 --- linux-2.6.23.17.orig/arch/i386/pci/init.c
225 +++ linux-2.6.23.17/arch/i386/pci/init.c
226 @@ -14,6 +14,9 @@ static __init int pci_access_init(void)
227 #ifdef CONFIG_PCI_MMCONFIG
228 pci_mmcfg_init(type);
230 +#ifdef CONFIG_PCI_OLPC
235 #ifdef CONFIG_PCI_BIOS
236 Index: linux-2.6.23.17/arch/i386/pci/pci.h
237 ===================================================================
238 --- linux-2.6.23.17.orig/arch/i386/pci/pci.h
239 +++ linux-2.6.23.17/arch/i386/pci/pci.h
240 @@ -93,6 +93,7 @@ extern void pci_direct_init(int type);
241 extern void pci_pcbios_init(void);
242 extern void pci_mmcfg_init(int type);
243 extern void pcibios_sort(void);
244 +extern void pci_olpc_init(void);
248 Index: linux-2.6.23.17/drivers/Makefile
249 ===================================================================
250 --- linux-2.6.23.17.orig/drivers/Makefile
251 +++ linux-2.6.23.17/drivers/Makefile
252 @@ -23,6 +23,8 @@ obj-y += char/
254 obj-$(CONFIG_CONNECTOR) += connector/
256 +obj-$(CONFIG_SYSPROF) += sysprof/
258 # i810fb and intelfb depend on char/agp/
259 obj-$(CONFIG_FB_I810) += video/i810/
260 obj-$(CONFIG_FB_INTEL) += video/intelfb/
261 Index: linux-2.6.23.17/drivers/char/vt_ioctl.c
262 ===================================================================
263 --- linux-2.6.23.17.orig/drivers/char/vt_ioctl.c
264 +++ linux-2.6.23.17/drivers/char/vt_ioctl.c
267 extern struct tty_driver *console_driver;
269 +/* Add a notifier chain to inform drivers of a VT_TEXT/VT_GRAPHICS switch */
270 +RAW_NOTIFIER_HEAD(console_notifier_list);
272 #define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
273 #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
275 @@ -491,6 +494,14 @@ int vt_ioctl(struct tty_struct *tty, str
276 vc->vc_mode = (unsigned char) arg;
277 if (console != fg_console)
280 + /* Notify listeners if the current fg_console has switched */
282 + raw_notifier_call_chain(&console_notifier_list,
284 + CONSOLE_EVENT_SWITCH_TEXT :
285 + CONSOLE_EVENT_SWITCH_GRAPHICS, 0);
288 * explicitly blank/unblank the screen if switching modes
290 Index: linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
291 ===================================================================
292 --- linux-2.6.23.17.orig/drivers/i2c/busses/scx200_acb.c
293 +++ linux-2.6.23.17/drivers/i2c/busses/scx200_acb.c
294 @@ -46,6 +46,10 @@ static int base[MAX_DEVICES] = { 0x820,
295 module_param_array(base, int, NULL, 0);
296 MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
298 +static unsigned int smbclk = 0x70;
299 +module_param(smbclk, uint, 0);
300 +MODULE_PARM_DESC(smbclk, "Specify the SMB_CLK value");
302 #define POLL_TIMEOUT (HZ/5)
304 enum scx200_acb_state {
305 @@ -108,6 +112,7 @@ struct scx200_acb_iface {
306 #define ACBADDR (iface->base + 4)
307 #define ACBCTL2 (iface->base + 5)
308 #define ACBCTL2_ENABLE 0x01
309 +#define ACBCTL3 (iface->base + 6)
311 /************************************************************************/
313 @@ -392,11 +397,13 @@ static __init int scx200_acb_probe(struc
317 - /* Disable the ACCESS.bus device and Configure the SCL
318 - frequency: 16 clock cycles */
319 - outb(0x70, ACBCTL2);
320 + /* Disable the ACCESS.bus device and Configure the SCL */
322 + outb((smbclk & 0x7F) << 1, ACBCTL2);
324 + outb((smbclk >> 7) & 0xFF, ACBCTL3);
326 - if (inb(ACBCTL2) != 0x70) {
327 + if (inb(ACBCTL2) != ((smbclk & 0x7F) << 1)) {
328 pr_debug(NAME ": ACBCTL2 readback failed\n");
331 Index: linux-2.6.23.17/drivers/input/keyboard/atkbd.c
332 ===================================================================
333 --- linux-2.6.23.17.orig/drivers/input/keyboard/atkbd.c
334 +++ linux-2.6.23.17/drivers/input/keyboard/atkbd.c
335 @@ -63,12 +63,25 @@ static int atkbd_extra;
336 module_param_named(extra, atkbd_extra, bool, 0);
337 MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
339 +#define ATKBD_KEY_UNKNOWN 0
340 +#define ATKBD_KEY_NULL 0xFF0000FF
342 +#define ATKBD_SCR_1 0xFF0000FE
343 +#define ATKBD_SCR_2 0xFF0000FD
344 +#define ATKBD_SCR_4 0xFF0000FC
345 +#define ATKBD_SCR_8 0xFF0000FB
346 +#define ATKBD_SCR_CLICK 0xFF0000FA
347 +#define ATKBD_SCR_LEFT 0xFF0000F9
348 +#define ATKBD_SCR_RIGHT 0xFF0000F8
350 +#define ATKBD_SPECIAL 0xFF0000F8
353 * Scancode to keycode tables. These are just the default setting, and
354 * are loadable via an userland utility.
357 -static unsigned char atkbd_set2_keycode[512] = {
358 +static unsigned int atkbd_set2_keycode[512] = {
360 #ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
362 @@ -87,11 +100,17 @@ static unsigned char atkbd_set2_keycode[
363 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
366 - 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
368 + 217,100,ATKBD_KEY_NULL, 0, 97,165, 0, 0,
369 + 156, 0, 0, 0, 0, 0, 0,125,
371 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
372 159, 0,115, 0,164, 0, 0,116,158, 0,172,166, 0, 0, 0,142,
373 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
374 - 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
376 + 226, 0, 0, 0, 0, 0, 0, 0,
377 + 0,ATKBD_KEY_NULL, 96, 0, 0, 0,143, 0,
379 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
380 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
382 @@ -150,19 +169,6 @@ static unsigned char atkbd_unxlate_table
383 #define ATKBD_RET_HANGEUL 0xf2
384 #define ATKBD_RET_ERR 0xff
386 -#define ATKBD_KEY_UNKNOWN 0
387 -#define ATKBD_KEY_NULL 255
389 -#define ATKBD_SCR_1 254
390 -#define ATKBD_SCR_2 253
391 -#define ATKBD_SCR_4 252
392 -#define ATKBD_SCR_8 251
393 -#define ATKBD_SCR_CLICK 250
394 -#define ATKBD_SCR_LEFT 249
395 -#define ATKBD_SCR_RIGHT 248
397 -#define ATKBD_SPECIAL 248
399 #define ATKBD_LED_EVENT_BIT 0
400 #define ATKBD_REP_EVENT_BIT 1
402 @@ -174,7 +180,7 @@ static unsigned char atkbd_unxlate_table
403 #define ATKBD_XL_HANJA 0x20
406 - unsigned char keycode;
407 + unsigned int keycode;
409 } atkbd_scroll_keys[] = {
410 { ATKBD_SCR_1, 0xc5 },
411 @@ -200,7 +206,7 @@ struct atkbd {
415 - unsigned char keycode[512];
416 + unsigned int keycode[512];
418 unsigned char translated;
420 @@ -351,7 +357,7 @@ static irqreturn_t atkbd_interrupt(struc
421 unsigned int code = data;
422 int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
424 - unsigned char keycode;
425 + unsigned int keycode;
428 printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
429 @@ -856,9 +862,11 @@ static void atkbd_set_keycode_table(stru
430 atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
432 } else if (atkbd->set == 3) {
433 - memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
434 + for (i = 0; i < ARRAY_SIZE(atkbd_set3_keycode); i++)
435 + atkbd->keycode[i] = atkbd_set3_keycode[i];
437 - memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
438 + for (i = 0; i < ARRAY_SIZE(atkbd_set2_keycode); i++)
439 + atkbd->keycode[i] = atkbd_set2_keycode[i];
442 for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
443 @@ -925,8 +933,8 @@ static void atkbd_set_device_attrs(struc
446 input_dev->keycode = atkbd->keycode;
447 - input_dev->keycodesize = sizeof(unsigned char);
448 - input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
449 + input_dev->keycodesize = sizeof(unsigned int);
450 + input_dev->keycodemax = ARRAY_SIZE(atkbd->keycode);
452 for (i = 0; i < 512; i++)
453 if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
454 @@ -1017,6 +1025,10 @@ static int atkbd_connect(struct serio *s
459 +#include <asm/olpc.h>
463 * atkbd_reconnect() tries to restore keyboard into a sane state and is
464 * most likely called on resume.
465 @@ -1027,6 +1039,12 @@ static int atkbd_reconnect(struct serio
466 struct atkbd *atkbd = serio_get_drvdata(serio);
467 struct serio_driver *drv = serio->drv;
470 + if (olpc_rev_after(OLPC_REV_B2))
471 + if (serio->dev.power.power_state.event != PM_EVENT_ON)
475 if (!atkbd || !drv) {
476 printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
478 Index: linux-2.6.23.17/drivers/input/mouse/Kconfig
479 ===================================================================
480 --- linux-2.6.23.17.orig/drivers/input/mouse/Kconfig
481 +++ linux-2.6.23.17/drivers/input/mouse/Kconfig
482 @@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
486 +config MOUSE_PS2_OLPC
487 + bool "OLPC PS/2 mouse protocol extension" if EMBEDDED
489 + depends on MOUSE_PS2 && OLPC
491 + Say Y here if you have an OLPC PS/2 touchpad connected to
497 tristate "Serial mouse"
499 Index: linux-2.6.23.17/drivers/input/mouse/Makefile
500 ===================================================================
501 --- linux-2.6.23.17.orig/drivers/input/mouse/Makefile
502 +++ linux-2.6.23.17/drivers/input/mouse/Makefile
503 @@ -24,3 +24,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) +=
504 psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
505 psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
506 psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
507 +psmouse-$(CONFIG_MOUSE_PS2_OLPC) += olpc.o
508 Index: linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
509 ===================================================================
510 --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse-base.c
511 +++ linux-2.6.23.17/drivers/input/mouse/psmouse-base.c
513 #include "synaptics.h"
514 #include "logips2pp.h"
517 #include "lifebook.h"
518 #include "trackpoint.h"
519 #include "touchkit_ps2.h"
520 @@ -103,7 +104,7 @@ static struct attribute_group psmouse_at
522 static DEFINE_MUTEX(psmouse_mutex);
524 -static struct workqueue_struct *kpsmoused_wq;
525 +struct workqueue_struct *kpsmoused_wq;
527 struct psmouse_protocol {
528 enum psmouse_type type;
529 @@ -320,7 +321,7 @@ static irqreturn_t psmouse_interrupt(str
533 - if (psmouse->packet[1] == PSMOUSE_RET_ID) {
534 + if (psmouse->packet[1] == PSMOUSE_RET_ID || psmouse->packet[1] == PSMOUSE_RET_BAT) {
535 __psmouse_set_state(psmouse, PSMOUSE_IGNORE);
536 serio_reconnect(serio);
538 @@ -631,8 +632,21 @@ static int psmouse_extensions(struct psm
543 + * Try OLPC touchpad.
545 if (max_proto > PSMOUSE_IMEX) {
546 + if (olpc_detect(psmouse, set_properties) == 0) {
547 + if (!set_properties || olpc_init(psmouse) == 0)
548 + return PSMOUSE_OLPC;
550 + * Init failed, try basic relative protocols
552 + max_proto = PSMOUSE_IMEX;
556 + if (max_proto > PSMOUSE_IMEX) {
557 if (genius_detect(psmouse, set_properties) == 0)
558 return PSMOUSE_GENPS;
560 @@ -762,6 +776,14 @@ static const struct psmouse_protocol psm
561 .detect = touchkit_ps2_detect,
564 +#ifdef CONFIG_MOUSE_PS2_OLPC
566 + .type = PSMOUSE_OLPC,
569 + .detect = olpc_detect,
573 .type = PSMOUSE_CORTRON,
574 .name = "CortronPS/2",
575 Index: linux-2.6.23.17/drivers/input/mouse/psmouse.h
576 ===================================================================
577 --- linux-2.6.23.17.orig/drivers/input/mouse/psmouse.h
578 +++ linux-2.6.23.17/drivers/input/mouse/psmouse.h
579 @@ -89,6 +89,7 @@ enum psmouse_type {
581 PSMOUSE_TOUCHKIT_PS2,
584 PSMOUSE_AUTO /* This one should always be last */
587 @@ -96,6 +97,7 @@ int psmouse_sliced_command(struct psmous
588 int psmouse_reset(struct psmouse *psmouse);
589 void psmouse_set_resolution(struct psmouse *psmouse, unsigned int resolution);
591 +extern struct workqueue_struct *kpsmoused_wq;
593 struct psmouse_attribute {
594 struct device_attribute dattr;
595 Index: linux-2.6.23.17/drivers/input/serio/i8042.c
596 ===================================================================
597 --- linux-2.6.23.17.orig/drivers/input/serio/i8042.c
598 +++ linux-2.6.23.17/drivers/input/serio/i8042.c
599 @@ -868,6 +868,11 @@ static long i8042_panic_blink(long count
605 +#include <asm/olpc.h>
609 * Here we try to restore the original BIOS settings. We only want to
610 * do that once, when we really suspend, not when we taking memory
611 @@ -878,8 +883,15 @@ static long i8042_panic_blink(long count
612 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
614 if (dev->dev.power.power_state.event != state.event) {
616 + /* Anything newer than B2 remains powered; no reset needed */
617 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
619 if (state.event == PM_EVENT_SUSPEND)
620 i8042_controller_reset();
625 dev->dev.power.power_state = state;
627 @@ -902,9 +914,15 @@ static int i8042_resume(struct platform_
628 if (dev->dev.power.power_state.event == PM_EVENT_ON)
632 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
634 error = i8042_controller_check();
641 error = i8042_controller_selftest();
643 Index: linux-2.6.23.17/drivers/input/serio/serio.c
644 ===================================================================
645 --- linux-2.6.23.17.orig/drivers/input/serio/serio.c
646 +++ linux-2.6.23.17/drivers/input/serio/serio.c
647 @@ -916,11 +916,22 @@ static int serio_uevent(struct device *d
648 #endif /* CONFIG_HOTPLUG */
653 +#include <asm/olpc.h>
656 static int serio_suspend(struct device *dev, pm_message_t state)
658 if (dev->power.power_state.event != state.event) {
660 + if (olpc_rev_before(OLPC_REV_PRE_B3)) {
662 if (state.event == PM_EVENT_SUSPEND)
663 serio_cleanup(to_serio_port(dev));
668 dev->power.power_state = state;
670 Index: linux-2.6.23.17/drivers/media/video/cafe_ccic.c
671 ===================================================================
672 --- linux-2.6.23.17.orig/drivers/media/video/cafe_ccic.c
673 +++ linux-2.6.23.17/drivers/media/video/cafe_ccic.c
674 @@ -63,13 +63,13 @@ MODULE_SUPPORTED_DEVICE("Video");
677 #define MAX_DMA_BUFS 3
678 -static int alloc_bufs_at_load = 0;
679 -module_param(alloc_bufs_at_load, bool, 0444);
680 -MODULE_PARM_DESC(alloc_bufs_at_load,
681 - "Non-zero value causes DMA buffers to be allocated at module "
682 - "load time. This increases the chances of successfully getting "
683 - "those buffers, but at the cost of nailing down the memory from "
685 +static int alloc_bufs_at_read = 0;
686 +module_param(alloc_bufs_at_read, bool, 0444);
687 +MODULE_PARM_DESC(alloc_bufs_at_read,
688 + "Non-zero value causes DMA buffers to be allocated when the "
689 + "video capture device is read, rather than at module load "
690 + "time. This saves memory, but decreases the chances of "
691 + "successfully getting those buffers.");
693 static int n_dma_bufs = 3;
694 module_param(n_dma_bufs, uint, 0644);
695 @@ -370,6 +370,10 @@ static int cafe_smbus_write_data(struct
696 rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR);
697 cafe_reg_write(cam, REG_TWSIC1, rval);
698 spin_unlock_irqrestore(&cam->dev_lock, flags);
699 + mdelay(2); /* It'll probably take about 900µs anyway, and the
700 + CAFÉ is apparently quite sensitive to being poked
701 + at this point. If we can work out precisely what's
702 + going on and reduce this delay, it would be nice. */
705 * Time to wait for the write to complete. THIS IS A RACY
706 @@ -1503,7 +1507,7 @@ static int cafe_v4l_release(struct inode
708 if (cam->users == 0) {
709 cafe_ctlr_power_down(cam);
710 - if (! alloc_bufs_at_load)
711 + if (alloc_bufs_at_read)
712 cafe_free_dma_bufs(cam);
714 mutex_unlock(&cam->s_mutex);
715 @@ -2162,7 +2166,7 @@ static int cafe_pci_probe(struct pci_dev
717 * If so requested, try to get our DMA buffers now.
719 - if (alloc_bufs_at_load) {
720 + if (!alloc_bufs_at_read) {
721 if (cafe_alloc_dma_bufs(cam, 1))
722 cam_warn(cam, "Unable to alloc DMA buffers at load"
723 " will try again later.");
724 Index: linux-2.6.23.17/drivers/misc/Kconfig
725 ===================================================================
726 --- linux-2.6.23.17.orig/drivers/misc/Kconfig
727 +++ linux-2.6.23.17/drivers/misc/Kconfig
728 @@ -202,5 +202,10 @@ config THINKPAD_ACPI_BAY
730 If you are not sure, say Y here.
733 + tristate "EEPROM 93CX6 support"
735 + This is a driver for the EEPROM chipsets 93c46 and 93c66.
736 + The driver supports both read as well as write commands.
739 Index: linux-2.6.23.17/drivers/mmc/host/sdhci.c
740 ===================================================================
741 --- linux-2.6.23.17.orig/drivers/mmc/host/sdhci.c
742 +++ linux-2.6.23.17/drivers/mmc/host/sdhci.c
743 @@ -411,6 +411,12 @@ static void sdhci_prepare_data(struct sd
748 + * There's an off-by-one error in the hw that we need to
754 printk(KERN_WARNING "%s: Too large timeout requested!\n",
755 mmc_hostname(host->mmc));
756 @@ -676,19 +682,17 @@ static void sdhci_set_power(struct sdhci
757 if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
758 writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
760 - pwr = SDHCI_POWER_ON;
762 switch (1 << power) {
763 case MMC_VDD_165_195:
764 - pwr |= SDHCI_POWER_180;
765 + pwr = SDHCI_POWER_180;
769 - pwr |= SDHCI_POWER_300;
770 + pwr = SDHCI_POWER_300;
774 - pwr |= SDHCI_POWER_330;
775 + pwr = SDHCI_POWER_330;
779 @@ -696,6 +700,10 @@ static void sdhci_set_power(struct sdhci
781 writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
783 + pwr |= SDHCI_POWER_ON;
785 + writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL);
790 Index: linux-2.6.23.17/drivers/mtd/Kconfig
791 ===================================================================
792 --- linux-2.6.23.17.orig/drivers/mtd/Kconfig
793 +++ linux-2.6.23.17/drivers/mtd/Kconfig
794 @@ -288,6 +288,14 @@ config SSFDC
795 This enables read only access to SmartMedia formatted NAND
796 flash. You can mount it with FAT file system.
799 + tristate "Log panic/oops to an MTD buffer"
802 + This enables panic and oops messages to be logged to a circular
803 + buffer in a flash partition where it can be read back at some
806 source "drivers/mtd/chips/Kconfig"
808 source "drivers/mtd/maps/Kconfig"
809 Index: linux-2.6.23.17/drivers/mtd/Makefile
810 ===================================================================
811 --- linux-2.6.23.17.orig/drivers/mtd/Makefile
812 +++ linux-2.6.23.17/drivers/mtd/Makefile
813 @@ -22,6 +22,7 @@ obj-$(CONFIG_NFTL) += nftl.o
814 obj-$(CONFIG_INFTL) += inftl.o
815 obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
816 obj-$(CONFIG_SSFDC) += ssfdc.o
817 +obj-$(CONFIG_MTD_OOPS) += mtdoops.o
819 nftl-objs := nftlcore.o nftlmount.o
820 inftl-objs := inftlcore.o inftlmount.o
821 Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
822 ===================================================================
823 --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0001.c
824 +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0001.c
825 @@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(
826 struct cfi_pri_intelext *extp = cfi->cmdset_priv;
829 - * Probing of multi-partition flash ships.
830 + * Probing of multi-partition flash chips.
832 * To support multiple partitions when available, we simply arrange
833 * for each of them to have their own flchip structure even if they
834 @@ -1781,7 +1781,7 @@ static int __xipram do_erase_oneblock(st
838 -int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
839 +static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
841 unsigned long ofs, len;
843 @@ -1931,7 +1931,7 @@ static int cfi_intelext_lock(struct mtd_
844 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
845 __FUNCTION__, ofs, len);
846 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
851 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
852 @@ -1941,7 +1941,7 @@ static int cfi_intelext_lock(struct mtd_
853 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
855 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
861 @@ -1955,7 +1955,7 @@ static int cfi_intelext_unlock(struct mt
862 printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
863 __FUNCTION__, ofs, len);
864 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
869 ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
870 @@ -1965,7 +1965,7 @@ static int cfi_intelext_unlock(struct mt
871 printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
873 cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
879 @@ -2256,7 +2256,7 @@ static void cfi_intelext_save_locks(stru
880 adr = region->offset + block * len;
882 status = cfi_varsize_frob(mtd,
883 - do_getlockstatus_oneblock, adr, len, 0);
884 + do_getlockstatus_oneblock, adr, len, NULL);
886 set_bit(block, region->lockmap);
888 Index: linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
889 ===================================================================
890 --- linux-2.6.23.17.orig/drivers/mtd/chips/cfi_cmdset_0002.c
891 +++ linux-2.6.23.17/drivers/mtd/chips/cfi_cmdset_0002.c
892 @@ -1617,7 +1617,7 @@ static int __xipram do_erase_oneblock(st
896 -int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
897 +static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
899 unsigned long ofs, len;
901 Index: linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
902 ===================================================================
903 --- linux-2.6.23.17.orig/drivers/mtd/chips/jedec_probe.c
904 +++ linux-2.6.23.17/drivers/mtd/chips/jedec_probe.c
908 #define MBM29F040C 0x00A4
909 +#define MBM29F800BA 0x2258
910 #define MBM29LV650UE 0x22D7
911 #define MBM29LV320TE 0x22F6
912 #define MBM29LV320BE 0x22F9
914 #define LH28F640BF 0x00b0
916 /* ST - www.st.com */
917 +#define M29F800AB 0x0058
918 #define M29W800DT 0x00D7
919 #define M29W800DB 0x005B
920 #define M29W160DT 0x22C4
921 @@ -646,6 +648,23 @@ static const struct amd_flash_info jedec
924 .mfr_id = MANUFACTURER_FUJITSU,
925 + .dev_id = MBM29F800BA,
926 + .name = "Fujitsu MBM29F800BA",
928 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
929 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
931 + .DevSize = SIZE_1MiB,
932 + .CmdSet = P_ID_AMD_STD,
933 + .NumEraseRegions= 4,
935 + ERASEINFO(0x04000,1),
936 + ERASEINFO(0x02000,2),
937 + ERASEINFO(0x08000,1),
938 + ERASEINFO(0x10000,15),
941 + .mfr_id = MANUFACTURER_FUJITSU,
942 .dev_id = MBM29LV650UE,
943 .name = "Fujitsu MBM29LV650UE",
945 @@ -1510,6 +1529,23 @@ static const struct amd_flash_info jedec
946 ERASEINFO(0x1000,256)
950 + .mfr_id = MANUFACTURER_ST,
951 + .dev_id = M29F800AB,
952 + .name = "ST M29F800AB",
954 + [0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
955 + [1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
957 + .DevSize = SIZE_1MiB,
958 + .CmdSet = P_ID_AMD_STD,
959 + .NumEraseRegions= 4,
961 + ERASEINFO(0x04000,1),
962 + ERASEINFO(0x02000,2),
963 + ERASEINFO(0x08000,1),
964 + ERASEINFO(0x10000,15),
967 .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
969 Index: linux-2.6.23.17/drivers/mtd/devices/Kconfig
970 ===================================================================
971 --- linux-2.6.23.17.orig/drivers/mtd/devices/Kconfig
972 +++ linux-2.6.23.17/drivers/mtd/devices/Kconfig
973 @@ -69,12 +69,21 @@ config MTD_DATAFLASH26
974 If you have such a board and such a DataFlash, say 'Y'.
977 - tristate "Support for M25 SPI Flash"
978 + tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
979 depends on SPI_MASTER && EXPERIMENTAL
981 - This enables access to ST M25P80 and similar SPI flash chips,
982 - used for program and data storage. Set up your spi devices
983 - with the right board-specific platform data.
984 + This enables access to most modern SPI flash chips, used for
985 + program and data storage. Series supported include Atmel AT26DF,
986 + Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
987 + are supported as well. See the driver source for the current list,
988 + or to add other chips.
990 + Note that the original DataFlash chips (AT45 series, not AT26DF),
991 + need an entirely different driver.
993 + Set up your spi devices with the right board-specific platform data,
994 + if you want to specify device partitioning or to use a device which
995 + doesn't support the JEDEC ID instruction.
998 tristate "Uncached system RAM"
999 Index: linux-2.6.23.17/drivers/mtd/devices/m25p80.c
1000 ===================================================================
1001 --- linux-2.6.23.17.orig/drivers/mtd/devices/m25p80.c
1002 +++ linux-2.6.23.17/drivers/mtd/devices/m25p80.c
1005 - * MTD SPI driver for ST M25Pxx flash chips
1006 + * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
1008 * Author: Mike Lavender, mike@steroidmicros.com
1011 #include <linux/module.h>
1012 #include <linux/device.h>
1013 #include <linux/interrupt.h>
1014 -#include <linux/interrupt.h>
1015 +#include <linux/mutex.h>
1017 #include <linux/mtd/mtd.h>
1018 #include <linux/mtd/partitions.h>
1020 #include <linux/spi/spi.h>
1021 #include <linux/spi/flash.h>
1023 -#include <asm/semaphore.h>
1026 -/* NOTE: AT 25F and SST 25LF series are very similar,
1027 - * but commands for sector erase and chip id differ...
1030 #define FLASH_PAGESIZE 256
1032 /* Flash opcodes. */
1033 -#define OPCODE_WREN 6 /* Write enable */
1034 -#define OPCODE_RDSR 5 /* Read status register */
1035 -#define OPCODE_READ 3 /* Read data bytes */
1036 -#define OPCODE_PP 2 /* Page program */
1037 -#define OPCODE_SE 0xd8 /* Sector erase */
1038 -#define OPCODE_RES 0xab /* Read Electronic Signature */
1039 +#define OPCODE_WREN 0x06 /* Write enable */
1040 +#define OPCODE_RDSR 0x05 /* Read status register */
1041 +#define OPCODE_READ 0x03 /* Read data bytes (low frequency) */
1042 +#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
1043 +#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
1044 +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
1045 +#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
1046 +#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
1047 #define OPCODE_RDID 0x9f /* Read JEDEC ID */
1049 /* Status Register bits. */
1050 #define SR_WIP 1 /* Write in progress */
1051 #define SR_WEL 2 /* Write enable latch */
1052 +/* meaning of other SR_* bits may differ between vendors */
1053 #define SR_BP0 4 /* Block protect 0 */
1054 #define SR_BP1 8 /* Block protect 1 */
1055 #define SR_BP2 0x10 /* Block protect 2 */
1059 struct spi_device *spi;
1060 - struct semaphore lock;
1061 + struct mutex lock;
1062 struct mtd_info mtd;
1063 - unsigned partitioned;
1064 + unsigned partitioned:1;
1069 @@ -150,8 +150,9 @@ static int wait_till_ready(struct m25p *
1071 static int erase_sector(struct m25p *flash, u32 offset)
1073 - DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
1074 - __FUNCTION__, offset);
1075 + DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
1076 + flash->spi->dev.bus_id, __FUNCTION__,
1077 + flash->mtd.erasesize / 1024, offset);
1079 /* Wait until finished previous write command. */
1080 if (wait_till_ready(flash))
1081 @@ -161,7 +162,7 @@ static int erase_sector(struct m25p *fla
1082 write_enable(flash);
1084 /* Set up command buffer. */
1085 - flash->command[0] = OPCODE_SE;
1086 + flash->command[0] = flash->erase_opcode;
1087 flash->command[1] = offset >> 16;
1088 flash->command[2] = offset >> 8;
1089 flash->command[3] = offset;
1090 @@ -201,13 +202,17 @@ static int m25p80_erase(struct mtd_info
1094 - down(&flash->lock);
1095 + mutex_lock(&flash->lock);
1097 + /* REVISIT in some cases we could speed up erasing large regions
1098 + * by using OPCODE_SE instead of OPCODE_BE_4K
1101 /* now erase those sectors */
1103 if (erase_sector(flash, addr)) {
1104 instr->state = MTD_ERASE_FAILED;
1106 + mutex_unlock(&flash->lock);
1110 @@ -215,7 +220,7 @@ static int m25p80_erase(struct mtd_info
1111 len -= mtd->erasesize;
1115 + mutex_unlock(&flash->lock);
1117 instr->state = MTD_ERASE_DONE;
1118 mtd_erase_callback(instr);
1119 @@ -260,16 +265,19 @@ static int m25p80_read(struct mtd_info *
1123 - down(&flash->lock);
1124 + mutex_lock(&flash->lock);
1126 /* Wait till previous write/erase is done. */
1127 if (wait_till_ready(flash)) {
1128 /* REVISIT status return?? */
1130 + mutex_unlock(&flash->lock);
1134 - /* NOTE: OPCODE_FAST_READ (if available) is faster... */
1135 + /* FIXME switch to OPCODE_FAST_READ. It's required for higher
1136 + * clocks; and at this writing, every chip this driver handles
1137 + * supports that opcode.
1140 /* Set up the write data buffer. */
1141 flash->command[0] = OPCODE_READ;
1142 @@ -281,7 +289,7 @@ static int m25p80_read(struct mtd_info *
1144 *retlen = m.actual_length - sizeof(flash->command);
1147 + mutex_unlock(&flash->lock);
1151 @@ -323,7 +331,7 @@ static int m25p80_write(struct mtd_info
1153 spi_message_add_tail(&t[1], &m);
1155 - down(&flash->lock);
1156 + mutex_lock(&flash->lock);
1158 /* Wait until finished previous write command. */
1159 if (wait_till_ready(flash))
1160 @@ -381,10 +389,10 @@ static int m25p80_write(struct mtd_info
1162 *retlen += m.actual_length
1163 - sizeof(flash->command);
1170 + mutex_unlock(&flash->lock);
1174 @@ -398,24 +406,118 @@ static int m25p80_write(struct mtd_info
1181 + /* JEDEC id zero means "no ID" (most older chips); otherwise it has
1182 + * a high byte of zero plus three data bytes: the manufacturer id,
1183 + * then a two byte device id.
1187 + /* The size listed here is what works with OPCODE_SE, which isn't
1188 + * necessarily called a "sector" by the vendor.
1190 unsigned sector_size;
1191 - unsigned n_sectors;
1195 +#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
1199 +/* NOTE: double check command sets and memory organization when you add
1200 + * more flash chips. This current list focusses on newer chips, which
1201 + * have been converging on command sets which including JEDEC ID.
1203 static struct flash_info __devinitdata m25p_data [] = {
1204 - /* REVISIT: fill in JEDEC ids, for parts that have them */
1205 - { "m25p05", 0x05, 0x2010, 32 * 1024, 2 },
1206 - { "m25p10", 0x10, 0x2011, 32 * 1024, 4 },
1207 - { "m25p20", 0x11, 0x2012, 64 * 1024, 4 },
1208 - { "m25p40", 0x12, 0x2013, 64 * 1024, 8 },
1209 - { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
1210 - { "m25p16", 0x14, 0x2015, 64 * 1024, 32 },
1211 - { "m25p32", 0x15, 0x2016, 64 * 1024, 64 },
1212 - { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
1214 + /* Atmel -- some are (confusingly) marketed as "DataFlash" */
1215 + { "at25fs010", 0x1f6601, 32 * 1024, 4, SECT_4K, },
1216 + { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, },
1218 + { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
1220 + { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, },
1221 + { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
1222 + { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
1223 + { "at26df321", 0x1f4701, 64 * 1024, 64, SECT_4K, },
1225 + /* Spansion -- single (large) sector size only, at least
1226 + * for the chips listed here (without boot sectors).
1228 + { "s25sl004a", 0x010212, 64 * 1024, 8, },
1229 + { "s25sl008a", 0x010213, 64 * 1024, 16, },
1230 + { "s25sl016a", 0x010214, 64 * 1024, 32, },
1231 + { "s25sl032a", 0x010215, 64 * 1024, 64, },
1232 + { "s25sl064a", 0x010216, 64 * 1024, 128, },
1234 + /* SST -- large erase sizes are "overlays", "sectors" are 4K */
1235 + { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
1236 + { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
1237 + { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
1238 + { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
1240 + /* ST Microelectronics -- newer production may have feature updates */
1241 + { "m25p05", 0x202010, 32 * 1024, 2, },
1242 + { "m25p10", 0x202011, 32 * 1024, 4, },
1243 + { "m25p20", 0x202012, 64 * 1024, 4, },
1244 + { "m25p40", 0x202013, 64 * 1024, 8, },
1245 + { "m25p80", 0, 64 * 1024, 16, },
1246 + { "m25p16", 0x202015, 64 * 1024, 32, },
1247 + { "m25p32", 0x202016, 64 * 1024, 64, },
1248 + { "m25p64", 0x202017, 64 * 1024, 128, },
1249 + { "m25p128", 0x202018, 256 * 1024, 64, },
1251 + { "m45pe80", 0x204014, 64 * 1024, 16, },
1252 + { "m45pe16", 0x204015, 64 * 1024, 32, },
1254 + { "m25pe80", 0x208014, 64 * 1024, 16, },
1255 + { "m25pe16", 0x208015, 64 * 1024, 32, SECT_4K, },
1257 + /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
1258 + { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
1259 + { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
1260 + { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
1261 + { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
1262 + { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
1263 + { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
1264 + { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
1267 +static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
1270 + u8 code = OPCODE_RDID;
1273 + struct flash_info *info;
1275 + /* JEDEC also defines an optional "extended device information"
1276 + * string for after vendor-specific data, after the three bytes
1277 + * we use here. Supporting some chips might require using it.
1279 + tmp = spi_write_then_read(spi, &code, 1, id, 3);
1281 + DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
1282 + spi->dev.bus_id, tmp);
1286 + jedec = jedec << 8;
1288 + jedec = jedec << 8;
1291 + for (tmp = 0, info = m25p_data;
1292 + tmp < ARRAY_SIZE(m25p_data);
1294 + if (info->jedec_id == jedec)
1297 + dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
1303 * board specific setup should have ensured the SPI clock used here
1304 * matches what the READ command supports, at least until this driver
1305 @@ -429,37 +531,51 @@ static int __devinit m25p_probe(struct s
1308 /* Platform data helps sort out which chip type we have, as
1309 - * well as how this board partitions it.
1310 + * well as how this board partitions it. If we don't have
1311 + * a chip ID, try the JEDEC id commands; they'll work for most
1312 + * newer chips, even if we don't recognize the particular chip.
1314 data = spi->dev.platform_data;
1315 - if (!data || !data->type) {
1316 - /* FIXME some chips can identify themselves with RES
1317 - * or JEDEC get-id commands. Try them ...
1319 - DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
1323 + if (data && data->type) {
1324 + for (i = 0, info = m25p_data;
1325 + i < ARRAY_SIZE(m25p_data);
1327 + if (strcmp(data->type, info->name) == 0)
1331 - for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
1332 - if (strcmp(data->type, info->name) == 0)
1335 - if (i == ARRAY_SIZE(m25p_data)) {
1336 - DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
1337 - spi->dev.bus_id, data->type);
1338 + /* unrecognized chip? */
1339 + if (i == ARRAY_SIZE(m25p_data)) {
1340 + DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
1341 + spi->dev.bus_id, data->type);
1344 + /* recognized; is that chip really what's there? */
1345 + } else if (info->jedec_id) {
1346 + struct flash_info *chip = jedec_probe(spi);
1348 + if (!chip || chip != info) {
1349 + dev_warn(&spi->dev, "found %s, expected %s\n",
1350 + chip ? chip->name : "UNKNOWN",
1356 + info = jedec_probe(spi);
1362 flash = kzalloc(sizeof *flash, GFP_KERNEL);
1367 - init_MUTEX(&flash->lock);
1368 + mutex_init(&flash->lock);
1369 dev_set_drvdata(&spi->dev, flash);
1372 + if (data && data->name)
1373 flash->mtd.name = data->name;
1375 flash->mtd.name = spi->dev.bus_id;
1376 @@ -468,17 +584,25 @@ static int __devinit m25p_probe(struct s
1377 flash->mtd.writesize = 1;
1378 flash->mtd.flags = MTD_CAP_NORFLASH;
1379 flash->mtd.size = info->sector_size * info->n_sectors;
1380 - flash->mtd.erasesize = info->sector_size;
1381 flash->mtd.erase = m25p80_erase;
1382 flash->mtd.read = m25p80_read;
1383 flash->mtd.write = m25p80_write;
1385 + /* prefer "small sector" erase if possible */
1386 + if (info->flags & SECT_4K) {
1387 + flash->erase_opcode = OPCODE_BE_4K;
1388 + flash->mtd.erasesize = 4096;
1390 + flash->erase_opcode = OPCODE_SE;
1391 + flash->mtd.erasesize = info->sector_size;
1394 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
1395 flash->mtd.size / 1024);
1397 DEBUG(MTD_DEBUG_LEVEL2,
1398 - "mtd .name = %s, .size = 0x%.8x (%uM) "
1399 - ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
1400 + "mtd .name = %s, .size = 0x%.8x (%uMiB) "
1401 + ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
1403 flash->mtd.size, flash->mtd.size / (1024*1024),
1404 flash->mtd.erasesize, flash->mtd.erasesize / 1024,
1405 @@ -488,7 +612,7 @@ static int __devinit m25p_probe(struct s
1406 for (i = 0; i < flash->mtd.numeraseregions; i++)
1407 DEBUG(MTD_DEBUG_LEVEL2,
1408 "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
1409 - ".erasesize = 0x%.8x (%uK), "
1410 + ".erasesize = 0x%.8x (%uKiB), "
1411 ".numblocks = %d }\n",
1412 i, flash->mtd.eraseregions[i].offset,
1413 flash->mtd.eraseregions[i].erasesize,
1414 @@ -516,14 +640,14 @@ static int __devinit m25p_probe(struct s
1418 - for (i = 0; i < data->nr_parts; i++) {
1419 + for (i = 0; i < nr_parts; i++) {
1420 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
1421 "{.name = %s, .offset = 0x%.8x, "
1422 - ".size = 0x%.8x (%uK) }\n",
1423 - i, data->parts[i].name,
1424 - data->parts[i].offset,
1425 - data->parts[i].size,
1426 - data->parts[i].size / 1024);
1427 + ".size = 0x%.8x (%uKiB) }\n",
1431 + parts[i].size / 1024);
1433 flash->partitioned = 1;
1434 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
1435 @@ -560,6 +684,11 @@ static struct spi_driver m25p80_driver =
1437 .probe = m25p_probe,
1438 .remove = __devexit_p(m25p_remove),
1440 + /* REVISIT: many of these chips have deep power-down modes, which
1441 + * should clearly be entered on suspend() to minimize power use.
1442 + * And also when they're otherwise idle...
1447 Index: linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
1448 ===================================================================
1449 --- linux-2.6.23.17.orig/drivers/mtd/devices/mtd_dataflash.c
1450 +++ linux-2.6.23.17/drivers/mtd/devices/mtd_dataflash.c
1452 #include <linux/slab.h>
1453 #include <linux/delay.h>
1454 #include <linux/device.h>
1455 +#include <linux/mutex.h>
1456 #include <linux/spi/spi.h>
1457 #include <linux/spi/flash.h>
1459 @@ -89,7 +90,7 @@ struct dataflash {
1460 unsigned short page_offset; /* offset in flash address */
1461 unsigned int page_size; /* of bytes per page */
1463 - struct semaphore lock;
1464 + struct mutex lock;
1465 struct spi_device *spi;
1467 struct mtd_info mtd;
1468 @@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_in
1470 spi_message_add_tail(&x, &msg);
1472 - down(&priv->lock);
1473 + mutex_lock(&priv->lock);
1474 while (instr->len > 0) {
1475 unsigned int pageaddr;
1477 @@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_in
1478 instr->len -= priv->page_size;
1482 + mutex_unlock(&priv->lock);
1484 /* Inform MTD subsystem that erase is complete */
1485 instr->state = MTD_ERASE_DONE;
1486 @@ -266,7 +267,7 @@ static int dataflash_read(struct mtd_inf
1488 spi_message_add_tail(&x[1], &msg);
1490 - down(&priv->lock);
1491 + mutex_lock(&priv->lock);
1493 /* Continuous read, max clock = f(car) which may be less than
1494 * the peak rate available. Some chips support commands with
1495 @@ -279,7 +280,7 @@ static int dataflash_read(struct mtd_inf
1496 /* plus 4 "don't care" bytes */
1498 status = spi_sync(priv->spi, &msg);
1500 + mutex_unlock(&priv->lock);
1503 *retlen = msg.actual_length - 8;
1504 @@ -336,7 +337,7 @@ static int dataflash_write(struct mtd_in
1508 - down(&priv->lock);
1509 + mutex_lock(&priv->lock);
1510 while (remaining > 0) {
1511 DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
1512 pageaddr, offset, writelen);
1513 @@ -441,7 +442,7 @@ static int dataflash_write(struct mtd_in
1515 writelen = remaining;
1518 + mutex_unlock(&priv->lock);
1522 @@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, ch
1526 - init_MUTEX(&priv->lock);
1527 + mutex_init(&priv->lock);
1529 priv->page_size = pagesize;
1530 priv->page_offset = pageoffset;
1531 Index: linux-2.6.23.17/drivers/mtd/devices/pmc551.c
1532 ===================================================================
1533 --- linux-2.6.23.17.orig/drivers/mtd/devices/pmc551.c
1534 +++ linux-2.6.23.17/drivers/mtd/devices/pmc551.c
1538 * Due to what I assume is more buggy SROM, the 64M PMC551 I
1539 - * have available claims that all 4 of it's DRAM banks have 64M
1540 - * of ram configured (making a grand total of 256M onboard).
1541 + * have available claims that all 4 of its DRAM banks have 64MiB
1542 + * of ram configured (making a grand total of 256MiB onboard).
1543 * This is slightly annoying since the BAR0 size reflects the
1544 * aperture size, not the dram size, and the V370PDC supplies no
1545 * other method for memory size discovery. This problem is
1547 * made the memory unusable, added a fix to code to touch up
1552 * * MUST fix the init function to not spin on a register
1553 * waiting for it to set .. this does not safely handle busted
1554 * devices that never reset the register correctly which will
1555 @@ -562,10 +562,10 @@ static u32 fixup_pmc551(struct pci_dev *
1559 - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
1560 + printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
1561 "0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
1562 size >> 10 : size >> 20,
1563 - (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
1564 + (size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
1565 ((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
1566 (unsigned long long)pci_resource_start(dev, 0));
1568 @@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
1569 * Stuff these outside the ifdef so as to not bust compiled in driver support
1571 static int msize = 0;
1572 -#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
1573 -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
1575 static int asize = 0;
1578 module_param(msize, int, 0);
1579 -MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
1580 +MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
1581 module_param(asize, int, 0);
1582 MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
1584 @@ -799,8 +795,7 @@ static int __init init_pmc551(void)
1585 mtd->owner = THIS_MODULE;
1587 if (add_mtd_device(mtd)) {
1588 - printk(KERN_NOTICE "pmc551: Failed to register new "
1590 + printk(KERN_NOTICE "pmc551: Failed to register new device\n");
1591 pci_iounmap(PCI_Device, priv->start);
1594 @@ -811,13 +806,13 @@ static int __init init_pmc551(void)
1595 pci_dev_get(PCI_Device);
1597 printk(KERN_NOTICE "Registered pmc551 memory device.\n");
1598 - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
1599 + printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
1601 priv->start, priv->start + priv->asize);
1602 - printk(KERN_NOTICE "Total memory is %d%c\n",
1603 + printk(KERN_NOTICE "Total memory is %d%sB\n",
1604 (length < 1024) ? length :
1605 (length < 1048576) ? length >> 10 : length >> 20,
1606 - (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
1607 + (length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
1608 priv->nextpmc551 = pmc551list;
1611 @@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
1612 pmc551list = priv->nextpmc551;
1615 - printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
1616 + printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
1617 "0x%p\n", priv->asize >> 20, priv->start);
1618 pci_iounmap(priv->dev, priv->start);
1620 Index: linux-2.6.23.17/drivers/mtd/maps/nettel.c
1621 ===================================================================
1622 --- linux-2.6.23.17.orig/drivers/mtd/maps/nettel.c
1623 +++ linux-2.6.23.17/drivers/mtd/maps/nettel.c
1624 @@ -158,68 +158,11 @@ static struct notifier_block nettel_noti
1625 nettel_reboot_notifier, NULL, 0
1629 - * Erase the configuration file system.
1630 - * Used to support the software reset button.
1632 -static void nettel_erasecallback(struct erase_info *done)
1634 - wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
1638 -static struct erase_info nettel_erase;
1640 -int nettel_eraseconfig(void)
1642 - struct mtd_info *mtd;
1643 - DECLARE_WAITQUEUE(wait, current);
1644 - wait_queue_head_t wait_q;
1647 - init_waitqueue_head(&wait_q);
1648 - mtd = get_mtd_device(NULL, 2);
1649 - if (!IS_ERR(mtd)) {
1650 - nettel_erase.mtd = mtd;
1651 - nettel_erase.callback = nettel_erasecallback;
1652 - nettel_erase.callback = NULL;
1653 - nettel_erase.addr = 0;
1654 - nettel_erase.len = mtd->size;
1655 - nettel_erase.priv = (u_long) &wait_q;
1656 - nettel_erase.priv = 0;
1658 - set_current_state(TASK_INTERRUPTIBLE);
1659 - add_wait_queue(&wait_q, &wait);
1661 - ret = mtd->erase(mtd, &nettel_erase);
1663 - set_current_state(TASK_RUNNING);
1664 - remove_wait_queue(&wait_q, &wait);
1665 - put_mtd_device(mtd);
1669 - schedule(); /* Wait for erase to finish. */
1670 - remove_wait_queue(&wait_q, &wait);
1672 - put_mtd_device(mtd);
1680 -int nettel_eraseconfig(void)
1687 /****************************************************************************/
1689 -int __init nettel_init(void)
1690 +static int __init nettel_init(void)
1692 volatile unsigned long *amdpar;
1693 unsigned long amdaddr, maxsize;
1694 @@ -421,10 +364,6 @@ int __init nettel_init(void)
1696 intel_mtd->owner = THIS_MODULE;
1698 -#ifndef CONFIG_BLK_DEV_INITRD
1699 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
1702 num_intel_partitions = sizeof(nettel_intel_partitions) /
1703 sizeof(nettel_intel_partitions[0]);
1705 @@ -477,7 +416,7 @@ out_unmap2:
1707 /****************************************************************************/
1709 -void __exit nettel_cleanup(void)
1710 +static void __exit nettel_cleanup(void)
1712 #ifdef CONFIG_MTD_CFI_INTELEXT
1713 unregister_reboot_notifier(&nettel_notifier_block);
1714 Index: linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
1715 ===================================================================
1716 --- linux-2.6.23.17.orig/drivers/mtd/maps/pmcmsp-ramroot.c
1717 +++ linux-2.6.23.17/drivers/mtd/maps/pmcmsp-ramroot.c
1718 @@ -79,7 +79,6 @@ static int __init init_rrmap(void)
1719 rr_mtd->owner = THIS_MODULE;
1721 add_mtd_device(rr_mtd);
1722 - ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
1726 Index: linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
1727 ===================================================================
1728 --- linux-2.6.23.17.orig/drivers/mtd/mtd_blkdevs.c
1729 +++ linux-2.6.23.17/drivers/mtd/mtd_blkdevs.c
1731 #include <linux/kthread.h>
1732 #include <asm/uaccess.h>
1734 -static LIST_HEAD(blktrans_majors);
1735 +#include "mtdcore.h"
1737 -extern struct mutex mtd_table_mutex;
1738 -extern struct mtd_info *mtd_table[];
1739 +static LIST_HEAD(blktrans_majors);
1741 struct mtd_blkcore_priv {
1742 struct task_struct *thread;
1743 @@ -202,7 +201,7 @@ static int blktrans_ioctl(struct inode *
1747 -struct block_device_operations mtd_blktrans_ops = {
1748 +static struct block_device_operations mtd_blktrans_ops = {
1749 .owner = THIS_MODULE,
1750 .open = blktrans_open,
1751 .release = blktrans_release,
1752 Index: linux-2.6.23.17/drivers/mtd/mtdchar.c
1753 ===================================================================
1754 --- linux-2.6.23.17.orig/drivers/mtd/mtdchar.c
1755 +++ linux-2.6.23.17/drivers/mtd/mtdchar.c
1756 @@ -137,7 +137,8 @@ static int mtd_close(struct inode *inode
1758 DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
1761 + /* Only sync if opened RW */
1762 + if ((file->f_mode & 2) && mtd->sync)
1765 put_mtd_device(mtd);
1766 Index: linux-2.6.23.17/drivers/mtd/mtdcore.c
1767 ===================================================================
1768 --- linux-2.6.23.17.orig/drivers/mtd/mtdcore.c
1769 +++ linux-2.6.23.17/drivers/mtd/mtdcore.c
1772 #include <linux/mtd/mtd.h>
1774 +#include "mtdcore.h"
1776 /* These are exported solely for the purpose of mtd_blkdevs.c. You
1777 should not use them for _anything_ else */
1778 DEFINE_MUTEX(mtd_table_mutex);
1779 Index: linux-2.6.23.17/drivers/mtd/nand/Kconfig
1780 ===================================================================
1781 --- linux-2.6.23.17.orig/drivers/mtd/nand/Kconfig
1782 +++ linux-2.6.23.17/drivers/mtd/nand/Kconfig
1783 @@ -134,10 +134,10 @@ config MTD_NAND_S3C2410_HWECC
1785 config MTD_NAND_NDFC
1786 tristate "NDFC NanD Flash Controller"
1789 select MTD_NAND_ECC_SMC
1791 - NDFC Nand Flash Controllers are integrated in EP44x SoCs
1792 + NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
1794 config MTD_NAND_S3C2410_CLKSTOP
1795 bool "S3C2410 NAND IDLE clock stop"
1796 @@ -237,7 +237,7 @@ config MTD_NAND_CAFE
1798 select REED_SOLOMON_DEC16
1800 - Use NAND flash attached to the CAFÉ chip designed for the $100
1801 + Use NAND flash attached to the CAFÉ chip designed for the OLPC
1804 config MTD_NAND_CS553X
1805 Index: linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
1806 ===================================================================
1807 --- linux-2.6.23.17.orig/drivers/mtd/nand/cafe_nand.c
1808 +++ linux-2.6.23.17/drivers/mtd/nand/cafe_nand.c
1809 @@ -822,14 +822,53 @@ static struct pci_device_id cafe_nand_tb
1811 MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
1813 +static int cafe_nand_resume(struct pci_dev *pdev)
1815 + uint32_t timing1, timing2, timing3;
1817 + struct mtd_info *mtd = pci_get_drvdata(pdev);
1818 + struct cafe_priv *cafe = mtd->priv;
1820 + timing1 = timing2 = timing3 = 0xffffffff;
1821 + /* Start off by resetting the NAND controller completely */
1822 + cafe_writel(cafe, 1, NAND_RESET);
1823 + cafe_writel(cafe, 0, NAND_RESET);
1824 + cafe_writel(cafe, timing1, NAND_TIMING1);
1825 + cafe_writel(cafe, timing2, NAND_TIMING2);
1826 + cafe_writel(cafe, timing3, NAND_TIMING3);
1827 + cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
1829 + /* Disable master reset, enable NAND clock */
1830 + ctrl = cafe_readl(cafe, GLOBAL_CTRL);
1831 + ctrl &= 0xffffeff0;
1832 + ctrl |= 0x00007000;
1833 + cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
1834 + cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
1835 + cafe_writel(cafe, 0, NAND_DMA_CTRL);
1836 + cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
1837 + cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
1839 + /* Set up DMA address */
1840 + cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
1841 + if (sizeof(cafe->dmaaddr) > 4)
1842 + /* Shift in two parts to shut the compiler up */
1843 + cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
1845 + cafe_writel(cafe, 0, NAND_DMA_ADDR1);
1847 + /* Enable NAND IRQ in global IRQ mask register */
1848 + cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
1852 static struct pci_driver cafe_nand_pci_driver = {
1853 .name = "CAFÉ NAND",
1854 .id_table = cafe_nand_tbl,
1855 .probe = cafe_nand_probe,
1856 .remove = __devexit_p(cafe_nand_remove),
1857 + .resume = cafe_nand_resume,
1859 .suspend = cafe_nand_suspend,
1860 - .resume = cafe_nand_resume,
1864 Index: linux-2.6.23.17/drivers/mtd/nand/ndfc.c
1865 ===================================================================
1866 --- linux-2.6.23.17.orig/drivers/mtd/nand/ndfc.c
1867 +++ linux-2.6.23.17/drivers/mtd/nand/ndfc.c
1869 #include <linux/platform_device.h>
1873 +#include <asm/ibm405.h>
1875 #include <asm/ibm44x.h>
1878 struct ndfc_nand_mtd {
1879 struct mtd_info mtd;
1880 @@ -230,7 +234,11 @@ static int ndfc_nand_probe(struct platfo
1881 struct ndfc_controller *ndfc = &ndfc_ctrl;
1882 unsigned long long phys = settings->ndfc_erpn | res->start;
1884 +#ifndef CONFIG_PHYS_64BIT
1885 + ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
1887 ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
1889 if (!ndfc->ndfcbase) {
1890 printk(KERN_ERR "NDFC: ioremap failed\n");
1892 Index: linux-2.6.23.17/drivers/mtd/onenand/Kconfig
1893 ===================================================================
1894 --- linux-2.6.23.17.orig/drivers/mtd/onenand/Kconfig
1895 +++ linux-2.6.23.17/drivers/mtd/onenand/Kconfig
1896 @@ -40,4 +40,27 @@ config MTD_ONENAND_OTP
1898 OTP block is fully-guaranteed to be a valid block.
1900 +config MTD_ONENAND_2X_PROGRAM
1901 + bool "OneNAND 2X program support"
1903 + The 2X Program is an extension of Program Operation.
1904 + Since the device is equipped with two DataRAMs, and two-plane NAND
1905 + Flash memory array, these two component enables simultaneous program
1906 + of 4KiB. Plane1 has only even blocks such as block0, block2, block4
1907 + while Plane2 has only odd blocks such as block1, block3, block5.
1908 + So MTD regards it as 4KiB page size and 256KiB block size
1910 + Now the following chips support it. (KFXXX16Q2M)
1911 + Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
1912 + Mux: KFM2G16Q2M, KFN4G16Q2M,
1914 + And more recent chips
1916 +config MTD_ONENAND_SIM
1917 + tristate "OneNAND simulator support"
1918 + depends on MTD_PARTITIONS
1920 + The simulator may simulate various OneNAND flash chips for the
1921 + OneNAND MTD layer.
1924 Index: linux-2.6.23.17/drivers/mtd/onenand/Makefile
1925 ===================================================================
1926 --- linux-2.6.23.17.orig/drivers/mtd/onenand/Makefile
1927 +++ linux-2.6.23.17/drivers/mtd/onenand/Makefile
1928 @@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
1930 obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
1933 +obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
1935 onenand-objs = onenand_base.o onenand_bbt.o
1936 Index: linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
1937 ===================================================================
1938 --- linux-2.6.23.17.orig/drivers/mtd/onenand/onenand_base.c
1939 +++ linux-2.6.23.17/drivers/mtd/onenand/onenand_base.c
1940 @@ -206,6 +206,15 @@ static int onenand_command(struct mtd_in
1942 block = (int) (addr >> this->erase_shift);
1943 page = (int) (addr >> this->page_shift);
1945 + if (ONENAND_IS_2PLANE(this)) {
1946 + /* Make the even block number */
1948 + /* Is it the odd plane? */
1949 + if (addr & this->writesize)
1953 page &= this->page_mask;
1956 @@ -216,8 +225,12 @@ static int onenand_command(struct mtd_in
1957 value = onenand_bufferram_address(this, block);
1958 this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
1960 - /* Switch to the next data buffer */
1961 - ONENAND_SET_NEXT_BUFFERRAM(this);
1962 + if (ONENAND_IS_2PLANE(this))
1963 + /* It is always BufferRAM0 */
1964 + ONENAND_SET_BUFFERRAM0(this);
1966 + /* Switch to the next data buffer */
1967 + ONENAND_SET_NEXT_BUFFERRAM(this);
1971 @@ -247,6 +260,8 @@ static int onenand_command(struct mtd_in
1975 + if (ONENAND_IS_2PLANE(this) && cmd == ONENAND_CMD_PROG)
1976 + cmd = ONENAND_CMD_2X_PROG;
1977 dataram = ONENAND_CURRENT_BUFFERRAM(this);
1980 @@ -445,8 +460,9 @@ static inline int onenand_bufferram_offs
1981 struct onenand_chip *this = mtd->priv;
1983 if (ONENAND_CURRENT_BUFFERRAM(this)) {
1984 + /* Note: the 'this->writesize' is a real page size */
1985 if (area == ONENAND_DATARAM)
1986 - return mtd->writesize;
1987 + return this->writesize;
1988 if (area == ONENAND_SPARERAM)
1989 return mtd->oobsize;
1991 @@ -572,6 +588,30 @@ static int onenand_write_bufferram(struc
1995 + * onenand_get_2x_blockpage - [GENERIC] Get blockpage at 2x program mode
1996 + * @param mtd MTD data structure
1997 + * @param addr address to check
1998 + * @return blockpage address
2000 + * Get blockpage address at 2x program mode
2002 +static int onenand_get_2x_blockpage(struct mtd_info *mtd, loff_t addr)
2004 + struct onenand_chip *this = mtd->priv;
2005 + int blockpage, block, page;
2007 + /* Calculate the even block number */
2008 + block = (int) (addr >> this->erase_shift) & ~1;
2009 + /* Is it the odd plane? */
2010 + if (addr & this->writesize)
2012 + page = (int) (addr >> (this->page_shift + 1)) & this->page_mask;
2013 + blockpage = (block << 7) | page;
2019 * onenand_check_bufferram - [GENERIC] Check BufferRAM information
2020 * @param mtd MTD data structure
2021 * @param addr address to check
2022 @@ -585,7 +625,10 @@ static int onenand_check_bufferram(struc
2023 int blockpage, found = 0;
2026 - blockpage = (int) (addr >> this->page_shift);
2027 + if (ONENAND_IS_2PLANE(this))
2028 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2030 + blockpage = (int) (addr >> this->page_shift);
2032 /* Is there valid data? */
2033 i = ONENAND_CURRENT_BUFFERRAM(this);
2034 @@ -625,7 +668,10 @@ static void onenand_update_bufferram(str
2038 - blockpage = (int) (addr >> this->page_shift);
2039 + if (ONENAND_IS_2PLANE(this))
2040 + blockpage = onenand_get_2x_blockpage(mtd, addr);
2042 + blockpage = (int) (addr >> this->page_shift);
2044 /* Invalidate another BufferRAM */
2045 i = ONENAND_NEXT_BUFFERRAM(this);
2046 @@ -734,6 +780,7 @@ static int onenand_read(struct mtd_info
2047 int read = 0, column;
2049 int ret = 0, boundary = 0;
2050 + int writesize = this->writesize;
2052 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
2054 @@ -754,22 +801,22 @@ static int onenand_read(struct mtd_info
2055 /* Do first load to bufferRAM */
2057 if (!onenand_check_bufferram(mtd, from)) {
2058 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2059 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2060 ret = this->wait(mtd, FL_READING);
2061 onenand_update_bufferram(mtd, from, !ret);
2065 - thislen = min_t(int, mtd->writesize, len - read);
2066 - column = from & (mtd->writesize - 1);
2067 - if (column + thislen > mtd->writesize)
2068 - thislen = mtd->writesize - column;
2069 + thislen = min_t(int, writesize, len - read);
2070 + column = from & (writesize - 1);
2071 + if (column + thislen > writesize)
2072 + thislen = writesize - column;
2075 /* If there is more to load then start next load */
2077 if (read + thislen < len) {
2078 - this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
2079 + this->command(mtd, ONENAND_CMD_READ, from, writesize);
2081 * Chip boundary handling in DDP
2082 * Now we issued chip 1 read and pointed chip 1
2083 @@ -794,7 +841,7 @@ static int onenand_read(struct mtd_info
2084 this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
2085 ONENAND_SET_NEXT_BUFFERRAM(this);
2087 - thislen = min_t(int, mtd->writesize, len - read);
2088 + thislen = min_t(int, writesize, len - read);
2091 /* Now wait for load */
2092 @@ -1079,7 +1126,7 @@ int onenand_bbt_read_oob(struct mtd_info
2095 /* Update Page size */
2096 - from += mtd->writesize;
2097 + from += this->writesize;
2101 @@ -1135,12 +1182,12 @@ static int onenand_verify(struct mtd_inf
2102 int thislen, column;
2105 - thislen = min_t(int, mtd->writesize, len);
2106 - column = addr & (mtd->writesize - 1);
2107 - if (column + thislen > mtd->writesize)
2108 - thislen = mtd->writesize - column;
2109 + thislen = min_t(int, this->writesize, len);
2110 + column = addr & (this->writesize - 1);
2111 + if (column + thislen > this->writesize)
2112 + thislen = this->writesize - column;
2114 - this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
2115 + this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
2117 onenand_update_bufferram(mtd, addr, 0);
2119 @@ -1236,6 +1283,10 @@ static int onenand_write(struct mtd_info
2121 /* In partial page write we don't update bufferram */
2122 onenand_update_bufferram(mtd, to, !ret && !subpage);
2123 + if (ONENAND_IS_2PLANE(this)) {
2124 + ONENAND_SET_BUFFERRAM1(this);
2125 + onenand_update_bufferram(mtd, to + this->writesize, !ret && !subpage);
2129 printk(KERN_ERR "onenand_write: write filaed %d\n", ret);
2130 @@ -1384,6 +1435,10 @@ static int onenand_do_write_oob(struct m
2131 this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
2133 onenand_update_bufferram(mtd, to, 0);
2134 + if (ONENAND_IS_2PLANE(this)) {
2135 + ONENAND_SET_BUFFERRAM1(this);
2136 + onenand_update_bufferram(mtd, to + this->writesize, 0);
2139 ret = this->wait(mtd, FL_WRITING);
2141 @@ -2107,6 +2162,7 @@ static int onenand_lock_user_prot_reg(st
2143 * Check and set OneNAND features
2147 static void onenand_check_features(struct mtd_info *mtd)
2149 @@ -2118,19 +2174,35 @@ static void onenand_check_features(struc
2150 process = this->version_id >> ONENAND_VERSION_PROCESS_SHIFT;
2153 - if (density >= ONENAND_DEVICE_DENSITY_1Gb) {
2154 + switch (density) {
2155 + case ONENAND_DEVICE_DENSITY_4Gb:
2156 + this->options |= ONENAND_HAS_2PLANE;
2158 + case ONENAND_DEVICE_DENSITY_2Gb:
2159 + /* 2Gb DDP don't have 2 plane */
2160 + if (!ONENAND_IS_DDP(this))
2161 + this->options |= ONENAND_HAS_2PLANE;
2162 + this->options |= ONENAND_HAS_UNLOCK_ALL;
2164 + case ONENAND_DEVICE_DENSITY_1Gb:
2165 /* A-Die has all block unlock */
2167 - printk(KERN_DEBUG "Chip support all block unlock\n");
2169 this->options |= ONENAND_HAS_UNLOCK_ALL;
2172 - /* Some OneNAND has continues lock scheme */
2174 - printk(KERN_DEBUG "Lock scheme is Continues Lock\n");
2178 + /* Some OneNAND has continuous lock scheme */
2180 this->options |= ONENAND_HAS_CONT_LOCK;
2185 + if (this->options & ONENAND_HAS_CONT_LOCK)
2186 + printk(KERN_DEBUG "Lock scheme is Continuous Lock\n");
2187 + if (this->options & ONENAND_HAS_UNLOCK_ALL)
2188 + printk(KERN_DEBUG "Chip support all block unlock\n");
2189 + if (this->options & ONENAND_HAS_2PLANE)
2190 + printk(KERN_DEBUG "Chip has 2 plane\n");
2194 @@ -2257,6 +2329,8 @@ static int onenand_probe(struct mtd_info
2195 this->erase_shift = ffs(mtd->erasesize) - 1;
2196 this->page_shift = ffs(mtd->writesize) - 1;
2197 this->page_mask = (1 << (this->erase_shift - this->page_shift)) - 1;
2198 + /* It's real page size */
2199 + this->writesize = mtd->writesize;
2201 /* REVIST: Multichip handling */
2203 @@ -2265,6 +2339,17 @@ static int onenand_probe(struct mtd_info
2204 /* Check OneNAND features */
2205 onenand_check_features(mtd);
2208 + * We emulate the 4KiB page and 256KiB erase block size
2209 + * But oobsize is still 64 bytes.
2210 + * It is only valid if you turn on 2X program support,
2211 + * Otherwise it will be ignored by compiler.
2213 + if (ONENAND_IS_2PLANE(this)) {
2214 + mtd->writesize <<= 1;
2215 + mtd->erasesize <<= 1;
2221 Index: linux-2.6.23.17/drivers/pci/quirks.c
2222 ===================================================================
2223 --- linux-2.6.23.17.orig/drivers/pci/quirks.c
2224 +++ linux-2.6.23.17/drivers/pci/quirks.c
2225 @@ -1396,6 +1396,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
2226 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm);
2229 + * According to Tom Sylla, the Geode does not support PCI power management
2230 + * transition, so we shouldn't need the D3hot delay.
2232 +static void __init quirk_geode_pci_pm(struct pci_dev *dev)
2234 + pci_pm_d3_delay = 0;
2236 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, quirk_geode_pci_pm);
2237 +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_geode_pci_pm);
2240 * Toshiba TC86C001 IDE controller reports the standard 8-byte BAR0 size
2241 * but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
2242 * Re-allocate the region if needed...
2243 Index: linux-2.6.23.17/drivers/video/Kconfig
2244 ===================================================================
2245 --- linux-2.6.23.17.orig/drivers/video/Kconfig
2246 +++ linux-2.6.23.17/drivers/video/Kconfig
2247 @@ -594,7 +594,7 @@ config FB_TGA
2250 bool "VESA VGA graphics support"
2251 - depends on (FB = y) && X86
2252 + depends on (FB = y) && X86 && !VGA_NOPROBE
2253 select FB_CFB_FILLRECT
2254 select FB_CFB_COPYAREA
2255 select FB_CFB_IMAGEBLIT
2256 @@ -1028,7 +1028,7 @@ config FB_CARILLO_RANCH
2259 tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G support (EXPERIMENTAL)"
2260 - depends on FB && EXPERIMENTAL && PCI && X86
2261 + depends on FB && EXPERIMENTAL && PCI && X86 && !VGA_NOPROBE
2264 select FB_MODE_HELPERS
2265 @@ -1383,7 +1383,7 @@ config FB_SAVAGE_ACCEL
2268 tristate "SiS/XGI display support"
2269 - depends on FB && PCI
2270 + depends on FB && PCI && !VGA_NOPROBE
2271 select FB_CFB_FILLRECT
2272 select FB_CFB_COPYAREA
2273 select FB_CFB_IMAGEBLIT
2274 @@ -1822,6 +1822,15 @@ config FB_PS3_DEFAULT_SIZE_M
2275 The default value can be overridden on the kernel command line
2276 using the "ps3fb" option (e.g. "ps3fb=9M");
2278 +config FB_OLPC_DCON
2279 + tristate "One Laptop Per Child Display CONtroller support"
2283 + Add support for the OLPC DCON controller. This controller is only
2284 + available on OLPC platforms. Unless you have one of these
2285 + platforms, you will want to say 'N'.
2288 tristate "Xilinx frame buffer support"
2289 depends on FB && XILINX_VIRTEX
2290 Index: linux-2.6.23.17/drivers/video/Makefile
2291 ===================================================================
2292 --- linux-2.6.23.17.orig/drivers/video/Makefile
2293 +++ linux-2.6.23.17/drivers/video/Makefile
2294 @@ -111,6 +111,7 @@ obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx
2295 obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
2296 obj-$(CONFIG_FB_PS3) += ps3fb.o
2297 obj-$(CONFIG_FB_SM501) += sm501fb.o
2298 +obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon.o
2299 obj-$(CONFIG_FB_XILINX) += xilinxfb.o
2300 obj-$(CONFIG_FB_OMAP) += omap/
2302 Index: linux-2.6.23.17/drivers/video/fbmem.c
2303 ===================================================================
2304 --- linux-2.6.23.17.orig/drivers/video/fbmem.c
2305 +++ linux-2.6.23.17/drivers/video/fbmem.c
2306 @@ -820,6 +820,53 @@ static void try_to_load(int fb)
2307 #endif /* CONFIG_KMOD */
2310 +fb_powerup(struct fb_info *info)
2314 + if (!info || info->state == FBINFO_STATE_RUNNING)
2317 + if (info->fbops->fb_powerup)
2318 + ret = info->fbops->fb_powerup(info);
2321 + acquire_console_sem();
2322 + fb_set_suspend(info, 0);
2323 + release_console_sem();
2330 +fb_powerdown(struct fb_info *info)
2334 + if (!info || info->state == FBINFO_STATE_SUSPENDED)
2337 + /* Tell everybody that the fbdev is going down */
2338 + acquire_console_sem();
2339 + fb_set_suspend(info, 1);
2340 + release_console_sem();
2342 + if (info->fbops->fb_powerdown)
2343 + ret = info->fbops->fb_powerdown(info);
2345 + /* If the power down failed, then un-notify */
2348 + acquire_console_sem();
2349 + fb_set_suspend(info, 0);
2350 + release_console_sem();
2357 fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
2359 struct fb_fix_screeninfo *fix = &info->fix;
2360 Index: linux-2.6.23.17/drivers/video/geode/Makefile
2361 ===================================================================
2362 --- linux-2.6.23.17.orig/drivers/video/geode/Makefile
2363 +++ linux-2.6.23.17/drivers/video/geode/Makefile
2364 @@ -5,5 +5,5 @@ obj-$(CONFIG_FB_GEODE_GX) += gxfb.o
2365 obj-$(CONFIG_FB_GEODE_LX) += lxfb.o
2367 gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o
2368 -gxfb-objs := gxfb_core.o display_gx.o video_gx.o
2369 +gxfb-objs := gxfb_core.o display_gx.o video_gx.o suspend_gx.o
2370 lxfb-objs := lxfb_core.o lxfb_ops.o
2371 Index: linux-2.6.23.17/drivers/video/geode/display_gx.c
2372 ===================================================================
2373 --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.c
2374 +++ linux-2.6.23.17/drivers/video/geode/display_gx.c
2376 * Free Software Foundation; either version 2 of the License, or * (at your
2377 * option) any later version.
2380 +#include <linux/kernel.h>
2381 #include <linux/spinlock.h>
2382 #include <linux/fb.h>
2383 #include <linux/delay.h>
2385 #include <asm/div64.h>
2386 #include <asm/delay.h>
2387 +#include <asm/olpc.h>
2389 #include "geodefb.h"
2390 #include "display_gx.h"
2392 -#ifdef CONFIG_FB_GEODE_GX_SET_FBSIZE
2393 -unsigned int gx_frame_buffer_size(void)
2394 +static inline void rmwl(u32 val, u32 *reg)
2396 - return CONFIG_FB_GEODE_GX_FBSIZE;
2397 + u32 in = readl(reg);
2403 unsigned int gx_frame_buffer_size(void)
2408 + if (machine_is_olpc() && !olpc_has_vsa()) {
2410 + rdmsr(GLIU0_P2D_RO0, lo, hi);
2412 + /* Top page number */
2413 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
2415 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
2416 + val += 1; /* Adjust page count */
2417 + return (val << 12);
2421 /* FB size is reported by a virtual register */
2422 /* Virtual register class = 0x02 */
2423 /* VG_MEM_SIZE(512Kb units) = 0x00 */
2424 @@ -41,7 +59,6 @@ unsigned int gx_frame_buffer_size(void)
2425 val = (unsigned int)(inw(0xAC1E)) & 0xFFl;
2430 int gx_line_delta(int xres, int bpp)
2432 @@ -63,23 +80,23 @@ static void gx_set_mode(struct fb_info *
2433 gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
2434 dcfg = readl(par->dc_regs + DC_DISPLAY_CFG);
2436 - /* Disable the timing generator. */
2437 - dcfg &= ~(DC_DCFG_TGEN);
2438 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2440 - /* Wait for pending memory requests before disabling the FIFO load. */
2443 - /* Disable FIFO load and compression. */
2444 - gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2445 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2447 - /* Setup DCLK and its divisor. */
2448 - par->vid_ops->set_dclk(info);
2453 + /* Programming the clock is costly and ugly, so avoid if if we can */
2455 + if (par->curdclk != info->var.pixclock) {
2456 + /* Disable the timing generator. */
2457 + dcfg &= ~(DC_DCFG_TGEN);
2458 + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2460 + /* Wait for pending memory requests before disabling the FIFO load. */
2463 + /* Disable FIFO load and compression. */
2464 + gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
2465 + writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2467 + /* Setup DCLK and its divisor. */
2468 + par->vid_ops->set_dclk(info);
2471 /* Clear all unused feature bits. */
2472 gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE;
2473 @@ -90,12 +107,13 @@ static void gx_set_mode(struct fb_info *
2474 gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
2476 /* Framebuffer start offset. */
2477 - writel(0, par->dc_regs + DC_FB_ST_OFFSET);
2478 + rmwl(0, par->dc_regs + DC_FB_ST_OFFSET);
2480 /* Line delta and line buffer length. */
2481 - writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2482 - writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2483 - par->dc_regs + DC_LINE_SIZE);
2484 + rmwl(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH);
2486 + rmwl(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
2487 + par->dc_regs + DC_LINE_SIZE);
2490 /* Enable graphics and video data and unmask address lines. */
2491 @@ -134,17 +152,16 @@ static void gx_set_mode(struct fb_info *
2492 vblankend = vsyncend + info->var.upper_margin;
2495 - writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2496 - writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2497 - writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2499 - writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2500 - writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2501 - writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2502 + rmwl((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING);
2503 + rmwl((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING);
2504 + rmwl((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING);
2505 + rmwl((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING);
2506 + rmwl((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING);
2507 + rmwl((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING);
2509 /* Write final register values. */
2510 - writel(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2511 - writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
2512 + rmwl(dcfg, par->dc_regs + DC_DISPLAY_CFG);
2513 + rmwl(gcfg, par->dc_regs + DC_GENERAL_CFG);
2515 par->vid_ops->configure_display(info);
2517 Index: linux-2.6.23.17/drivers/video/geode/display_gx.h
2518 ===================================================================
2519 --- linux-2.6.23.17.orig/drivers/video/geode/display_gx.h
2520 +++ linux-2.6.23.17/drivers/video/geode/display_gx.h
2521 @@ -20,6 +20,9 @@ extern struct geode_dc_ops gx_dc_ops;
2522 #define GLD_MSR_CONFIG 0xC0002001
2523 #define GLD_MSR_CONFIG_DM_FP 0x40
2525 +/* Used for memory dection on the OLPC */
2526 +#define GLIU0_P2D_RO0 0x10000029
2528 /* Display controller registers */
2530 #define DC_UNLOCK 0x00
2531 Index: linux-2.6.23.17/drivers/video/geode/geodefb.h
2532 ===================================================================
2533 --- linux-2.6.23.17.orig/drivers/video/geode/geodefb.h
2534 +++ linux-2.6.23.17/drivers/video/geode/geodefb.h
2536 #ifndef __GEODEFB_H__
2537 #define __GEODEFB_H__
2539 +#define FB_POWER_STATE_OFF 0
2540 +#define FB_POWER_STATE_SUSPEND 1
2541 +#define FB_POWER_STATE_ON 2
2543 struct geodefb_info;
2545 struct geode_dc_ops {
2546 @@ -21,18 +25,24 @@ struct geode_dc_ops {
2548 struct geode_vid_ops {
2549 void (*set_dclk)(struct fb_info *);
2550 + unsigned int (*get_dclk)(struct fb_info *);
2551 void (*configure_display)(struct fb_info *);
2552 int (*blank_display)(struct fb_info *, int blank_mode);
2555 struct geodefb_par {
2557 + int fbactive; /* True if the current console is in KD_GRAPHICS mode */
2558 int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
2560 + unsigned int curdclk; /* Used by GX to avoid unnessesary clock switching */
2561 void __iomem *dc_regs;
2562 void __iomem *vid_regs;
2563 + void __iomem *gp_regs;
2564 struct geode_dc_ops *dc_ops;
2565 struct geode_vid_ops *vid_ops;
2570 #endif /* !__GEODEFB_H__ */
2571 Index: linux-2.6.23.17/drivers/video/geode/gxfb_core.c
2572 ===================================================================
2573 --- linux-2.6.23.17.orig/drivers/video/geode/gxfb_core.c
2574 +++ linux-2.6.23.17/drivers/video/geode/gxfb_core.c
2576 #include <linux/fb.h>
2577 #include <linux/init.h>
2578 #include <linux/pci.h>
2579 +#include <linux/notifier.h>
2580 +#include <linux/vt_kern.h>
2581 +#include <linux/console.h>
2582 +#include <asm/uaccess.h>
2583 +#include <asm/olpc.h>
2585 #include "geodefb.h"
2586 #include "display_gx.h"
2587 #include "video_gx.h"
2589 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
2590 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
2594 +#define FBIODUMPGP _IOW('F', 0x22, void *)
2595 +#define FBIODUMPDC _IOW('F', 0x23, void *)
2596 +#define FBIODUMPVP _IOW('F', 0x24, void *)
2597 +#define FBIODUMPFP _IOW('F', 0x25, void *)
2601 static char *mode_option;
2602 +static int noclear;
2603 +struct fb_info *gxfb_info;
2605 /* Modes relevant to the GX (taken from modedb.c) */
2606 static const struct fb_videomode gx_modedb[] __initdata = {
2607 @@ -103,8 +122,20 @@ static const struct fb_videomode gx_mode
2608 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
2609 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
2610 FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
2611 + /* 1200x900-75 - CRT timings for the OLPC mode */
2612 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
2613 + 0, FB_VMODE_NONINTERLACED, 0 }
2617 +static const struct fb_videomode gx_dcon_modedb[] __initdata = {
2618 + /* The only mode the DCON has is 1200x900 */
2619 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
2620 + 0, FB_VMODE_NONINTERLACED, 0 }
2625 static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
2627 if (var->xres > 1600 || var->yres > 1200)
2628 @@ -137,7 +168,7 @@ static int gxfb_check_var(struct fb_var_
2632 -static int gxfb_set_par(struct fb_info *info)
2633 +int gxfb_set_par(struct fb_info *info)
2635 struct geodefb_par *par = info->par;
2637 @@ -204,16 +235,26 @@ static int gxfb_blank(int blank_mode, st
2638 return par->vid_ops->blank_display(info, blank_mode);
2643 static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev)
2645 struct geodefb_par *par = info->par;
2649 ret = pci_enable_device(dev);
2653 + ret = pci_request_region(dev, 1, "gxfb (graphics processor)");
2657 + par->gp_regs = ioremap(pci_resource_start(dev, 1),
2658 + pci_resource_len(dev, 1));
2659 + if (!par->gp_regs)
2662 ret = pci_request_region(dev, 3, "gxfb (video processor)");
2665 @@ -232,36 +273,118 @@ static int __init gxfb_map_video_memory(
2666 ret = pci_request_region(dev, 0, "gxfb (framebuffer)");
2669 - if ((fb_len = gx_frame_buffer_size()) < 0)
2672 + /* If the fbsize wasn't specified then try to probe it */
2675 + fbsize = gx_frame_buffer_size();
2680 info->fix.smem_start = pci_resource_start(dev, 0);
2681 - info->fix.smem_len = fb_len;
2682 + info->fix.smem_len = fbsize;
2683 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2684 if (!info->screen_base)
2687 - /* Set the 16MB aligned base address of the graphics memory region
2688 + /* Set the 16MiB aligned base address of the graphics memory region
2689 * in the display controller */
2691 writel(info->fix.smem_start & 0xFF000000,
2692 par->dc_regs + DC_GLIU0_MEM_OFFSET);
2694 - dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n",
2695 + dev_info(&dev->dev, "%d KiB of video memory at 0x%lx\n",
2696 info->fix.smem_len / 1024, info->fix.smem_start);
2701 +static int gxfb_ioctl( struct fb_info *info, unsigned int cmd,
2702 + unsigned long arg)
2704 + unsigned int gamma[GXFB_GAMMA_DWORDS];
2705 + int ret = -EINVAL;
2706 + struct geodefb_par *par = info->par;
2711 + /* Read the gamma information from the user - 256 dwords */
2713 + if (copy_from_user(gamma, (void * __user) arg, GXFB_GAMMA_SIZE))
2716 + writel(0, par->vid_regs + GX_GAR);
2718 + /* Sequential writes to the data register will increment the
2719 + address automatically */
2721 + for(i = 0; i < GXFB_GAMMA_DWORDS; i++)
2722 + writel(gamma[i] & 0xFFFFFF, par->vid_regs + GX_GDR);
2724 + writel(readl(par->vid_regs + GX_MISC) & ~GX_MISC_GAM_EN,
2725 + par->vid_regs + GX_MISC);
2731 + if (readl(par->vid_regs + GX_MISC) & GX_MISC_GAM_EN)
2734 + memset(gamma, 0, GXFB_GAMMA_SIZE);
2735 + writel(0, par->vid_regs + GX_GAR);
2737 + for(i = 0; i < GXFB_GAMMA_DWORDS;i++)
2738 + gamma[i] = readl(par->vid_regs + GX_GDR);
2740 + if (copy_to_user((void * __user) arg, gamma, GXFB_GAMMA_SIZE))
2750 + dump_regs(info, 0);
2755 + dump_regs(info, 1);
2760 + dump_regs(info, 2);
2765 + dump_regs(info, 3);
2773 static struct fb_ops gxfb_ops = {
2774 .owner = THIS_MODULE,
2775 .fb_check_var = gxfb_check_var,
2776 .fb_set_par = gxfb_set_par,
2777 .fb_setcolreg = gxfb_setcolreg,
2778 .fb_blank = gxfb_blank,
2779 + .fb_ioctl = gxfb_ioctl,
2780 /* No HW acceleration for now. */
2781 .fb_fillrect = cfb_fillrect,
2782 .fb_copyarea = cfb_copyarea,
2783 .fb_imageblit = cfb_imageblit,
2784 + .fb_powerdown = gxfb_powerdown,
2785 + .fb_powerup = gxfb_powerup,
2788 static struct fb_info * __init gxfb_init_fbinfo(struct device *dev)
2789 @@ -303,23 +426,86 @@ static struct fb_info * __init gxfb_init
2793 -static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2794 +static int gxfb_console_notify(struct notifier_block *self,
2795 + unsigned long action, void *data)
2797 + if (gxfb_info != NULL) {
2798 + struct geodefb_par *par = gxfb_info->par;
2799 + par->fbactive = (action == CONSOLE_EVENT_SWITCH_TEXT) ? 0 : 1;
2805 +static struct notifier_block gxfb_console_notifier = {
2806 + .notifier_call = gxfb_console_notify
2811 +static int gxfb_suspend(struct pci_dev *pdev, pm_message_t state)
2813 + struct fb_info *info = pci_get_drvdata(pdev);
2814 + struct geodefb_par *par = info->par;
2816 + if (pdev->dev.power.power_state.event == state.event)
2819 + if (state.event == PM_EVENT_SUSPEND) {
2821 + acquire_console_sem();
2822 + gxfb_powerdown(info);
2824 + par->state = FB_POWER_STATE_OFF;
2825 + fb_set_suspend(info, 1);
2827 + release_console_sem();
2830 + pdev->dev.power.power_state = state;
2834 +static int gxfb_resume(struct pci_dev *pdev)
2836 + struct fb_info *info = pci_get_drvdata(pdev);
2838 + acquire_console_sem();
2840 + /* Turn the engine completely on */
2842 + if (gxfb_powerup(info))
2843 + printk(KERN_ERR "gxfb: Powerup failed\n");
2845 + fb_set_suspend(info, 0);
2846 + release_console_sem();
2848 + pdev->dev.power.power_state = PMSG_ON;
2853 +static int __init gxfb_probe(struct pci_dev *pdev,
2854 + const struct pci_device_id *id)
2856 struct geodefb_par *par;
2857 - struct fb_info *info;
2861 - info = gxfb_init_fbinfo(&pdev->dev);
2863 + struct fb_videomode *modedb_ptr;
2866 + gxfb_info = gxfb_init_fbinfo(&pdev->dev);
2867 + if (gxfb_info == NULL)
2871 + par = gxfb_info->par;
2873 /* GX display controller and GX video device. */
2874 par->dc_ops = &gx_dc_ops;
2875 par->vid_ops = &gx_vid_ops;
2877 - if ((ret = gxfb_map_video_memory(info, pdev)) < 0) {
2878 + if ((ret = gxfb_map_video_memory(gxfb_info, pdev)) < 0) {
2879 dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n");
2882 @@ -333,32 +519,60 @@ static int __init gxfb_probe(struct pci_
2884 par->enable_crt = 1;
2886 - ret = fb_find_mode(&info->var, info, mode_option,
2887 - gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16);
2888 + /* Get the current dotclock */
2890 + par->curdclk = (par->vid_ops->get_dclk) ? par->vid_ops->get_dclk(gxfb_info) : 0;
2892 + /* We need to determine a display mode right now, so we will
2893 + * check to see if the DCON was previously detected by the BIOS
2894 + * and use that to make our mode database decision.
2897 + modedb_ptr = (struct fb_videomode *) gx_modedb;
2898 + modedb_size = ARRAY_SIZE(gx_modedb);
2901 + if (olpc_has_dcon()) {
2902 + modedb_ptr = (struct fb_videomode *) gx_dcon_modedb;
2903 + modedb_size = ARRAY_SIZE(gx_dcon_modedb);
2907 + ret = fb_find_mode(&gxfb_info->var, gxfb_info, mode_option,
2908 + modedb_ptr, modedb_size, NULL, 16);
2910 if (ret == 0 || ret == 4) {
2911 dev_err(&pdev->dev, "could not find valid video mode\n");
2916 + /* Clear the screen of garbage, unless noclear was specified,
2917 + * in which case we assume the user knows what he is doing */
2920 + memset_io(gxfb_info->screen_base, 0, gxfb_info->fix.smem_len);
2922 + gxfb_check_var(&gxfb_info->var, gxfb_info);
2923 + gxfb_set_par(gxfb_info);
2925 + /* We are powered up */
2926 + par->state = FB_POWER_STATE_ON;
2928 - /* Clear the frame buffer of garbage. */
2929 - memset_io(info->screen_base, 0, info->fix.smem_len);
2931 - gxfb_check_var(&info->var, info);
2932 - gxfb_set_par(info);
2933 + console_event_register(&gxfb_console_notifier);
2935 - if (register_framebuffer(info) < 0) {
2936 + if (register_framebuffer(gxfb_info) < 0) {
2940 - pci_set_drvdata(pdev, info);
2941 - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
2942 + pci_set_drvdata(pdev, gxfb_info);
2943 + printk(KERN_INFO "fb%d: %s frame buffer device\n", gxfb_info->node, gxfb_info->fix.id);
2947 - if (info->screen_base) {
2948 - iounmap(info->screen_base);
2949 + if (gxfb_info->screen_base) {
2950 + iounmap(gxfb_info->screen_base);
2951 pci_release_region(pdev, 0);
2953 if (par->vid_regs) {
2954 @@ -370,8 +584,9 @@ static int __init gxfb_probe(struct pci_
2955 pci_release_region(pdev, 2);
2959 - framebuffer_release(info);
2961 + framebuffer_release(gxfb_info);
2966 @@ -397,9 +612,7 @@ static void gxfb_remove(struct pci_dev *
2969 static struct pci_device_id gxfb_id_table[] = {
2970 - { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO,
2971 - PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
2973 + { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_GX_VIDEO) },
2977 @@ -410,22 +623,30 @@ static struct pci_driver gxfb_driver = {
2978 .id_table = gxfb_id_table,
2979 .probe = gxfb_probe,
2980 .remove = gxfb_remove,
2982 + .suspend = gxfb_suspend,
2983 + .resume = gxfb_resume
2988 -static int __init gxfb_setup(char *options)
2990 +static int __init gxfb_setup(char *options) {
2994 if (!options || !*options)
2997 - while ((opt = strsep(&options, ",")) != NULL) {
2998 + while((opt = strsep(&options, ",")) != NULL) {
3002 - mode_option = opt;
3003 + if (!strncmp(opt, "fbsize:", 7))
3004 + fbsize = simple_strtoul(opt+7, NULL, 0);
3005 + else if (!strcmp(opt, "noclear"))
3008 + mode_option = opt;
3012 @@ -444,7 +665,6 @@ static int __init gxfb_init(void)
3014 return pci_register_driver(&gxfb_driver);
3017 static void __exit gxfb_cleanup(void)
3019 pci_unregister_driver(&gxfb_driver);
3020 @@ -456,5 +676,8 @@ module_exit(gxfb_cleanup);
3021 module_param(mode_option, charp, 0);
3022 MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])");
3024 +module_param(fbsize, int, 0);
3025 +MODULE_PARM_DESC(fbsize, "video memory size");
3027 MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX");
3028 MODULE_LICENSE("GPL");
3029 Index: linux-2.6.23.17/drivers/video/geode/lxfb.h
3030 ===================================================================
3031 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb.h
3032 +++ linux-2.6.23.17/drivers/video/geode/lxfb.h
3033 @@ -25,10 +25,23 @@ void lx_set_mode(struct fb_info *);
3034 void lx_get_gamma(struct fb_info *, unsigned int *, int);
3035 void lx_set_gamma(struct fb_info *, unsigned int *, int);
3036 unsigned int lx_framebuffer_size(void);
3037 +int lx_shutdown(struct fb_info *);
3038 +int lx_powerup(struct fb_info *);
3039 int lx_blank_display(struct fb_info *, int);
3040 void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int,
3041 unsigned int, unsigned int);
3045 +/* ioctl() defines */
3047 +#define FBIOSGAMMA _IOW('F', 0x20, void *)
3048 +#define FBIOGGAMMA _IOW('F', 0x21, void *)
3050 +/* General definitions */
3051 +#define LXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
3052 +#define LXFB_GAMMA_SIZE (LXFB_GAMMA_DWORDS * sizeof(unsigned int))
3056 #define MSR_LX_GLD_CONFIG 0x48002001
3057 Index: linux-2.6.23.17/drivers/video/geode/lxfb_core.c
3058 ===================================================================
3059 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_core.c
3060 +++ linux-2.6.23.17/drivers/video/geode/lxfb_core.c
3062 #include <linux/init.h>
3063 #include <linux/pci.h>
3064 #include <linux/uaccess.h>
3065 +#include <asm/olpc.h>
3069 @@ -35,186 +36,84 @@ static int fbsize;
3072 const struct fb_videomode geode_modedb[] __initdata = {
3074 - { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2,
3075 + /* 640x480-60 VESA */
3076 + { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
3077 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3078 + /* 640x480-75 VESA */
3079 + { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
3080 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3081 + /* 640x480-85 VESA */
3082 + { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
3083 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3084 + /* 800x600-60 VESA */
3085 + { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
3086 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3087 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3088 + /* 800x600-75 VESA */
3089 + { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
3090 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3091 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3092 + /* 800x600-85 VESA */
3093 + { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
3094 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3095 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3096 + /* 1024x768-60 VESA */
3097 + { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
3098 + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3099 + /* 1024x768-75 VESA */
3100 + { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
3101 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3102 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3103 + /* 1024x768-85 VESA */
3104 + { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
3105 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3106 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3107 + /* 1280x960-60 VESA */
3108 + { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
3109 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3110 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3111 + /* 1280x960-85 VESA */
3112 + { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
3113 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3114 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3115 + /* 1280x1024-60 VESA */
3116 + { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
3117 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3118 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3119 + /* 1280x1024-75 VESA */
3120 + { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
3121 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3122 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3123 + /* 1280x1024-85 VESA */
3124 + { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
3125 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3126 - FB_VMODE_NONINTERLACED, 0 },
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_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3137 - FB_VMODE_NONINTERLACED, 0 },
3139 - { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3,
3140 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3141 - FB_VMODE_NONINTERLACED, 0 },
3143 - { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3,
3144 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3145 - FB_VMODE_NONINTERLACED, 0 },
3147 - { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3,
3148 - 0, FB_VMODE_NONINTERLACED, 0 },
3150 - { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3,
3151 - 0, FB_VMODE_NONINTERLACED, 0 },
3153 - { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2,
3154 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3155 - FB_VMODE_NONINTERLACED, 0 },
3157 - { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2,
3158 - 0, FB_VMODE_NONINTERLACED, 0 },
3160 - { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4,
3161 - 0, FB_VMODE_NONINTERLACED, 0 },
3163 - { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3,
3164 - 0, FB_VMODE_NONINTERLACED, 0 },
3166 - { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6,
3167 - 0, FB_VMODE_NONINTERLACED, 0 },
3169 - { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3,
3170 - 0, FB_VMODE_NONINTERLACED, 0 },
3172 - { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3,
3173 - 0, FB_VMODE_NONINTERLACED, 0 },
3175 - { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3,
3176 - 0, FB_VMODE_NONINTERLACED, 0 },
3178 - { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3,
3179 - 0, FB_VMODE_NONINTERLACED, 0 },
3181 - { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4,
3182 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3183 - FB_VMODE_NONINTERLACED, 0 },
3185 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3186 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3187 - FB_VMODE_NONINTERLACED, 0 },
3189 - { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6,
3190 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3191 - FB_VMODE_NONINTERLACED, 0 },
3193 - { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3,
3194 - 0, FB_VMODE_NONINTERLACED, 0 },
3196 - { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3,
3197 - 0, FB_VMODE_NONINTERLACED, 0 },
3199 - { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3,
3200 - 0, FB_VMODE_NONINTERLACED, 0 },
3202 - { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3,
3203 - 0, FB_VMODE_NONINTERLACED, 0 },
3204 - /* 1024x768-100 */
3205 - { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3,
3206 - 0, FB_VMODE_NONINTERLACED, 0 },
3208 - { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6,
3209 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3210 - FB_VMODE_NONINTERLACED, 0 },
3212 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3213 - 0, FB_VMODE_NONINTERLACED, 0 },
3215 - { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3,
3216 - 0, FB_VMODE_NONINTERLACED, 0 },
3218 - { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3,
3219 - 0, FB_VMODE_NONINTERLACED, 0 },
3221 - { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
3222 - 0, FB_VMODE_NONINTERLACED, 0 },
3224 - { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3,
3225 - 0, FB_VMODE_NONINTERLACED, 0 },
3227 - { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3,
3228 - 0, FB_VMODE_NONINTERLACED, 0 },
3229 - /* 1152x864-100 */
3230 - { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3,
3231 - 0, FB_VMODE_NONINTERLACED, 0 },
3233 - { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3,
3234 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3235 - FB_VMODE_NONINTERLACED, 0 },
3236 - /* 1280x1024-60 */
3237 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3238 - 0, FB_VMODE_NONINTERLACED, 0 },
3239 - /* 1280x1024-70 */
3240 - { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3,
3241 - 0, FB_VMODE_NONINTERLACED, 0 },
3242 - /* 1280x1024-72 */
3243 - { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3,
3244 - 0, FB_VMODE_NONINTERLACED, 0 },
3245 - /* 1280x1024-75 */
3246 - { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3,
3247 - 0, FB_VMODE_NONINTERLACED, 0 },
3248 - /* 1280x1024-85 */
3249 - { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3,
3250 - 0, FB_VMODE_NONINTERLACED, 0 },
3251 - /* 1280x1024-90 */
3252 - { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3,
3253 - 0, FB_VMODE_NONINTERLACED, 0 },
3254 - /* 1280x1024-100 */
3255 - { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3,
3256 - 0, FB_VMODE_NONINTERLACED, 0 },
3257 - /* 1280x1024-60 */
3258 - { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3,
3259 - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3260 - FB_VMODE_NONINTERLACED, 0 },
3261 - /* 1600x1200-60 */
3262 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3263 + /* 1600x1200-60 VESA */
3264 { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3265 - 0, FB_VMODE_NONINTERLACED, 0 },
3266 - /* 1600x1200-70 */
3267 - { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
3268 - 0, FB_VMODE_NONINTERLACED, 0 },
3269 - /* 1600x1200-72 */
3270 - { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3,
3271 - 0, FB_VMODE_NONINTERLACED, 0 },
3272 - /* 1600x1200-75 */
3273 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3274 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3275 + /* 1600x1200-75 VESA */
3276 { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
3277 - 0, FB_VMODE_NONINTERLACED, 0 },
3278 - /* 1600x1200-85 */
3279 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3280 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3281 + /* 1600x1200-85 VESA */
3282 { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
3283 - 0, FB_VMODE_NONINTERLACED, 0 },
3284 - /* 1600x1200-90 */
3285 - { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3,
3286 - 0, FB_VMODE_NONINTERLACED, 0 },
3287 - /* 1600x1200-100 */
3288 - { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3,
3289 - 0, FB_VMODE_NONINTERLACED, 0 },
3290 - /* 1600x1200-60 */
3291 - { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
3292 FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3293 - FB_VMODE_NONINTERLACED, 0 },
3294 - /* 1920x1440-60 */
3295 - { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3,
3296 - 0, FB_VMODE_NONINTERLACED, 0 },
3297 - /* 1920x1440-70 */
3298 - { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3,
3299 - 0, FB_VMODE_NONINTERLACED, 0 },
3300 - /* 1920x1440-72 */
3301 - { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3,
3302 - 0, FB_VMODE_NONINTERLACED, 0 },
3303 - /* 1920x1440-75 */
3304 - { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
3305 - 0, FB_VMODE_NONINTERLACED, 0 },
3306 - /* 1920x1440-85 */
3307 - { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3,
3308 - 0, FB_VMODE_NONINTERLACED, 0 },
3309 + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
3310 + /* 1200x900-75 - CRT timings for the OLPC mode */
3311 + { NULL, 75, 1200, 900, 8049, 104, 240, 29, 54, 136, 3,
3312 + 0, FB_VMODE_NONINTERLACED, 0 }
3316 +const struct fb_videomode olpc_dcon_modedb[] __initdata = {
3317 + /* The only mode the DCON has is 1200x900 */
3318 + { NULL, 50, 1200, 900, 17460, 24, 8, 4, 5, 8, 3,
3319 + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
3320 + FB_VMODE_NONINTERLACED, 0 }
3324 static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
3326 if (var->xres > 1920 || var->yres > 1440)
3327 @@ -379,16 +278,55 @@ static int __init lxfb_map_video_memory(
3331 +static int lxfb_set_gamma(struct fb_info *info, void * __user data)
3333 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3335 + if (copy_from_user(gamma, data, LXFB_GAMMA_SIZE))
3338 + lx_set_gamma(info, gamma, LXFB_GAMMA_SIZE);
3342 +static int lxfb_get_gamma(struct fb_info *info, void * __user data)
3344 + unsigned int gamma[LXFB_GAMMA_DWORDS];
3345 + memset(gamma, 0, sizeof(gamma));
3347 + lx_get_gamma(info, gamma, LXFB_GAMMA_DWORDS);
3349 + return copy_to_user(data, gamma, LXFB_GAMMA_SIZE) ?
3353 +static int lxfb_ioctl( struct fb_info *info, unsigned int cmd,
3354 + unsigned long arg)
3358 + return lxfb_set_gamma(info, (void * __user) arg);
3361 + return lxfb_get_gamma(info, (void * __user) arg);
3367 static struct fb_ops lxfb_ops = {
3368 .owner = THIS_MODULE,
3369 .fb_check_var = lxfb_check_var,
3370 .fb_set_par = lxfb_set_par,
3371 .fb_setcolreg = lxfb_setcolreg,
3372 .fb_blank = lxfb_blank,
3373 + .fb_ioctl = lxfb_ioctl,
3374 /* No HW acceleration for now. */
3375 .fb_fillrect = cfb_fillrect,
3376 .fb_copyarea = cfb_copyarea,
3377 .fb_imageblit = cfb_imageblit,
3378 + .fb_powerdown = lx_shutdown,
3379 + .fb_powerup = lx_powerup,
3382 static struct fb_info * __init lxfb_init_fbinfo(struct device *dev)
3383 @@ -431,6 +369,45 @@ static struct fb_info * __init lxfb_init
3389 +static int lxfb_suspend(struct pci_dev *pdev, pm_message_t state)
3391 + struct fb_info *info = pci_get_drvdata(pdev);
3393 + if (pdev->dev.power.power_state.event == state.event)
3396 + if (state.event == PM_EVENT_SUSPEND) {
3398 + acquire_console_sem();
3399 + lx_shutdown(info);
3400 + fb_set_suspend(info, 1);
3401 + release_console_sem();
3404 + pdev->dev.power.power_state = state;
3408 +static int lxfb_resume(struct pci_dev *pdev)
3410 + struct fb_info *info = pci_get_drvdata(pdev);
3412 + acquire_console_sem();
3414 + /* Turn the engine completely on */
3417 + fb_set_suspend(info, 0);
3418 + release_console_sem();
3420 + pdev->dev.power.power_state = PMSG_ON;
3426 static int __init lxfb_probe(struct pci_dev *pdev,
3427 const struct pci_device_id *id)
3429 @@ -467,6 +444,13 @@ static int __init lxfb_probe(struct pci_
3430 modedb_ptr = (struct fb_videomode *) geode_modedb;
3431 modedb_size = ARRAY_SIZE(geode_modedb);
3434 + if (olpc_has_dcon()) {
3435 + modedb_ptr = (struct fb_videomode *) olpc_dcon_modedb;
3436 + modedb_size = ARRAY_SIZE(olpc_dcon_modedb);
3440 ret = fb_find_mode(&info->var, info, mode_option,
3441 modedb_ptr, modedb_size, NULL, 16);
3443 @@ -556,6 +540,10 @@ static struct pci_driver lxfb_driver = {
3444 .id_table = lxfb_id_table,
3445 .probe = lxfb_probe,
3446 .remove = lxfb_remove,
3448 + .suspend = lxfb_suspend,
3449 + .resume = lxfb_resume
3454 Index: linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
3455 ===================================================================
3456 --- linux-2.6.23.17.orig/drivers/video/geode/lxfb_ops.c
3457 +++ linux-2.6.23.17/drivers/video/geode/lxfb_ops.c
3459 #include <linux/fb.h>
3460 #include <linux/uaccess.h>
3461 #include <linux/delay.h>
3462 +#include <asm/olpc.h>
3467 +#include "geode_regs.h"
3470 * Support panel scaling
3472 @@ -290,6 +294,19 @@ unsigned int lx_framebuffer_size(void)
3477 + if (machine_is_olpc() && !olpc_has_vsa()) {
3479 + rdmsr(MSR_LX_GLIU0_P2D_RO0, lo, hi);
3481 + /* Top page number */
3482 + val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
3483 + val -= (lo & 0x000fffff); /* Subtract bottom page number */
3484 + val += 1; /* Adjust page count */
3485 + return (val << 12);
3489 /* The frame buffer size is reported by a VSM in VSA II */
3490 /* Virtual Register Class = 0x02 */
3491 /* VG_MEM_SIZE (1MB units) = 0x00 */
3492 @@ -301,6 +318,34 @@ unsigned int lx_framebuffer_size(void)
3496 +void lx_set_gamma(struct fb_info *info, unsigned int *gamma, int len)
3499 + struct lxfb_par *par = info->par;
3501 + writel(0, par->df_regs + DF_PAR);
3503 + /* Sequential writes to the data register will increment the
3504 + address automatically */
3506 + for(i = 0; i < len; i++)
3507 + writel(gamma[i] & 0xFFFFFF, par->df_regs + DF_PDR);
3509 + writel(readl(par->df_regs + DF_MISC) & ~DF_MISC_GAM_BYPASS,
3510 + par->df_regs + DF_MISC);
3513 +void lx_get_gamma(struct fb_info *info, unsigned int *gamma, int len)
3516 + struct lxfb_par *par = info->par;
3518 + writel(0, par->df_regs + DF_PAR);
3520 + for(i = 0; i < len;i++)
3521 + gamma[i] = readl(par->df_regs + DF_PDR);
3524 void lx_set_mode(struct fb_info *info)
3526 struct lxfb_par *par = info->par;
3527 @@ -313,6 +358,7 @@ void lx_set_mode(struct fb_info *info)
3528 int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
3530 /* Unlock the DC registers */
3531 + readl(par->dc_regs + DC_UNLOCK);
3532 writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3534 lx_graphics_disable(info);
3535 @@ -534,3 +580,285 @@ int lx_blank_display(struct fb_info *inf
3540 +static struct geoderegs saved_regs;
3542 +static void lx_save_regs(struct fb_info *info, struct geoderegs *regs)
3544 + struct lxfb_par *par = info->par;
3547 + /* Wait for the command buffer to empty */
3548 + while(!(readl(par->gp_regs + 0x44) & (1 << 4)));
3550 + rdmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3551 + rdmsrl(MSR_LX_GLCP_DOTPLL, regs->msr.dotpll);
3552 + rdmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3553 + rdmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3555 + writel(0x4758, par->dc_regs + 0x00);
3557 + memcpy(regs->gp.b, par->gp_regs, GP_REG_SIZE);
3558 + memcpy(regs->dc.b, par->dc_regs, DC_REG_SIZE);
3559 + memcpy(regs->vp.b, par->df_regs, VP_REG_SIZE);
3560 + memcpy(regs->fp.b, par->df_regs + VP_FP_START, FP_REG_SIZE);
3562 + /* Save the palettes */
3563 + writel(0, par->dc_regs + 0x70);
3565 + for(i = 0; i < DC_PAL_SIZE; i++)
3566 + regs->pal[i] = readl(par->dc_regs + 0x74);
3568 + writel(0, par->df_regs + 0x38);
3570 + for(i = 0; i <= 0xFF; i++)
3571 + regs->gamma[i] = readl(par->df_regs + 0x40);
3574 +static void lx_restore_regs(struct fb_info *info, struct geoderegs *regs)
3576 + struct lxfb_par *par = info->par;
3579 + /* == DOTPLL == */
3581 + lx_set_dotpll((u32) (regs->msr.dotpll >> 32));
3585 + wrmsrl(MSR_LX_DF_GLCONFIG, regs->msr.dfglcfg);
3589 + writel(regs->gp.r.dst_offset, par->gp_regs + 0x00);
3590 + writel(regs->gp.r.src_offset, par->gp_regs + 0x04);
3591 + writel(regs->gp.r.stride, par->gp_regs + 0x08);
3592 + writel(regs->gp.r.wid_height, par->gp_regs + 0x0C);
3593 + writel(regs->gp.r.src_color_fg, par->gp_regs + 0x10);
3594 + writel(regs->gp.r.src_color_bg, par->gp_regs + 0x14);
3595 + writel(regs->gp.r.pat_color_0, par->gp_regs + 0x18);
3596 + writel(regs->gp.r.pat_color_1, par->gp_regs + 0x1C);
3597 + writel(regs->gp.r.pat_color_2, par->gp_regs + 0x20);
3598 + writel(regs->gp.r.pat_color_3, par->gp_regs + 0x24);
3599 + writel(regs->gp.r.pat_color_4, par->gp_regs + 0x28);
3600 + writel(regs->gp.r.pat_color_5, par->gp_regs + 0x2C);
3601 + writel(regs->gp.r.pat_data_0, par->gp_regs + 0x30);
3602 + writel(regs->gp.r.pat_data_1, par->gp_regs + 0x34);
3604 + /* Writing to these registers would cause a blt to happen */
3605 + /* 0x38, 0x3c, 0x40 */
3607 + /* Status register (0x44) is read only */
3609 + writel(regs->gp.r.hst_src, par->gp_regs + 0x48);
3610 + writel(regs->gp.r.base_offset, par->gp_regs + 0x4c);
3611 + writel(regs->gp.r.cmd_top, par->gp_regs + 0x50);
3612 + writel(regs->gp.r.cmd_bot, par->gp_regs + 0x54);
3613 + writel(regs->gp.r.cmd_read, par->gp_regs + 0x58);
3614 + writel(regs->gp.r.cmd_write, par->gp_regs + 0x5C);
3615 + writel(regs->gp.r.ch3_offset, par->gp_regs + 0x60);
3616 + writel(regs->gp.r.ch3_mode_str, par->gp_regs + 0x64);
3617 + writel(regs->gp.r.ch3_width, par->gp_regs + 0x6C);
3618 + writel(regs->gp.r.ch3_hsrc, par->gp_regs + 0x70);
3620 + /* FIXME: Restore the LUT data here */
3622 + writel(regs->gp.r.int_cntrl, par->gp_regs + 0x70);
3626 + /* Write the unlock value */
3627 + writel(0x4758, par->dc_regs + 0x00);
3629 + /* Write the palette data first */
3631 + writel(0, par->dc_regs + 0x70);
3633 + for(i = 0; i < DC_PAL_SIZE; i++)
3634 + writel(regs->pal[i], par->dc_regs + 0x74);
3637 + wrmsrl(MSR_LX_DC_SPARE, regs->msr.dcspare);
3639 + /* Write the gcfg register without the enables */
3640 + writel(regs->dc.r.gcfg & ~0x0F, par->dc_regs + 0x04);
3642 + /* Write the vcfg register without the enables */
3643 + writel(regs->dc.r.dcfg & ~0x19, par->dc_regs + 0x08);
3645 + /* Write the rest of the active registers */
3646 + writel(regs->dc.r.arb, par->dc_regs + 0x0C);
3647 + writel(regs->dc.r.fb_st_offset, par->dc_regs + 0x10);
3648 + writel(regs->dc.r.cb_st_offset, par->dc_regs + 0x14);
3649 + writel(regs->dc.r.curs_st_offset, par->dc_regs + 0x18);
3650 + writel(regs->dc.r.icon_st_offset, par->dc_regs + 0x1C);
3651 + writel(regs->dc.r.vid_y_st_offset, par->dc_regs + 0x20);
3652 + writel(regs->dc.r.vid_u_st_offset, par->dc_regs + 0x24);
3653 + writel(regs->dc.r.vid_v_st_offset, par->dc_regs + 0x28);
3654 + writel(regs->dc.r.dctop, par->dc_regs + 0x2c);
3655 + writel(regs->dc.r.line_size, par->dc_regs + 0x30);
3656 + writel(regs->dc.r.gfx_pitch, par->dc_regs + 0x34);
3657 + writel(regs->dc.r.vid_yuv_pitch, par->dc_regs + 0x38);
3658 + writel(regs->dc.r.h_active_timing, par->dc_regs + 0x40);
3659 + writel(regs->dc.r.h_blank_timing, par->dc_regs + 0x44);
3660 + writel(regs->dc.r.h_sync_timing, par->dc_regs + 0x48);
3661 + writel(regs->dc.r.v_active_timing, par->dc_regs + 0x50);
3662 + writel(regs->dc.r.v_blank_timing, par->dc_regs + 0x54);
3663 + writel(regs->dc.r.v_sync_timing, par->dc_regs + 0x58);
3664 + writel(regs->dc.r.fbactive, par->dc_regs + 0x5c);
3665 + writel(regs->dc.r.dc_cursor_x, par->dc_regs + 0x60);
3666 + writel(regs->dc.r.dc_cursor_y, par->dc_regs + 0x64);
3667 + writel(regs->dc.r.dc_icon_x, par->dc_regs + 0x68);
3669 + /* Skip register 0x6C (line_cnt), 0x70/0x74 (palette),
3670 + 0x78 (diagnostic), and 0x7c (diagnostic)
3673 + writel(regs->dc.r.dc_vid_ds_delta, par->dc_regs + 0x80);
3674 + writel(regs->dc.r.gliu0_mem_offset, par->dc_regs + 0x84);
3675 + writel(regs->dc.r.dv_ctl, par->dc_regs + 0x88);
3676 + writel(regs->dc.r.dv_acc, par->dc_regs + 0x8C);
3678 + writel(regs->dc.r.gfx_scale, par->dc_regs + 0x90);
3679 + writel(regs->dc.r.irq_filt_ctl, par->dc_regs + 0x94);
3680 + writel(regs->dc.r.filt_coeff1, par->dc_regs + 0x98);
3681 + writel(regs->dc.r.filt_coeff2, par->dc_regs + 0x9C);
3682 + writel(regs->dc.r.vbi_event_ctl, par->dc_regs + 0xA0);
3684 + writel(regs->dc.r.vbi_odd_ctl, par->dc_regs + 0xA4);
3685 + writel(regs->dc.r.vbi_hor, par->dc_regs + 0xA8);
3686 + writel(regs->dc.r.vbi_ln_odd, par->dc_regs + 0xAC);
3687 + writel(regs->dc.r.vbi_ln_event, par->dc_regs + 0xB0);
3688 + writel(regs->dc.r.vbi_pitch, par->dc_regs + 0xB4);
3689 + writel(regs->dc.r.clr_key, par->dc_regs + 0xB8);
3690 + writel(regs->dc.r.clr_key_mask, par->dc_regs + 0xBC);
3692 + writel(regs->dc.r.clr_key_x, par->dc_regs + 0xC0);
3693 + writel(regs->dc.r.clr_key_y, par->dc_regs + 0xC4);
3694 + writel(regs->dc.r.irq, par->dc_regs + 0xC8);
3695 + writel(regs->dc.r.genlk_ctrl, par->dc_regs + 0xD4);
3697 + writel(regs->dc.r.vid_even_y_st_offset, par->dc_regs + 0xD8);
3698 + writel(regs->dc.r.vid_even_u_st_offset, par->dc_regs + 0xDC);
3699 + writel(regs->dc.r.vid_even_v_st_offset, par->dc_regs + 0xE0);
3701 + writel(regs->dc.r.v_active_even_timing, par->dc_regs + 0xE4);
3702 + writel(regs->dc.r.v_blank_even_timing, par->dc_regs + 0xE8);
3703 + writel(regs->dc.r.v_sync_even_timing, par->dc_regs + 0xEC);
3708 + wrmsrl(MSR_LX_DF_PADSEL, regs->msr.padsel);
3710 + /* Write gamma information first */
3712 + writel(0, par->df_regs + 0x38);
3714 + for(i = 0; i <= 0xFF; i++)
3715 + writel((u32) regs->gamma[i], par->df_regs + 0x40);
3717 + /* Don't enable video yet */
3718 + writel((u32) regs->vp.r.vcfg & ~0x01, par->df_regs + 0x00);
3720 + /* Don't enable the CRT yet */
3721 + writel((u32) regs->vp.r.dcfg & ~0x0F, par->df_regs + 0x08);
3723 + /* Write the rest of the VP registers */
3725 + writel((u32) regs->vp.r.vx, par->df_regs + 0x10);
3726 + writel((u32) regs->vp.r.vy, par->df_regs + 0x18);
3727 + writel((u32) regs->vp.r.vs, par->df_regs + 0x20);
3728 + writel((u32) regs->vp.r.vck, par->df_regs + 0x28);
3729 + writel((u32) regs->vp.r.vcm, par->df_regs + 0x30);
3730 + writel((u32) regs->vp.r.misc, par->df_regs + 0x50);
3731 + writel((u32) regs->vp.r.ccs, par->df_regs + 0x58);
3732 + writel((u32) regs->vp.r.vdc, par->df_regs + 0x78);
3733 + writel((u32) regs->vp.r.vco, par->df_regs + 0x80);
3734 + writel((u32) regs->vp.r.crc, par->df_regs + 0x88);
3735 + writel((u32) regs->vp.r.vde, par->df_regs + 0x98);
3736 + writel((u32) regs->vp.r.cck, par->df_regs + 0xA0);
3737 + writel((u32) regs->vp.r.ccm, par->df_regs + 0xA8);
3738 + writel((u32) regs->vp.r.cc1, par->df_regs + 0xB0);
3739 + writel((u32) regs->vp.r.cc2, par->df_regs + 0xB8);
3740 + writel((u32) regs->vp.r.a1x, par->df_regs + 0xC0);
3741 + writel((u32) regs->vp.r.a1y, par->df_regs + 0xC8);
3742 + writel((u32) regs->vp.r.a1c, par->df_regs + 0xD0);
3743 + writel((u32) regs->vp.r.a1t, par->df_regs + 0xD8);
3744 + writel((u32) regs->vp.r.a2x, par->df_regs + 0xE0);
3745 + writel((u32) regs->vp.r.a2y, par->df_regs + 0xE8);
3746 + writel((u32) regs->vp.r.a2c, par->df_regs + 0xF0);
3747 + writel((u32) regs->vp.r.a2t, par->df_regs + 0xF8);
3748 + writel((u32) regs->vp.r.a3x, par->df_regs + 0x100);
3749 + writel((u32) regs->vp.r.a3y, par->df_regs + 0x108);
3750 + writel((u32) regs->vp.r.a3c, par->df_regs + 0x110);
3751 + writel((u32) regs->vp.r.a3t, par->df_regs + 0x118);
3752 + writel((u32) regs->vp.r.vrr, par->df_regs + 0x120);
3754 + writel((u32) regs->vp.r.vye, par->df_regs + 0x138);
3755 + writel((u32) regs->vp.r.a1ye, par->df_regs + 0x140);
3756 + writel((u32) regs->vp.r.a2ye, par->df_regs + 0x148);
3757 + writel((u32) regs->vp.r.a3ye, par->df_regs + 0x150);
3761 + writel((u32) regs->fp.r.pt1, par->df_regs + 0x400);
3762 + writel((u32) regs->fp.r.pt2, par->df_regs + 0x408);
3763 + writel((u32) regs->fp.r.dfc, par->df_regs + 0x418);
3764 + writel(regs->fp.r.dca, par->df_regs + 0x448);
3765 + writel(regs->fp.r.dmd, par->df_regs + 0x450);
3766 + writel(regs->fp.r.crc, par->df_regs + 0x458);
3768 + /* Final enables */
3770 + val = readl(par->df_regs + 0x410);
3772 + /* Control the panel */
3773 + if (regs->fp.r.pm & (1 << 24)) {
3775 + if (!(val & 0x09))
3776 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3779 + if (!(val & 0x05))
3780 + writel(regs->fp.r.pm, par->df_regs + 0x410);
3783 + /* Turn everything on */
3785 + writel(regs->dc.r.gcfg, par->dc_regs + 0x04);
3786 + writel((u32) regs->vp.r.vcfg, par->df_regs + 0x00);
3787 + writel((u32) regs->vp.r.dcfg, par->df_regs + 0x08);
3788 + writel(regs->dc.r.dcfg, par->dc_regs + 0x08);
3791 +static int lx_power_on = 1;
3793 +int lx_shutdown(struct fb_info *info)
3795 + struct lxfb_par *par = info->par;
3797 + if (lx_power_on == 0)
3800 + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
3801 + lx_save_regs(info, &saved_regs);
3802 + lx_graphics_disable(info);
3808 +int lx_powerup(struct fb_info *info)
3810 + struct lxfb_par *par = info->par;
3812 + if (lx_power_on == 1)
3815 + lx_restore_regs(info, &saved_regs);
3816 + writel(0, par->dc_regs + DC_UNLOCK);
3821 Index: linux-2.6.23.17/drivers/video/geode/video_gx.c
3822 ===================================================================
3823 --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.c
3824 +++ linux-2.6.23.17/drivers/video/geode/video_gx.c
3827 #include <asm/delay.h>
3828 #include <asm/msr.h>
3829 +#include <asm/olpc.h>
3831 #include "geodefb.h"
3832 #include "video_gx.h"
3833 +#include "display_gx.h"
3835 +/* This structure is used to store the saved registers during suspend */
3836 +static struct geoderegs gx_saved_regs;
3839 * Tables of register settings for various DOTCLKs.
3840 @@ -58,7 +62,7 @@ static const struct gx_pll_entry gx_pll_
3841 { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */
3842 { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */
3843 { 13333, 0, 0x00000052 }, /* 75.0000 */
3844 - { 12698, 0, 0x00000056 }, /* 78.7500 */
3845 + { 12698, 0, 0x00000056 }, /* 78.7500 */
3846 { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */
3847 { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */
3848 { 10582, 0, 0x000002D2 }, /* 94.5000 */
3849 @@ -117,8 +121,9 @@ static const struct gx_pll_entry gx_pll_
3850 { 4357, 0, 0x0000057D }, /* 229.5000 */
3853 -static void gx_set_dclk_frequency(struct fb_info *info)
3854 +void gx_set_dclk_frequency(struct fb_info *info)
3856 + struct geodefb_par *par = info->par;
3857 const struct gx_pll_entry *pll_table;
3860 @@ -173,115 +178,169 @@ static void gx_set_dclk_frequency(struct
3862 rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3863 } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK));
3865 + par->curdclk = pll_table[best_i].dotpll_value;
3869 -gx_configure_tft(struct fb_info *info)
3870 +/* Find out the current clock - we will use this information to avoid
3871 + re-programming it if we don't need to */
3873 +unsigned int gx_get_dclk(struct fb_info *info)
3875 - struct geodefb_par *par = info->par;
3876 - unsigned long val;
3878 + const struct gx_pll_entry *pll_table;
3879 + int pll_table_len;
3883 - /* Set up the DF pad select MSR */
3884 + if (cpu_data->x86_mask == 1) {
3885 + pll_table = gx_pll_table_14MHz;
3886 + pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz);
3888 + pll_table = gx_pll_table_48MHz;
3889 + pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz);
3892 - rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3893 - val &= ~GX_VP_PAD_SELECT_MASK;
3894 - val |= GX_VP_PAD_SELECT_TFT;
3895 - wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3896 + rdmsrl(MSR_GLCP_DOTPLL, dotpll);
3898 - /* Turn off the panel */
3899 + for(i = 0; i < pll_table_len; i++) {
3900 + if (pll_table[i].dotpll_value == (u32) (dotpll >> 32))
3904 + return (i == pll_table_len) ? 0 : pll_table[i].pixclock;
3907 - fp = readl(par->vid_regs + GX_FP_PM);
3908 - fp &= ~GX_FP_PM_P;
3909 - writel(fp, par->vid_regs + GX_FP_PM);
3911 - /* Set timing 1 */
3912 +#define CMP(val, mask, res) (((val) & (mask)) == (res))
3914 - fp = readl(par->vid_regs + GX_FP_PT1);
3915 - fp &= GX_FP_PT1_VSIZE_MASK;
3916 - fp |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
3917 - writel(fp, par->vid_regs + GX_FP_PT1);
3919 +gx_configure_tft(struct fb_info *info) {
3922 - /* Set bits that are always on for TFT */
3923 + struct geodefb_par *par = info->par;
3924 + u32 val, fp = 0, fp1, fp2, sync = 0;
3927 + /* Set up the DF pad select MSR */
3929 - /* Add sync polarity */
3930 + rdmsrl(GX_VP_MSR_PAD_SELECT, val);
3932 + if ((val & GX_VP_PAD_SELECT_MASK) != GX_VP_PAD_SELECT_TFT) {
3933 + val &= ~GX_VP_PAD_SELECT_MASK;
3934 + val |= GX_VP_PAD_SELECT_TFT;
3935 + wrmsrl(GX_VP_MSR_PAD_SELECT, val);
3938 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
3939 - fp |= GX_FP_PT2_VSP;
3940 + sync |= GX_FP_PT2_VSP;
3942 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
3943 - fp |= GX_FP_PT2_HSP;
3944 + sync |= GX_FP_PT2_HSP;
3946 - writel(fp, par->vid_regs + GX_FP_PT2);
3947 + /* We only need to turn off the panel if something changed */
3949 - /* Set the dither control */
3950 - writel(0x70, par->vid_regs + GX_FP_DFC);
3951 + fp1 = readl(par->vid_regs + GX_FP_PT1);
3952 + fp2 = readl(par->vid_regs + GX_FP_PT2);
3954 + if (!CMP(fp1, GX_FP_PT1_VSIZE_MASK, info->var.yres << GX_FP_PT1_VSIZE_SHIFT) ||
3955 + (fp2 != (0x0F100000 | sync))) {
3957 + /* Turn off the panel */
3960 + /* Do we really need to turn off the panel? */
3961 + /* Possibly - we have a glitch somewhere */
3963 - /* Enable the FP data and power (in case the BIOS didn't) */
3964 + fp = readl(par->vid_regs + GX_FP_PM);
3965 + fp &= ~GX_FP_PM_P;
3966 + writel(fp, par->vid_regs + GX_FP_PM);
3969 - fp = readl(par->vid_regs + GX_DCFG);
3970 - fp |= GX_DCFG_FP_PWR_EN | GX_DCFG_FP_DATA_EN;
3971 - writel(fp, par->vid_regs + GX_DCFG);
3973 + fp1 &= GX_FP_PT1_VSIZE_MASK;
3974 + fp1 |= info->var.yres << GX_FP_PT1_VSIZE_SHIFT;
3975 + writel(fp, par->vid_regs + GX_FP_PT1);
3977 - /* Unblank the panel */
3979 + writel(0x0F100000 | sync, par->vid_regs + GX_FP_PT2);
3982 + /* Set the dither control */
3983 + if (readl(par->vid_regs + GX_FP_DFC) != 0x70) {
3984 + writel(0x70, par->vid_regs + GX_FP_DFC);
3987 + /* Turn on the panel */
3989 fp = readl(par->vid_regs + GX_FP_PM);
3991 - writel(fp, par->vid_regs + GX_FP_PM);
3994 + writel(fp | GX_FP_PM_P, par->vid_regs + GX_FP_PM);
3997 +#define DCFG_DEFAULT_VAL GX_DCFG_CRT_SYNC_SKW_DFLT | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN | \
3998 +GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN
4000 static void gx_configure_display(struct fb_info *info)
4002 struct geodefb_par *par = info->par;
4004 + u32 dcfg, misc, sync = 0;
4006 /* Set up the MISC register */
4008 misc = readl(par->vid_regs + GX_MISC);
4010 - /* Power up the DAC */
4011 - misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4012 + /* We leave gamma enabled if it was already enabled.
4013 + Although the hardware enables it without setting
4014 + up the gamma table, the BIOS or bootloader ought
4015 + to have either disabled it or loaded a table by now */
4017 - /* Disable gamma correction */
4018 - misc |= GX_MISC_GAM_EN;
4020 - writel(misc, par->vid_regs + GX_MISC);
4022 - /* Write the display configuration */
4023 - dcfg = readl(par->vid_regs + GX_DCFG);
4024 + if (par->enable_crt) {
4025 + /* Power up the CRT DACs */
4026 + if (misc & ( GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN)) {
4027 + misc &= ~(GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4028 + writel(misc, par->vid_regs + GX_MISC);
4031 - /* Disable hsync and vsync */
4032 - dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4033 - writel(dcfg, par->vid_regs + GX_DCFG);
4034 + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
4035 + sync |= GX_DCFG_CRT_HSYNC_POL;
4037 - /* Clear bits from existing mode. */
4038 - dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4039 - | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4040 - | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4041 + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
4042 + sync |= GX_DCFG_CRT_VSYNC_POL;
4045 + /* Turn off the CRT DACs in FP mode - we don't need them */
4046 + if ((misc & (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN))) {
4047 + misc |= (GX_MISC_A_PWRDN | GX_MISC_DAC_PWRDN);
4048 + writel(misc, par->vid_regs + GX_MISC);
4052 - /* Set default sync skew. */
4053 - dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4054 + /* Write the display configuration */
4055 + dcfg = readl(par->vid_regs + GX_DCFG);
4057 - /* Enable hsync and vsync. */
4058 - dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4059 + if (!CMP(dcfg, DCFG_DEFAULT_VAL | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL,
4060 + DCFG_DEFAULT_VAL | sync)) {
4062 - /* Sync polarities. */
4063 - if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
4064 - dcfg |= GX_DCFG_CRT_HSYNC_POL;
4065 - if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
4066 - dcfg |= GX_DCFG_CRT_VSYNC_POL;
4067 + /* Disable hsync and vsync */
4068 + dcfg &= ~(GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4069 + writel(dcfg, par->vid_regs + GX_DCFG);
4071 - /* Enable the display logic */
4072 - /* Set up the DACS to blank normally */
4073 + /* Clear bits from existing mode. */
4074 + dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK
4075 + | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL
4076 + | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN);
4078 - dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4079 + /* Set default sync skew. */
4080 + dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT;
4082 - /* Enable the external DAC VREF? */
4083 + /* Enable hsync and vsync. */
4084 + dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN;
4086 - writel(dcfg, par->vid_regs + GX_DCFG);
4087 + /* Enable the display logic */
4088 + dcfg |= GX_DCFG_CRT_EN | GX_DCFG_DAC_BL_EN;
4090 + writel(dcfg, par->vid_regs + GX_DCFG);
4093 /* Set up the flat panel (if it is enabled) */
4095 @@ -289,6 +348,100 @@ static void gx_configure_display(struct
4096 gx_configure_tft(info);
4099 +int gxfb_powerdown(struct fb_info *info)
4101 + struct geodefb_par *par = info->par;
4103 + /* We're already suspended */
4105 + if (par->state != FB_POWER_STATE_ON)
4108 + /* Save the registers */
4109 + gx_save_regs(info, &gx_saved_regs);
4111 + /* Shut down the engine */
4113 + writel(gx_saved_regs.vp.r.vcfg & ~0x01, par->vid_regs + GX_VCFG);
4114 + writel(gx_saved_regs.vp.r.dcfg & ~0x0F, par->vid_regs + GX_DCFG);
4116 + /* Turn off the flat panel unless we are attached to a DCON */
4117 + if (!olpc_has_dcon())
4118 + writel(gx_saved_regs.fp.r.pm & ~GX_FP_PM_P, par->vid_regs + GX_FP_PM);
4120 + writel(0x4758, par->dc_regs + DC_UNLOCK);
4122 + writel(gx_saved_regs.dc.r.gcfg & ~0x0F,
4123 + par->dc_regs + DC_GENERAL_CFG);
4125 + writel(gx_saved_regs.dc.r.dcfg & ~0x19,
4126 + par->dc_regs + DC_DISPLAY_CFG);
4128 + par->state = FB_POWER_STATE_SUSPEND;
4133 +int gxfb_powerup(struct fb_info *info)
4135 + struct geodefb_par *par = info->par;
4138 + if (par->state == FB_POWER_STATE_SUSPEND) {
4140 + writel(gx_saved_regs.dc.r.dcfg,
4141 + par->dc_regs + DC_DISPLAY_CFG);
4143 + writel(gx_saved_regs.vp.r.vcfg, par->vid_regs + GX_VCFG);
4144 + writel(gx_saved_regs.vp.r.dcfg, par->vid_regs + GX_DCFG);
4146 + val = readl(par->vid_regs + GX_FP_PM);
4148 + /* power up the panel if it needs it; we don't always power it down */
4149 + if (!(val & 0x09)) {
4150 + writel(gx_saved_regs.fp.r.pm, par->vid_regs + GX_FP_PM);
4155 + /* If the panel is currently on its way up, then wait up to 100ms
4158 + if (readl(par->vid_regs + GX_FP_PM) & 0x08) {
4161 + for(i = 0; i < 10; i++) {
4162 + if (readl(par->vid_regs + GX_FP_PM) & 0x01)
4169 + printk(KERN_ERR "gxfb: Panel power up timed out\n");
4172 + if (par->state == FB_POWER_STATE_ON)
4175 + switch(par->state) {
4176 + case FB_POWER_STATE_OFF:
4177 + gx_restore_regs(info, &gx_saved_regs);
4180 + case FB_POWER_STATE_SUSPEND:
4181 + /* Do this because it will turn on the FIFO which will
4182 + start the line count */
4183 + writel(gx_saved_regs.dc.r.gcfg,
4184 + par->dc_regs + DC_GENERAL_CFG);
4185 + writel(0x0, par->dc_regs + DC_UNLOCK);
4189 + par->state = FB_POWER_STATE_ON;
4193 static int gx_blank_display(struct fb_info *info, int blank_mode)
4195 struct geodefb_par *par = info->par;
4196 @@ -315,6 +468,7 @@ static int gx_blank_display(struct fb_in
4201 dcfg = readl(par->vid_regs + GX_DCFG);
4202 dcfg &= ~(GX_DCFG_DAC_BL_EN
4203 | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN);
4204 @@ -326,7 +480,7 @@ static int gx_blank_display(struct fb_in
4205 dcfg |= GX_DCFG_VSYNC_EN;
4206 writel(dcfg, par->vid_regs + GX_DCFG);
4208 - /* Power on/off flat panel. */
4209 + /* Power on/off flat panel */
4211 if (par->enable_crt == 0) {
4212 fp_pm = readl(par->vid_regs + GX_FP_PM);
4213 @@ -340,8 +494,37 @@ static int gx_blank_display(struct fb_in
4217 +extern struct fb_info *gxfb_info;
4219 +/* This function controls the flatpanel power sequencing - this is used
4220 + by the OLPC power management engine to enable the FP sequencing much
4221 + earlier in the resume process
4224 +void gxfb_flatpanel_control(int state)
4226 + struct geodefb_par *par = gxfb_info->par;
4227 + u32 val, fp = readl(par->vid_regs + GX_FP_PM);
4230 + /* Turn on the panel if it isn't aleady */
4233 + if (!(val & 0x01))
4234 + val |= GX_FP_PM_P;
4237 + if (!(val & 0x02))
4238 + val &= ~GX_FP_PM_P;
4242 + writel(val, par->vid_regs + GX_FP_PM);
4245 struct geode_vid_ops gx_vid_ops = {
4246 .set_dclk = gx_set_dclk_frequency,
4247 + .get_dclk = gx_get_dclk,
4248 .configure_display = gx_configure_display,
4249 .blank_display = gx_blank_display,
4251 Index: linux-2.6.23.17/drivers/video/geode/video_gx.h
4252 ===================================================================
4253 --- linux-2.6.23.17.orig/drivers/video/geode/video_gx.h
4254 +++ linux-2.6.23.17/drivers/video/geode/video_gx.h
4256 #ifndef __VIDEO_GX_H__
4257 #define __VIDEO_GX_H__
4259 +#include "geode_regs.h"
4261 extern struct geode_vid_ops gx_vid_ops;
4263 /* GX Flatpanel control MSR */
4264 @@ -20,6 +22,8 @@ extern struct geode_vid_ops gx_vid_ops;
4266 /* Geode GX video processor registers */
4268 +#define GX_VCFG 0x0000
4270 #define GX_DCFG 0x0008
4271 # define GX_DCFG_CRT_EN 0x00000001
4272 # define GX_DCFG_HSYNC_EN 0x00000002
4273 @@ -42,6 +46,14 @@ extern struct geode_vid_ops gx_vid_ops;
4274 #define GX_MISC_DAC_PWRDN 0x00000400
4275 #define GX_MISC_A_PWRDN 0x00000800
4277 +/* Gamma correction RAM - address and data registers */
4279 +#define GX_GAR 0x038
4280 +#define GX_GDR 0x040
4282 +#define GXFB_GAMMA_DWORDS 256 /* number of dwords in the gamma ram */
4283 +#define GXFB_GAMMA_SIZE (GXFB_GAMMA_DWORDS * sizeof(unsigned int))
4285 /* Geode GX flat panel display control registers */
4287 #define GX_FP_PT1 0x0400
4288 @@ -69,4 +81,13 @@ extern struct geode_vid_ops gx_vid_ops;
4289 # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull)
4290 # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull)
4292 +int gxfb_powerdown(struct fb_info *info);
4293 +int gxfb_powerup(struct fb_info *info);
4295 +void gx_set_dclk_frequency(struct fb_info *info);
4296 +unsigned int gx_get_dclk(struct fb_info *info);
4298 +void gx_save_regs(struct fb_info *info, struct geoderegs *regs);
4299 +void gx_restore_regs(struct fb_info *info, struct geoderegs *regs);
4301 #endif /* !__VIDEO_GX_H__ */
4302 Index: linux-2.6.23.17/drivers/video/modedb.c
4303 ===================================================================
4304 --- linux-2.6.23.17.orig/drivers/video/modedb.c
4305 +++ linux-2.6.23.17/drivers/video/modedb.c
4306 @@ -33,6 +33,8 @@ const char *global_mode_option;
4307 * Standard video mode definitions (taken from XFree86)
4310 +#define DEFAULT_MODEDB_INDEX 0
4312 static const struct fb_videomode modedb[] = {
4314 /* 640x400 @ 70 Hz, 31.5 kHz hsync */
4315 @@ -504,7 +506,8 @@ int fb_find_mode(struct fb_var_screeninf
4319 - default_mode = &db[0];
4320 + default_mode = (db == modedb) ?
4321 + &modedb[DEFAULT_MODEDB_INDEX] : &db[0];
4325 Index: linux-2.6.23.17/fs/Kconfig
4326 ===================================================================
4327 --- linux-2.6.23.17.orig/fs/Kconfig
4328 +++ linux-2.6.23.17/fs/Kconfig
4329 @@ -1003,6 +1003,23 @@ config HUGETLBFS
4334 + tristate "PromFS IEEE 1275 file system support"
4335 + depends on SPARC || PPC || OLPC
4337 + PromFS is a file system interface to various IEEE-1275 compatible
4338 + firmwares. If you have such a firmware (Sparc64, PowerPC, and
4339 + some other architectures and embedded systems have such firmwares,
4340 + with names like "OpenBoot (tm)" and "OpenFirmware"), say Y here
4341 + to be able to access the firmware's device-tree from Linux.
4343 + The firmware device-tree is available as a virtual file system,
4344 + can be mounted under /prom with the command "mount -t promfs
4347 + To compile PromFS support as a module, choose M here; the module
4348 + will be called promfs. If unsure, choose M.
4353 @@ -1229,6 +1246,14 @@ config JFFS2_FS_WRITEBUFFER
4354 - NOR flash with transparent ECC
4357 +config JFFS2_FS_WBUF_VERIFY
4358 + bool "Verify JFFS2 write-buffer reads"
4359 + depends on JFFS2_FS_WRITEBUFFER
4362 + This causes JFFS2 to read back every page written through the
4363 + write-buffer, and check for errors.
4365 config JFFS2_SUMMARY
4366 bool "JFFS2 summary support (EXPERIMENTAL)"
4367 depends on JFFS2_FS && EXPERIMENTAL
4368 @@ -1299,52 +1324,52 @@ config JFFS2_ZLIB
4373 - Zlib is designed to be a free, general-purpose, legally unencumbered,
4374 - lossless data-compression library for use on virtually any computer
4375 - hardware and operating system. See <http://www.gzip.org/zlib/> for
4376 - further information.
4378 + Zlib is designed to be a free, general-purpose, legally unencumbered,
4379 + lossless data-compression library for use on virtually any computer
4380 + hardware and operating system. See <http://www.gzip.org/zlib/> for
4381 + further information.
4383 - Say 'Y' if unsure.
4384 + Say 'Y' if unsure.
4387 bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
4391 - Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4393 + Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
4396 bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
4400 - RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4402 + RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
4405 - prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4406 - default JFFS2_CMODE_PRIORITY
4407 - depends on JFFS2_FS
4409 - You can set here the default compression mode of JFFS2 from
4410 - the available compression modes. Don't touch if unsure.
4411 + prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
4412 + default JFFS2_CMODE_PRIORITY
4413 + depends on JFFS2_FS
4415 + You can set here the default compression mode of JFFS2 from
4416 + the available compression modes. Don't touch if unsure.
4418 config JFFS2_CMODE_NONE
4419 - bool "no compression"
4421 - Uses no compression.
4422 + bool "no compression"
4424 + Uses no compression.
4426 config JFFS2_CMODE_PRIORITY
4429 - Tries the compressors in a predefined order and chooses the first
4433 + Tries the compressors in a predefined order and chooses the first
4436 config JFFS2_CMODE_SIZE
4437 - bool "size (EXPERIMENTAL)"
4439 - Tries all compressors and chooses the one which has the smallest
4441 + bool "size (EXPERIMENTAL)"
4443 + Tries all compressors and chooses the one which has the smallest
4448 Index: linux-2.6.23.17/fs/Makefile
4449 ===================================================================
4450 --- linux-2.6.23.17.orig/fs/Makefile
4451 +++ linux-2.6.23.17/fs/Makefile
4452 @@ -110,6 +110,7 @@ obj-$(CONFIG_ADFS_FS) += adfs/
4453 obj-$(CONFIG_FUSE_FS) += fuse/
4454 obj-$(CONFIG_UDF_FS) += udf/
4455 obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
4456 +obj-$(CONFIG_PROMFS_FS) += promfs/
4457 obj-$(CONFIG_JFS_FS) += jfs/
4458 obj-$(CONFIG_XFS_FS) += xfs/
4459 obj-$(CONFIG_9P_FS) += 9p/
4460 Index: linux-2.6.23.17/fs/jffs2/background.c
4461 ===================================================================
4462 --- linux-2.6.23.17.orig/fs/jffs2/background.c
4463 +++ linux-2.6.23.17/fs/jffs2/background.c
4464 @@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(
4465 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
4467 spin_lock(&c->erase_completion_lock);
4468 - if (c->gc_task && jffs2_thread_should_wake(c))
4469 - send_sig(SIGHUP, c->gc_task, 1);
4470 + if (c->gc_task && jffs2_thread_should_wake(c))
4471 + send_sig(SIGHUP, c->gc_task, 1);
4472 spin_unlock(&c->erase_completion_lock);
4475 Index: linux-2.6.23.17/fs/jffs2/compr.c
4476 ===================================================================
4477 --- linux-2.6.23.17.orig/fs/jffs2/compr.c
4478 +++ linux-2.6.23.17/fs/jffs2/compr.c
4480 * Created by Arjan van de Ven <arjanv@redhat.com>
4482 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4483 - * University of Szeged, Hungary
4484 + * University of Szeged, Hungary
4486 * For licensing information, see the file 'LICENCE' in this directory.
4488 @@ -43,121 +43,122 @@ static uint32_t none_stat_compr_blocks=0
4489 * *datalen accordingly to show the amount of data which were compressed.
4491 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
4492 - unsigned char *data_in, unsigned char **cpage_out,
4493 - uint32_t *datalen, uint32_t *cdatalen)
4494 + unsigned char *data_in, unsigned char **cpage_out,
4495 + uint32_t *datalen, uint32_t *cdatalen)
4497 int ret = JFFS2_COMPR_NONE;
4499 - struct jffs2_compressor *this, *best=NULL;
4500 - unsigned char *output_buf = NULL, *tmp_buf;
4501 - uint32_t orig_slen, orig_dlen;
4502 - uint32_t best_slen=0, best_dlen=0;
4504 - switch (jffs2_compression_mode) {
4505 - case JFFS2_COMPR_MODE_NONE:
4507 - case JFFS2_COMPR_MODE_PRIORITY:
4508 - output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4509 - if (!output_buf) {
4510 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4513 - orig_slen = *datalen;
4514 - orig_dlen = *cdatalen;
4515 - spin_lock(&jffs2_compressor_list_lock);
4516 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4517 - /* Skip decompress-only backwards-compatibility and disabled modules */
4518 - if ((!this->compress)||(this->disabled))
4522 - spin_unlock(&jffs2_compressor_list_lock);
4523 - *datalen = orig_slen;
4524 - *cdatalen = orig_dlen;
4525 - compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4526 - spin_lock(&jffs2_compressor_list_lock);
4529 - ret = this->compr;
4530 - this->stat_compr_blocks++;
4531 - this->stat_compr_orig_size += *datalen;
4532 - this->stat_compr_new_size += *cdatalen;
4536 - spin_unlock(&jffs2_compressor_list_lock);
4537 - if (ret == JFFS2_COMPR_NONE) kfree(output_buf);
4539 - case JFFS2_COMPR_MODE_SIZE:
4540 - orig_slen = *datalen;
4541 - orig_dlen = *cdatalen;
4542 - spin_lock(&jffs2_compressor_list_lock);
4543 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4544 - /* Skip decompress-only backwards-compatibility and disabled modules */
4545 - if ((!this->compress)||(this->disabled))
4547 - /* Allocating memory for output buffer if necessary */
4548 - if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4549 - spin_unlock(&jffs2_compressor_list_lock);
4550 - kfree(this->compr_buf);
4551 - spin_lock(&jffs2_compressor_list_lock);
4552 - this->compr_buf_size=0;
4553 - this->compr_buf=NULL;
4555 - if (!this->compr_buf) {
4556 - spin_unlock(&jffs2_compressor_list_lock);
4557 - tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4558 - spin_lock(&jffs2_compressor_list_lock);
4560 - printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4564 - this->compr_buf = tmp_buf;
4565 - this->compr_buf_size = orig_dlen;
4569 - spin_unlock(&jffs2_compressor_list_lock);
4570 - *datalen = orig_slen;
4571 - *cdatalen = orig_dlen;
4572 - compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4573 - spin_lock(&jffs2_compressor_list_lock);
4576 - if ((!best_dlen)||(best_dlen>*cdatalen)) {
4577 - best_dlen = *cdatalen;
4578 - best_slen = *datalen;
4584 - *cdatalen = best_dlen;
4585 - *datalen = best_slen;
4586 - output_buf = best->compr_buf;
4587 - best->compr_buf = NULL;
4588 - best->compr_buf_size = 0;
4589 - best->stat_compr_blocks++;
4590 - best->stat_compr_orig_size += best_slen;
4591 - best->stat_compr_new_size += best_dlen;
4592 - ret = best->compr;
4594 - spin_unlock(&jffs2_compressor_list_lock);
4597 - printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4600 + struct jffs2_compressor *this, *best=NULL;
4601 + unsigned char *output_buf = NULL, *tmp_buf;
4602 + uint32_t orig_slen, orig_dlen;
4603 + uint32_t best_slen=0, best_dlen=0;
4605 + switch (jffs2_compression_mode) {
4606 + case JFFS2_COMPR_MODE_NONE:
4608 + case JFFS2_COMPR_MODE_PRIORITY:
4609 + output_buf = kmalloc(*cdatalen,GFP_KERNEL);
4610 + if (!output_buf) {
4611 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n");
4614 + orig_slen = *datalen;
4615 + orig_dlen = *cdatalen;
4616 + spin_lock(&jffs2_compressor_list_lock);
4617 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4618 + /* Skip decompress-only backwards-compatibility and disabled modules */
4619 + if ((!this->compress)||(this->disabled))
4623 + spin_unlock(&jffs2_compressor_list_lock);
4624 + *datalen = orig_slen;
4625 + *cdatalen = orig_dlen;
4626 + compr_ret = this->compress(data_in, output_buf, datalen, cdatalen, NULL);
4627 + spin_lock(&jffs2_compressor_list_lock);
4630 + ret = this->compr;
4631 + this->stat_compr_blocks++;
4632 + this->stat_compr_orig_size += *datalen;
4633 + this->stat_compr_new_size += *cdatalen;
4637 + spin_unlock(&jffs2_compressor_list_lock);
4638 + if (ret == JFFS2_COMPR_NONE)
4639 + kfree(output_buf);
4641 + case JFFS2_COMPR_MODE_SIZE:
4642 + orig_slen = *datalen;
4643 + orig_dlen = *cdatalen;
4644 + spin_lock(&jffs2_compressor_list_lock);
4645 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4646 + /* Skip decompress-only backwards-compatibility and disabled modules */
4647 + if ((!this->compress)||(this->disabled))
4649 + /* Allocating memory for output buffer if necessary */
4650 + if ((this->compr_buf_size<orig_dlen)&&(this->compr_buf)) {
4651 + spin_unlock(&jffs2_compressor_list_lock);
4652 + kfree(this->compr_buf);
4653 + spin_lock(&jffs2_compressor_list_lock);
4654 + this->compr_buf_size=0;
4655 + this->compr_buf=NULL;
4657 + if (!this->compr_buf) {
4658 + spin_unlock(&jffs2_compressor_list_lock);
4659 + tmp_buf = kmalloc(orig_dlen,GFP_KERNEL);
4660 + spin_lock(&jffs2_compressor_list_lock);
4662 + printk(KERN_WARNING "JFFS2: No memory for compressor allocation. (%d bytes)\n",orig_dlen);
4666 + this->compr_buf = tmp_buf;
4667 + this->compr_buf_size = orig_dlen;
4671 + spin_unlock(&jffs2_compressor_list_lock);
4672 + *datalen = orig_slen;
4673 + *cdatalen = orig_dlen;
4674 + compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen, NULL);
4675 + spin_lock(&jffs2_compressor_list_lock);
4678 + if ((!best_dlen)||(best_dlen>*cdatalen)) {
4679 + best_dlen = *cdatalen;
4680 + best_slen = *datalen;
4686 + *cdatalen = best_dlen;
4687 + *datalen = best_slen;
4688 + output_buf = best->compr_buf;
4689 + best->compr_buf = NULL;
4690 + best->compr_buf_size = 0;
4691 + best->stat_compr_blocks++;
4692 + best->stat_compr_orig_size += best_slen;
4693 + best->stat_compr_new_size += best_dlen;
4694 + ret = best->compr;
4696 + spin_unlock(&jffs2_compressor_list_lock);
4699 + printk(KERN_ERR "JFFS2: unknow compression mode.\n");
4702 - if (ret == JFFS2_COMPR_NONE) {
4703 - *cpage_out = data_in;
4704 - *datalen = *cdatalen;
4705 - none_stat_compr_blocks++;
4706 - none_stat_compr_size += *datalen;
4709 - *cpage_out = output_buf;
4711 + if (ret == JFFS2_COMPR_NONE) {
4712 + *cpage_out = data_in;
4713 + *datalen = *cdatalen;
4714 + none_stat_compr_blocks++;
4715 + none_stat_compr_size += *datalen;
4718 + *cpage_out = output_buf;
4723 @@ -165,8 +166,8 @@ int jffs2_decompress(struct jffs2_sb_inf
4724 uint16_t comprtype, unsigned char *cdata_in,
4725 unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
4727 - struct jffs2_compressor *this;
4729 + struct jffs2_compressor *this;
4732 /* Older code had a bug where it would write non-zero 'usercompr'
4733 fields. Deal with it. */
4734 @@ -177,32 +178,32 @@ int jffs2_decompress(struct jffs2_sb_inf
4735 case JFFS2_COMPR_NONE:
4736 /* This should be special-cased elsewhere, but we might as well deal with it */
4737 memcpy(data_out, cdata_in, datalen);
4738 - none_stat_decompr_blocks++;
4739 + none_stat_decompr_blocks++;
4741 case JFFS2_COMPR_ZERO:
4742 memset(data_out, 0, datalen);
4745 - spin_lock(&jffs2_compressor_list_lock);
4746 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4747 - if (comprtype == this->compr) {
4749 - spin_unlock(&jffs2_compressor_list_lock);
4750 - ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4751 - spin_lock(&jffs2_compressor_list_lock);
4753 - printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4756 - this->stat_decompr_blocks++;
4759 - spin_unlock(&jffs2_compressor_list_lock);
4763 + spin_lock(&jffs2_compressor_list_lock);
4764 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4765 + if (comprtype == this->compr) {
4767 + spin_unlock(&jffs2_compressor_list_lock);
4768 + ret = this->decompress(cdata_in, data_out, cdatalen, datalen, NULL);
4769 + spin_lock(&jffs2_compressor_list_lock);
4771 + printk(KERN_WARNING "Decompressor \"%s\" returned %d\n", this->name, ret);
4774 + this->stat_decompr_blocks++;
4777 + spin_unlock(&jffs2_compressor_list_lock);
4781 printk(KERN_WARNING "JFFS2 compression type 0x%02x not available.\n", comprtype);
4782 - spin_unlock(&jffs2_compressor_list_lock);
4783 + spin_unlock(&jffs2_compressor_list_lock);
4787 @@ -210,108 +211,108 @@ int jffs2_decompress(struct jffs2_sb_inf
4789 int jffs2_register_compressor(struct jffs2_compressor *comp)
4791 - struct jffs2_compressor *this;
4792 + struct jffs2_compressor *this;
4794 - if (!comp->name) {
4795 - printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4798 - comp->compr_buf_size=0;
4799 - comp->compr_buf=NULL;
4801 - comp->stat_compr_orig_size=0;
4802 - comp->stat_compr_new_size=0;
4803 - comp->stat_compr_blocks=0;
4804 - comp->stat_decompr_blocks=0;
4805 - D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4807 - spin_lock(&jffs2_compressor_list_lock);
4809 - list_for_each_entry(this, &jffs2_compressor_list, list) {
4810 - if (this->priority < comp->priority) {
4811 - list_add(&comp->list, this->list.prev);
4815 - list_add_tail(&comp->list, &jffs2_compressor_list);
4816 + if (!comp->name) {
4817 + printk(KERN_WARNING "NULL compressor name at registering JFFS2 compressor. Failed.\n");
4820 + comp->compr_buf_size=0;
4821 + comp->compr_buf=NULL;
4823 + comp->stat_compr_orig_size=0;
4824 + comp->stat_compr_new_size=0;
4825 + comp->stat_compr_blocks=0;
4826 + comp->stat_decompr_blocks=0;
4827 + D1(printk(KERN_DEBUG "Registering JFFS2 compressor \"%s\"\n", comp->name));
4829 + spin_lock(&jffs2_compressor_list_lock);
4831 + list_for_each_entry(this, &jffs2_compressor_list, list) {
4832 + if (this->priority < comp->priority) {
4833 + list_add(&comp->list, this->list.prev);
4837 + list_add_tail(&comp->list, &jffs2_compressor_list);
4839 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4840 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4842 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4843 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4846 - spin_unlock(&jffs2_compressor_list_lock);
4847 + spin_unlock(&jffs2_compressor_list_lock);
4853 int jffs2_unregister_compressor(struct jffs2_compressor *comp)
4855 - D2(struct jffs2_compressor *this;)
4856 + D2(struct jffs2_compressor *this;)
4858 + D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4860 - D1(printk(KERN_DEBUG "Unregistering JFFS2 compressor \"%s\"\n", comp->name));
4861 + spin_lock(&jffs2_compressor_list_lock);
4863 - spin_lock(&jffs2_compressor_list_lock);
4864 + if (comp->usecount) {
4865 + spin_unlock(&jffs2_compressor_list_lock);
4866 + printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4869 + list_del(&comp->list);
4871 - if (comp->usecount) {
4872 - spin_unlock(&jffs2_compressor_list_lock);
4873 - printk(KERN_WARNING "JFFS2: Compressor modul is in use. Unregister failed.\n");
4876 - list_del(&comp->list);
4878 - D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4879 - printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4881 - spin_unlock(&jffs2_compressor_list_lock);
4883 + D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
4884 + printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
4886 + spin_unlock(&jffs2_compressor_list_lock);
4890 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
4892 - if (orig != comprbuf)
4894 + if (orig != comprbuf)
4898 int __init jffs2_compressors_init(void)
4900 /* Registering compressors */
4901 #ifdef CONFIG_JFFS2_ZLIB
4902 - jffs2_zlib_init();
4903 + jffs2_zlib_init();
4905 #ifdef CONFIG_JFFS2_RTIME
4906 - jffs2_rtime_init();
4907 + jffs2_rtime_init();
4909 #ifdef CONFIG_JFFS2_RUBIN
4910 - jffs2_rubinmips_init();
4911 - jffs2_dynrubin_init();
4912 + jffs2_rubinmips_init();
4913 + jffs2_dynrubin_init();
4915 /* Setting default compression mode */
4916 #ifdef CONFIG_JFFS2_CMODE_NONE
4917 - jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4918 - D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4919 + jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
4920 + D1(printk(KERN_INFO "JFFS2: default compression mode: none\n");)
4922 #ifdef CONFIG_JFFS2_CMODE_SIZE
4923 - jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4924 - D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4925 + jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
4926 + D1(printk(KERN_INFO "JFFS2: default compression mode: size\n");)
4928 - D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4929 + D1(printk(KERN_INFO "JFFS2: default compression mode: priority\n");)
4936 int jffs2_compressors_exit(void)
4938 /* Unregistering compressors */
4939 #ifdef CONFIG_JFFS2_RUBIN
4940 - jffs2_dynrubin_exit();
4941 - jffs2_rubinmips_exit();
4942 + jffs2_dynrubin_exit();
4943 + jffs2_rubinmips_exit();
4945 #ifdef CONFIG_JFFS2_RTIME
4946 - jffs2_rtime_exit();
4947 + jffs2_rtime_exit();
4949 #ifdef CONFIG_JFFS2_ZLIB
4950 - jffs2_zlib_exit();
4951 + jffs2_zlib_exit();
4956 Index: linux-2.6.23.17/fs/jffs2/compr.h
4957 ===================================================================
4958 --- linux-2.6.23.17.orig/fs/jffs2/compr.h
4959 +++ linux-2.6.23.17/fs/jffs2/compr.h
4961 * JFFS2 -- Journalling Flash File System, Version 2.
4963 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
4964 - * University of Szeged, Hungary
4965 + * University of Szeged, Hungary
4967 * For licensing information, see the file 'LICENCE' in this directory.
4970 #define JFFS2_ZLIB_PRIORITY 60
4972 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
4973 -#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4974 +#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
4976 #define JFFS2_COMPR_MODE_NONE 0
4977 #define JFFS2_COMPR_MODE_PRIORITY 1
4978 #define JFFS2_COMPR_MODE_SIZE 2
4980 struct jffs2_compressor {
4981 - struct list_head list;
4982 - int priority; /* used by prirority comr. mode */
4984 - char compr; /* JFFS2_COMPR_XXX */
4985 - int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
4986 - uint32_t *srclen, uint32_t *destlen, void *model);
4987 - int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
4988 - uint32_t cdatalen, uint32_t datalen, void *model);
4990 - int disabled; /* if seted the compressor won't compress */
4991 - unsigned char *compr_buf; /* used by size compr. mode */
4992 - uint32_t compr_buf_size; /* used by size compr. mode */
4993 - uint32_t stat_compr_orig_size;
4994 - uint32_t stat_compr_new_size;
4995 - uint32_t stat_compr_blocks;
4996 - uint32_t stat_decompr_blocks;
4997 + struct list_head list;
4998 + int priority; /* used by prirority comr. mode */
5000 + char compr; /* JFFS2_COMPR_XXX */
5001 + int (*compress)(unsigned char *data_in, unsigned char *cpage_out,
5002 + uint32_t *srclen, uint32_t *destlen, void *model);
5003 + int (*decompress)(unsigned char *cdata_in, unsigned char *data_out,
5004 + uint32_t cdatalen, uint32_t datalen, void *model);
5006 + int disabled; /* if set the compressor won't compress */
5007 + unsigned char *compr_buf; /* used by size compr. mode */
5008 + uint32_t compr_buf_size; /* used by size compr. mode */
5009 + uint32_t stat_compr_orig_size;
5010 + uint32_t stat_compr_new_size;
5011 + uint32_t stat_compr_blocks;
5012 + uint32_t stat_decompr_blocks;
5015 int jffs2_register_compressor(struct jffs2_compressor *comp);
5016 @@ -64,12 +64,12 @@ int jffs2_compressors_init(void);
5017 int jffs2_compressors_exit(void);
5019 uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5020 - unsigned char *data_in, unsigned char **cpage_out,
5021 - uint32_t *datalen, uint32_t *cdatalen);
5022 + unsigned char *data_in, unsigned char **cpage_out,
5023 + uint32_t *datalen, uint32_t *cdatalen);
5025 int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
5026 - uint16_t comprtype, unsigned char *cdata_in,
5027 - unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5028 + uint16_t comprtype, unsigned char *cdata_in,
5029 + unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
5031 void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
5033 Index: linux-2.6.23.17/fs/jffs2/compr_rtime.c
5034 ===================================================================
5035 --- linux-2.6.23.17.orig/fs/jffs2/compr_rtime.c
5036 +++ linux-2.6.23.17/fs/jffs2/compr_rtime.c
5037 @@ -104,7 +104,7 @@ static int jffs2_rtime_decompress(unsign
5045 static struct jffs2_compressor jffs2_rtime_comp = {
5046 Index: linux-2.6.23.17/fs/jffs2/compr_rubin.c
5047 ===================================================================
5048 --- linux-2.6.23.17.orig/fs/jffs2/compr_rubin.c
5049 +++ linux-2.6.23.17/fs/jffs2/compr_rubin.c
5050 @@ -384,7 +384,7 @@ static int jffs2_rubinmips_decompress(un
5053 rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen);
5058 static int jffs2_dynrubin_decompress(unsigned char *data_in,
5059 @@ -399,7 +399,7 @@ static int jffs2_dynrubin_decompress(uns
5060 bits[c] = data_in[c];
5062 rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8, dstlen);
5067 static struct jffs2_compressor jffs2_rubinmips_comp = {
5068 Index: linux-2.6.23.17/fs/jffs2/compr_zlib.c
5069 ===================================================================
5070 --- linux-2.6.23.17.orig/fs/jffs2/compr_zlib.c
5071 +++ linux-2.6.23.17/fs/jffs2/compr_zlib.c
5072 @@ -181,7 +181,7 @@ static int jffs2_zlib_decompress(unsigne
5074 zlib_inflateEnd(&inf_strm);
5075 mutex_unlock(&inflate_mutex);
5080 static struct jffs2_compressor jffs2_zlib_comp = {
5081 @@ -203,11 +203,11 @@ int __init jffs2_zlib_init(void)
5083 ret = alloc_workspaces();
5088 ret = jffs2_register_compressor(&jffs2_zlib_comp);
5090 - free_workspaces();
5091 + free_workspaces();
5095 Index: linux-2.6.23.17/fs/jffs2/dir.c
5096 ===================================================================
5097 --- linux-2.6.23.17.orig/fs/jffs2/dir.c
5098 +++ linux-2.6.23.17/fs/jffs2/dir.c
5099 @@ -32,7 +32,7 @@ static int jffs2_mkdir (struct inode *,s
5100 static int jffs2_rmdir (struct inode *,struct dentry *);
5101 static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t);
5102 static int jffs2_rename (struct inode *, struct dentry *,
5103 - struct inode *, struct dentry *);
5104 + struct inode *, struct dentry *);
5106 const struct file_operations jffs2_dir_operations =
5108 @@ -770,7 +770,7 @@ static int jffs2_mknod (struct inode *di
5111 static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
5112 - struct inode *new_dir_i, struct dentry *new_dentry)
5113 + struct inode *new_dir_i, struct dentry *new_dentry)
5116 struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
5117 Index: linux-2.6.23.17/fs/jffs2/erase.c
5118 ===================================================================
5119 --- linux-2.6.23.17.orig/fs/jffs2/erase.c
5120 +++ linux-2.6.23.17/fs/jffs2/erase.c
5121 @@ -38,8 +38,8 @@ static void jffs2_erase_block(struct jff
5123 ret = jffs2_flash_erase(c, jeb);
5125 - jffs2_erase_succeeded(c, jeb);
5127 + jffs2_erase_succeeded(c, jeb);
5130 bad_offset = jeb->offset;
5132 @@ -50,12 +50,14 @@ static void jffs2_erase_block(struct jff
5133 instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
5135 printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
5136 + down(&c->erase_free_sem);
5137 spin_lock(&c->erase_completion_lock);
5138 list_move(&jeb->list, &c->erase_pending_list);
5139 c->erasing_size -= c->sector_size;
5140 c->dirty_size += c->sector_size;
5141 jeb->dirty_size = c->sector_size;
5142 spin_unlock(&c->erase_completion_lock);
5143 + up(&c->erase_free_sem);
5147 @@ -82,12 +84,14 @@ static void jffs2_erase_block(struct jff
5148 if (ret == -ENOMEM || ret == -EAGAIN) {
5149 /* Erase failed immediately. Refile it on the list */
5150 D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
5151 + down(&c->erase_free_sem);
5152 spin_lock(&c->erase_completion_lock);
5153 list_move(&jeb->list, &c->erase_pending_list);
5154 c->erasing_size -= c->sector_size;
5155 c->dirty_size += c->sector_size;
5156 jeb->dirty_size = c->sector_size;
5157 spin_unlock(&c->erase_completion_lock);
5158 + up(&c->erase_free_sem);
5162 @@ -114,6 +118,7 @@ void jffs2_erase_pending_blocks(struct j
5163 jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
5164 list_del(&jeb->list);
5165 spin_unlock(&c->erase_completion_lock);
5166 + up(&c->erase_free_sem);
5167 jffs2_mark_erased_block(c, jeb);
5170 @@ -134,6 +139,7 @@ void jffs2_erase_pending_blocks(struct j
5171 jffs2_free_jeb_node_refs(c, jeb);
5172 list_add(&jeb->list, &c->erasing_list);
5173 spin_unlock(&c->erase_completion_lock);
5174 + up(&c->erase_free_sem);
5176 jffs2_erase_block(c, jeb);
5178 @@ -142,23 +148,25 @@ void jffs2_erase_pending_blocks(struct j
5184 + down(&c->erase_free_sem);
5185 spin_lock(&c->erase_completion_lock);
5188 spin_unlock(&c->erase_completion_lock);
5189 + up(&c->erase_free_sem);
5191 D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
5193 - up(&c->erase_free_sem);
5196 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
5198 D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
5199 + down(&c->erase_free_sem);
5200 spin_lock(&c->erase_completion_lock);
5201 list_move_tail(&jeb->list, &c->erase_complete_list);
5202 spin_unlock(&c->erase_completion_lock);
5203 + up(&c->erase_free_sem);
5204 /* Ensure that kupdated calls us again to mark them clean */
5205 jffs2_erase_pending_trigger(c);
5207 @@ -172,22 +180,26 @@ static void jffs2_erase_failed(struct jf
5208 failed too many times. */
5209 if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
5210 /* We'd like to give this block another try. */
5211 + down(&c->erase_free_sem);
5212 spin_lock(&c->erase_completion_lock);
5213 list_move(&jeb->list, &c->erase_pending_list);
5214 c->erasing_size -= c->sector_size;
5215 c->dirty_size += c->sector_size;
5216 jeb->dirty_size = c->sector_size;
5217 spin_unlock(&c->erase_completion_lock);
5218 + up(&c->erase_free_sem);
5223 + down(&c->erase_free_sem);
5224 spin_lock(&c->erase_completion_lock);
5225 c->erasing_size -= c->sector_size;
5226 c->bad_size += c->sector_size;
5227 list_move(&jeb->list, &c->bad_list);
5228 c->nr_erasing_blocks--;
5229 spin_unlock(&c->erase_completion_lock);
5230 + up(&c->erase_free_sem);
5231 wake_up(&c->erase_wait);
5234 @@ -317,6 +329,33 @@ static int jffs2_block_check_erase(struc
5238 + if (c->mtd->point) {
5239 + unsigned long *wordebuf;
5241 + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf);
5243 + D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
5244 + goto do_flash_read;
5246 + if (retlen < c->sector_size) {
5247 + /* Don't muck about if it won't let us point to the whole erase sector */
5248 + D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen));
5249 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5250 + goto do_flash_read;
5252 + wordebuf = ebuf-sizeof(*wordebuf);
5253 + retlen /= sizeof(*wordebuf);
5255 + if (*++wordebuf != ~0)
5257 + } while(--retlen);
5258 + c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size);
5260 + printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n",
5261 + *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
5265 ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
5267 printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset);
5268 @@ -417,6 +456,7 @@ static void jffs2_mark_erased_block(stru
5269 jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
5272 + down(&c->erase_free_sem);
5273 spin_lock(&c->erase_completion_lock);
5274 c->erasing_size -= c->sector_size;
5275 c->free_size += jeb->free_size;
5276 @@ -429,23 +469,28 @@ static void jffs2_mark_erased_block(stru
5277 c->nr_erasing_blocks--;
5278 c->nr_free_blocks++;
5279 spin_unlock(&c->erase_completion_lock);
5280 + up(&c->erase_free_sem);
5281 wake_up(&c->erase_wait);
5285 + down(&c->erase_free_sem);
5286 spin_lock(&c->erase_completion_lock);
5287 /* Stick it on a list (any list) so erase_failed can take it
5288 right off again. Silly, but shouldn't happen often. */
5289 list_add(&jeb->list, &c->erasing_list);
5290 spin_unlock(&c->erase_completion_lock);
5291 + up(&c->erase_free_sem);
5292 jffs2_erase_failed(c, jeb, bad_offset);
5296 /* Stick it back on the list from whence it came and come back later */
5297 jffs2_erase_pending_trigger(c);
5298 + down(&c->erase_free_sem);
5299 spin_lock(&c->erase_completion_lock);
5300 list_add(&jeb->list, &c->erase_complete_list);
5301 spin_unlock(&c->erase_completion_lock);
5302 + up(&c->erase_free_sem);
5305 Index: linux-2.6.23.17/fs/jffs2/gc.c
5306 ===================================================================
5307 --- linux-2.6.23.17.orig/fs/jffs2/gc.c
5308 +++ linux-2.6.23.17/fs/jffs2/gc.c
5309 @@ -556,7 +556,7 @@ static int jffs2_garbage_collect_pristin
5311 node = kmalloc(rawlen, GFP_KERNEL);
5316 ret = jffs2_flash_read(c, ref_offset(raw), rawlen, &retlen, (char *)node);
5317 if (!ret && retlen != rawlen)
5318 @@ -624,7 +624,7 @@ static int jffs2_garbage_collect_pristin
5320 if (ret || (retlen != rawlen)) {
5321 printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
5322 - rawlen, phys_ofs, ret, retlen);
5323 + rawlen, phys_ofs, ret, retlen);
5325 jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
5327 Index: linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
5328 ===================================================================
5329 --- linux-2.6.23.17.orig/fs/jffs2/jffs2_fs_sb.h
5330 +++ linux-2.6.23.17/fs/jffs2/jffs2_fs_sb.h
5331 @@ -106,6 +106,9 @@ struct jffs2_sb_info {
5333 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
5335 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5336 + unsigned char *wbuf_verify; /* read-back buffer for verification */
5338 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
5339 unsigned char *wbuf; /* Write-behind buffer for NAND flash */
5341 Index: linux-2.6.23.17/fs/jffs2/nodelist.h
5342 ===================================================================
5343 --- linux-2.6.23.17.orig/fs/jffs2/nodelist.h
5344 +++ linux-2.6.23.17/fs/jffs2/nodelist.h
5345 @@ -127,7 +127,7 @@ static inline struct jffs2_inode_cache *
5346 return ((struct jffs2_inode_cache *)raw);
5349 - /* flash_offset & 3 always has to be zero, because nodes are
5350 + /* flash_offset & 3 always has to be zero, because nodes are
5351 always aligned at 4 bytes. So we have a couple of extra bits
5352 to play with, which indicate the node's status; see below: */
5353 #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
5354 @@ -197,7 +197,7 @@ struct jffs2_inode_cache {
5355 #define RAWNODE_CLASS_XATTR_DATUM 1
5356 #define RAWNODE_CLASS_XATTR_REF 2
5358 -#define INOCACHE_HASHSIZE 128
5359 +#define INOCACHE_HASHSIZE 1024
5361 #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
5363 Index: linux-2.6.23.17/fs/jffs2/nodemgmt.c
5364 ===================================================================
5365 --- linux-2.6.23.17.orig/fs/jffs2/nodemgmt.c
5366 +++ linux-2.6.23.17/fs/jffs2/nodemgmt.c
5367 @@ -154,7 +154,7 @@ int jffs2_reserve_space_gc(struct jffs2_
5368 while(ret == -EAGAIN) {
5369 ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
5371 - D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5372 + D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
5375 spin_unlock(&c->erase_completion_lock);
5376 @@ -423,7 +423,12 @@ struct jffs2_raw_node_ref *jffs2_add_phy
5377 even after refiling c->nextblock */
5378 if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
5379 && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
5380 - printk(KERN_WARNING "argh. node added in wrong place\n");
5381 + printk(KERN_WARNING "argh. node added in wrong place at 0x%08x(%d)\n", ofs & ~3, ofs & 3);
5383 + printk(KERN_WARNING "nextblock 0x%08x", c->nextblock->offset);
5385 + printk(KERN_WARNING "No nextblock");
5386 + printk(", expected at %08x\n", jeb->offset + (c->sector_size - jeb->free_size));
5387 return ERR_PTR(-EINVAL);
5390 Index: linux-2.6.23.17/fs/jffs2/readinode.c
5391 ===================================================================
5392 --- linux-2.6.23.17.orig/fs/jffs2/readinode.c
5393 +++ linux-2.6.23.17/fs/jffs2/readinode.c
5394 @@ -211,7 +211,7 @@ static void jffs2_kill_tn(struct jffs2_s
5397 * Returns 0 if the node was handled (including marking it obsolete)
5398 - * < 0 an if error occurred
5399 + * < 0 an if error occurred
5401 static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c,
5402 struct jffs2_readinode_info *rii,
5403 @@ -862,8 +862,8 @@ static inline int read_unknown(struct jf
5404 JFFS2_ERROR("REF_UNCHECKED but unknown node at %#08x\n",
5406 JFFS2_ERROR("Node is {%04x,%04x,%08x,%08x}. Please report this error.\n",
5407 - je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5408 - je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5409 + je16_to_cpu(un->magic), je16_to_cpu(un->nodetype),
5410 + je32_to_cpu(un->totlen), je32_to_cpu(un->hdr_crc));
5411 jffs2_mark_node_obsolete(c, ref);
5414 Index: linux-2.6.23.17/fs/jffs2/scan.c
5415 ===================================================================
5416 --- linux-2.6.23.17.orig/fs/jffs2/scan.c
5417 +++ linux-2.6.23.17/fs/jffs2/scan.c
5418 @@ -877,7 +877,7 @@ scan_more:
5419 switch (je16_to_cpu(node->nodetype) & JFFS2_COMPAT_MASK) {
5420 case JFFS2_FEATURE_ROCOMPAT:
5421 printk(KERN_NOTICE "Read-only compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs);
5422 - c->flags |= JFFS2_SB_FLAG_RO;
5423 + c->flags |= JFFS2_SB_FLAG_RO;
5424 if (!(jffs2_is_readonly(c)))
5426 if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
5427 Index: linux-2.6.23.17/fs/jffs2/security.c
5428 ===================================================================
5429 --- linux-2.6.23.17.orig/fs/jffs2/security.c
5430 +++ linux-2.6.23.17/fs/jffs2/security.c
5431 @@ -38,9 +38,9 @@ int jffs2_init_security(struct inode *in
5433 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
5443 /* ---- XATTR Handler for "security.*" ----------------- */
5444 Index: linux-2.6.23.17/fs/jffs2/summary.c
5445 ===================================================================
5446 --- linux-2.6.23.17.orig/fs/jffs2/summary.c
5447 +++ linux-2.6.23.17/fs/jffs2/summary.c
5449 * JFFS2 -- Journalling Flash File System, Version 2.
5451 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5452 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5453 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5454 - * University of Szeged, Hungary
5455 - * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5456 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5457 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5458 + * University of Szeged, Hungary
5459 + * 2006 KaiGai Kohei <kaigai@ak.jp.nec.com>
5461 * For licensing information, see the file 'LICENCE' in this directory.
5463 Index: linux-2.6.23.17/fs/jffs2/summary.h
5464 ===================================================================
5465 --- linux-2.6.23.17.orig/fs/jffs2/summary.h
5466 +++ linux-2.6.23.17/fs/jffs2/summary.h
5468 * JFFS2 -- Journalling Flash File System, Version 2.
5470 * Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
5471 - * Zoltan Sogor <weth@inf.u-szeged.hu>,
5472 - * Patrik Kluba <pajko@halom.u-szeged.hu>,
5473 - * University of Szeged, Hungary
5474 + * Zoltan Sogor <weth@inf.u-szeged.hu>,
5475 + * Patrik Kluba <pajko@halom.u-szeged.hu>,
5476 + * University of Szeged, Hungary
5478 * For licensing information, see the file 'LICENCE' in this directory.
5480 Index: linux-2.6.23.17/fs/jffs2/wbuf.c
5481 ===================================================================
5482 --- linux-2.6.23.17.orig/fs/jffs2/wbuf.c
5483 +++ linux-2.6.23.17/fs/jffs2/wbuf.c
5484 @@ -220,6 +220,47 @@ static struct jffs2_raw_node_ref **jffs2
5488 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5489 +static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
5496 + ret = c->mtd->read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
5497 + if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
5498 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x failed: %d\n", c->wbuf_ofs, ret);
5500 + } else if (retlen != c->wbuf_pagesize) {
5501 + printk(KERN_WARNING "jffs2_verify_write(): Read back of page at %08x gave short read: %zd not %d.\n", ofs, retlen, c->wbuf_pagesize);
5504 + if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
5507 + if (ret == -EUCLEAN)
5508 + eccstr = "corrected";
5509 + else if (ret == -EBADMSG)
5510 + eccstr = "correction failed";
5512 + eccstr = "OK or unused";
5514 + printk(KERN_WARNING "Write verify error (ECC %s) at %08x. Wrote:\n",
5515 + eccstr, c->wbuf_ofs);
5516 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5517 + c->wbuf, c->wbuf_pagesize, 0);
5519 + printk(KERN_WARNING "Read back:\n");
5520 + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
5521 + c->wbuf_verify, c->wbuf_pagesize, 0);
5526 +#define jffs2_verify_write(c,b,o) (0)
5529 /* Recover from failure to write wbuf. Recover the nodes up to the
5530 * wbuf, not the one which we were starting to try to write. */
5532 @@ -380,7 +421,7 @@ static void jffs2_wbuf_recover(struct jf
5533 ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
5536 - if (ret || retlen != towrite) {
5537 + if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
5538 /* Argh. We tried. Really we did. */
5539 printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
5541 @@ -587,15 +628,16 @@ static int __jffs2_flush_wbuf(struct jff
5543 ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
5545 - if (ret || retlen != c->wbuf_pagesize) {
5547 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n",ret);
5549 - printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5550 - retlen, c->wbuf_pagesize);
5555 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write failed with %d\n", ret);
5557 + } else if (retlen != c->wbuf_pagesize) {
5558 + printk(KERN_WARNING "jffs2_flush_wbuf(): Write was short: %zd instead of %d\n",
5559 + retlen, c->wbuf_pagesize);
5562 + } else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
5564 jffs2_wbuf_recover(c);
5567 @@ -966,8 +1008,8 @@ exit:
5569 #define NR_OOB_SCAN_PAGES 4
5571 -/* For historical reasons we use only 12 bytes for OOB clean marker */
5572 -#define OOB_CM_SIZE 12
5573 +/* For historical reasons we use only 8 bytes for OOB clean marker */
5574 +#define OOB_CM_SIZE 8
5576 static const struct jffs2_unknown_node oob_cleanmarker =
5578 @@ -1021,8 +1063,8 @@ int jffs2_check_oob_empty(struct jffs2_s
5580 * Check for a valid cleanmarker.
5581 * Returns: 0 if a valid cleanmarker was found
5582 - * 1 if no cleanmarker was found
5583 - * negative error code if an error occurred
5584 + * 1 if no cleanmarker was found
5585 + * negative error code if an error occurred
5587 int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c,
5588 struct jffs2_eraseblock *jeb)
5589 @@ -1138,11 +1180,22 @@ int jffs2_nand_flash_setup(struct jffs2_
5593 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5594 + c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
5595 + if (!c->wbuf_verify) {
5604 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
5606 +#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
5607 + kfree(c->wbuf_verify);
5612 Index: linux-2.6.23.17/fs/jffs2/xattr.h
5613 ===================================================================
5614 --- linux-2.6.23.17.orig/fs/jffs2/xattr.h
5615 +++ linux-2.6.23.17/fs/jffs2/xattr.h
5616 @@ -75,7 +75,7 @@ extern void jffs2_build_xattr_subsystem(
5617 extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
5619 extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
5620 - uint32_t xid, uint32_t version);
5621 + uint32_t xid, uint32_t version);
5623 extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5624 extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
5625 Index: linux-2.6.23.17/fs/jffs2/xattr_user.c
5626 ===================================================================
5627 --- linux-2.6.23.17.orig/fs/jffs2/xattr_user.c
5628 +++ linux-2.6.23.17/fs/jffs2/xattr_user.c
5630 #include "nodelist.h"
5632 static int jffs2_user_getxattr(struct inode *inode, const char *name,
5633 - void *buffer, size_t size)
5634 + void *buffer, size_t size)
5636 if (!strcmp(name, ""))
5638 @@ -25,7 +25,7 @@ static int jffs2_user_getxattr(struct in
5641 static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
5642 - size_t size, int flags)
5643 + size_t size, int flags)
5645 if (!strcmp(name, ""))
5647 Index: linux-2.6.23.17/include/asm-i386/geode.h
5648 ===================================================================
5649 --- linux-2.6.23.17.orig/include/asm-i386/geode.h
5650 +++ linux-2.6.23.17/include/asm-i386/geode.h
5651 @@ -135,6 +135,55 @@ static inline void geode_gpio_event_pme(
5652 geode_gpio_setup_event(gpio, pair, 1);
5657 +#define MFGPT_TIMER_ANY -1
5659 +#define MFGPT_DOMAIN_WORKING 1
5660 +#define MFGPT_DOMAIN_STANDBY 2
5661 +#define MFGPT_DOMAIN_ANY (MFGPT_DOMAIN_WORKING | MFGPT_DOMAIN_STANDBY)
5663 +#define MFGPT_CMP1 0
5664 +#define MFGPT_CMP2 1
5666 +#define MFGPT_EVENT_IRQ 0
5667 +#define MFGPT_EVENT_NMI 1
5668 +#define MFGPT_EVENT_RESET 3
5670 +#define MFGPT_REG_CMP1 0
5671 +#define MFGPT_REG_CMP2 2
5672 +#define MFGPT_REG_COUNTER 4
5673 +#define MFGPT_REG_SETUP 6
5675 +#define MFGPT_SETUP_CNTEN (1 << 15)
5676 +#define MFGPT_SETUP_CMP2 (1 << 14)
5677 +#define MFGPT_SETUP_CMP1 (1 << 13)
5678 +#define MFGPT_SETUP_SETUP (1 << 12)
5679 +#define MFGPT_SETUP_STOPEN (1 << 11)
5680 +#define MFGPT_SETUP_EXTEN (1 << 10)
5681 +#define MFGPT_SETUP_REVEN (1 << 5)
5682 +#define MFGPT_SETUP_CLKSEL (1 << 4)
5684 +static inline void geode_mfgpt_write(int timer, u16 reg, u16 value)
5686 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5687 + outw(value, base + reg + (timer * 8));
5690 +static inline u16 geode_mfgpt_read(int timer, u16 reg)
5692 + u32 base = geode_get_dev_base(GEODE_DEV_MFGPT);
5693 + return inw(base + reg + (timer * 8));
5696 +extern int __init geode_mfgpt_detect(void);
5697 +extern int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable);
5698 +extern int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable);
5699 +extern int geode_mfgpt_alloc_timer(int timer, int domain, struct module *owner);
5701 +#define geode_mfgpt_setup_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),1)
5702 +#define geode_mfgpt_release_irq(t,c,i) geode_mfgpt_set_irq((t),(c),(i),0)
5704 /* Specific geode tests */
5706 static inline int is_geode_gx(void)
5707 Index: linux-2.6.23.17/include/asm-i386/setup.h
5708 ===================================================================
5709 --- linux-2.6.23.17.orig/include/asm-i386/setup.h
5710 +++ linux-2.6.23.17/include/asm-i386/setup.h
5712 #define OLD_CL_BASE_ADDR 0x90000
5713 #define OLD_CL_OFFSET 0x90022
5714 #define NEW_CL_POINTER 0x228 /* Relative to real mode data */
5715 +#define OFW_INFO_OFFSET 0xb0 /* Relative to real mode data */
5717 #ifndef __ASSEMBLY__
5719 Index: linux-2.6.23.17/include/linux/console.h
5720 ===================================================================
5721 --- linux-2.6.23.17.orig/include/linux/console.h
5722 +++ linux-2.6.23.17/include/linux/console.h
5723 @@ -121,14 +121,11 @@ extern void console_stop(struct console
5724 extern void console_start(struct console *);
5725 extern int is_console_locked(void);
5727 -#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND
5728 +extern int serial_console_suspend_enabled;
5730 /* Suspend and resume console messages over PM events */
5731 extern void suspend_console(void);
5732 extern void resume_console(void);
5734 -static inline void suspend_console(void) {}
5735 -static inline void resume_console(void) {}
5736 -#endif /* CONFIG_DISABLE_CONSOLE_SUSPEND */
5738 int mda_console_init(void);
5739 void prom_con_init(void);
5740 Index: linux-2.6.23.17/include/linux/fb.h
5741 ===================================================================
5742 --- linux-2.6.23.17.orig/include/linux/fb.h
5743 +++ linux-2.6.23.17/include/linux/fb.h
5744 @@ -664,6 +664,12 @@ struct fb_ops {
5745 /* restore saved state */
5746 void (*fb_restore_state)(struct fb_info *info);
5748 + /* Shut down the graphics engine to save power */
5749 + int (*fb_powerdown)(struct fb_info *info);
5751 + /* Power it back up */
5752 + int (*fb_powerup)(struct fb_info *info);
5754 /* get capability given var */
5755 void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
5756 struct fb_var_screeninfo *var);
5757 @@ -943,6 +949,9 @@ extern int fb_get_color_depth(struct fb_
5758 extern int fb_get_options(char *name, char **option);
5759 extern int fb_new_modelist(struct fb_info *info);
5761 +extern int fb_powerdown(struct fb_info *info);
5762 +extern int fb_powerup(struct fb_info *info);
5764 extern struct fb_info *registered_fb[FB_MAX];
5765 extern int num_registered_fb;
5766 extern struct class *fb_class;
5767 Index: linux-2.6.23.17/include/linux/mtd/onenand.h
5768 ===================================================================
5769 --- linux-2.6.23.17.orig/include/linux/mtd/onenand.h
5770 +++ linux-2.6.23.17/include/linux/mtd/onenand.h
5771 @@ -60,6 +60,7 @@ struct onenand_bufferram {
5772 * @erase_shift: [INTERN] number of address bits in a block
5773 * @page_shift: [INTERN] number of address bits in a page
5774 * @page_mask: [INTERN] a page per block mask
5775 + * @writesize: [INTERN] a real page size
5776 * @bufferram_index: [INTERN] BufferRAM index
5777 * @bufferram: [INTERN] BufferRAM info
5778 * @readw: [REPLACEABLE] hardware specific function for read short
5779 @@ -100,6 +101,7 @@ struct onenand_chip {
5780 unsigned int erase_shift;
5781 unsigned int page_shift;
5782 unsigned int page_mask;
5783 + unsigned int writesize;
5785 unsigned int bufferram_index;
5786 struct onenand_bufferram bufferram[MAX_BUFFERRAM];
5787 @@ -140,6 +142,8 @@ struct onenand_chip {
5788 #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)
5789 #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)
5790 #define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)
5791 +#define ONENAND_SET_BUFFERRAM0(this) (this->bufferram_index = 0)
5792 +#define ONENAND_SET_BUFFERRAM1(this) (this->bufferram_index = 1)
5794 #define ONENAND_GET_SYS_CFG1(this) \
5795 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))
5796 @@ -149,6 +153,13 @@ struct onenand_chip {
5797 #define ONENAND_IS_DDP(this) \
5798 (this->device_id & ONENAND_DEVICE_IS_DDP)
5800 +#ifdef CONFIG_MTD_ONENAND_2X_PROGRAM
5801 +#define ONENAND_IS_2PLANE(this) \
5802 + (this->options & ONENAND_HAS_2PLANE)
5804 +#define ONENAND_IS_2PLANE(this) (0)
5807 /* Check byte access in OneNAND */
5808 #define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
5810 @@ -157,6 +168,7 @@ struct onenand_chip {
5812 #define ONENAND_HAS_CONT_LOCK (0x0001)
5813 #define ONENAND_HAS_UNLOCK_ALL (0x0002)
5814 +#define ONENAND_HAS_2PLANE (0x0004)
5815 #define ONENAND_PAGEBUF_ALLOC (0x1000)
5816 #define ONENAND_OOBBUF_ALLOC (0x2000)
5818 Index: linux-2.6.23.17/include/linux/mtd/onenand_regs.h
5819 ===================================================================
5820 --- linux-2.6.23.17.orig/include/linux/mtd/onenand_regs.h
5821 +++ linux-2.6.23.17/include/linux/mtd/onenand_regs.h
5824 #define ONENAND_DEVICE_DENSITY_512Mb (0x002)
5825 #define ONENAND_DEVICE_DENSITY_1Gb (0x003)
5826 +#define ONENAND_DEVICE_DENSITY_2Gb (0x004)
5827 +#define ONENAND_DEVICE_DENSITY_4Gb (0x005)
5830 * Version ID Register F002h (R)
5832 #define ONENAND_CMD_READOOB (0x13)
5833 #define ONENAND_CMD_PROG (0x80)
5834 #define ONENAND_CMD_PROGOOB (0x1A)
5835 +#define ONENAND_CMD_2X_PROG (0x7D)
5836 +#define ONENAND_CMD_2X_CACHE_PROG (0x7F)
5837 #define ONENAND_CMD_UNLOCK (0x23)
5838 #define ONENAND_CMD_LOCK (0x2A)
5839 #define ONENAND_CMD_LOCK_TIGHT (0x2C)
5840 Index: linux-2.6.23.17/include/linux/vt_kern.h
5841 ===================================================================
5842 --- linux-2.6.23.17.orig/include/linux/vt_kern.h
5843 +++ linux-2.6.23.17/include/linux/vt_kern.h
5844 @@ -95,4 +95,23 @@ struct vt_spawn_console {
5846 extern struct vt_spawn_console vt_spawn_con;
5848 +/* A notifier list for console events */
5849 +extern struct raw_notifier_head console_notifier_list;
5851 +/* Called when the FG console switches to KD_TEXT mode */
5852 +#define CONSOLE_EVENT_SWITCH_TEXT 0x01
5854 +/* Called when the FG console switches to KD_GRAPHICS mode */
5855 +#define CONSOLE_EVENT_SWITCH_GRAPHICS 0x02
5857 +static inline int console_event_register(struct notifier_block *n)
5859 + return raw_notifier_chain_register(&console_notifier_list, n);
5862 +static inline int console_event_unregister(struct notifier_block *n)
5864 + return raw_notifier_chain_unregister(&console_notifier_list, n);
5867 #endif /* _VT_KERN_H */
5868 Index: linux-2.6.23.17/kernel/power/console.c
5869 ===================================================================
5870 --- linux-2.6.23.17.orig/kernel/power/console.c
5871 +++ linux-2.6.23.17/kernel/power/console.c
5873 #include <linux/console.h>
5876 -#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE)
5877 +#if defined(CONFIG_VT) && defined(CONFIG_VT_CONSOLE) && !defined(CONFIG_DISABLE_SUSPEND_VT_SWITCH)
5878 #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
5880 static int orig_fgconsole, orig_kmsg;