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