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