patch-2.4.0-test11 linux/drivers/macintosh/via-pmu.c
Next file: linux/drivers/md/lvm.c
Previous file: linux/drivers/isdn/sc/debug.c
Back to the patch index
Back to the overall index
- Lines: 198
- Date:
Sat Nov 11 18:19:56 2000
- Orig file:
v2.4.0-test10/linux/drivers/macintosh/via-pmu.c
- Orig date:
Sun Oct 8 10:50:18 2000
diff -u --recursive --new-file v2.4.0-test10/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
@@ -1296,6 +1296,33 @@
* Put the powerbook to sleep.
*/
+static u32 save_via[8];
+static void save_via_state(void)
+{
+ save_via[0] = in_8(&via[ANH]);
+ save_via[1] = in_8(&via[DIRA]);
+ save_via[2] = in_8(&via[B]);
+ save_via[3] = in_8(&via[DIRB]);
+ save_via[4] = in_8(&via[PCR]);
+ save_via[5] = in_8(&via[ACR]);
+ save_via[6] = in_8(&via[T1CL]);
+ save_via[7] = in_8(&via[T1CH]);
+}
+static void restore_via_state(void)
+{
+ out_8(&via[ANH], save_via[0]);
+ out_8(&via[DIRA], save_via[1]);
+ out_8(&via[B], save_via[2]);
+ out_8(&via[DIRB], save_via[3]);
+ out_8(&via[PCR], save_via[4]);
+ out_8(&via[ACR], save_via[5]);
+ out_8(&via[T1CL], save_via[6]);
+ out_8(&via[T1CH], save_via[7]);
+ out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */
+ out_8(&via[IFR], 0x7f); /* clear IFR */
+ out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
+}
+
#define FEATURE_CTRL(base) ((unsigned int *)(base + 0x38))
#define GRACKLE_PM (1<<7)
#define GRACKLE_DOZE (1<<5)
@@ -1304,11 +1331,11 @@
int __openfirmware powerbook_sleep_G3(void)
{
- int ret;
unsigned long save_l2cr;
unsigned long wait;
unsigned short pmcr1;
struct adb_request req;
+ int ret, timeout;
/* Notify device drivers */
ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
@@ -1333,24 +1360,54 @@
}
/* Give the disks a little time to actually finish writing */
- for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
+ for (wait = jiffies + (HZ/2); time_before(jiffies, wait); )
mb();
+ /* Wait for completion of async backlight requests */
+ while (!bright_req_1.complete || !bright_req_2.complete || !bright_req_3.complete)
+ pmu_poll();
+
+ /* Turn off various things. Darwin does some retry tests here... */
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE);
+ while (!req.complete)
+ pmu_poll();
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY);
+ while (!req.complete)
+ pmu_poll();
+
/* Disable all interrupts except pmu */
sleep_save_intrs(vias->intrs[0].line);
+ /* Make sure the PMU is idle */
+ while (pmu_state != idle)
+ pmu_poll();
+
/* Make sure the decrementer won't interrupt us */
asm volatile("mtdec %0" : : "r" (0x7fffffff));
-
- feature_prepare_for_sleep();
+ /* Make sure any pending DEC interrupt occuring while we did
+ * the above didn't re-enable the DEC */
+ mb();
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
+ /* Giveup the FPU */
+ if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
+ giveup_fpu(current);
/* For 750, save backside cache setting and disable it */
save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */
if (save_l2cr)
_set_L2CR(0);
- if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
- giveup_fpu(current);
+ /* Ask the PMU to put us to sleep */
+ pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
+ while (!req.complete)
+ pmu_poll();
+
+ /* The VIA is supposed not to be restored correctly*/
+ save_via_state();
+ /* We shut down some HW */
+ feature_prepare_for_sleep();
grackle_pcibios_read_config_word(0,0,0x70,&pmcr1);
/* Apparently, MacOS uses NAP mode for Grackle ??? */
@@ -1358,15 +1415,6 @@
pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
- /* Ask the PMU to put us to sleep */
- pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
- while (!req.complete)
- pmu_poll();
-
- cli();
- while (pmu_state != idle)
- pmu_poll();
-
/* Call low-level ASM sleep handler */
low_sleep_handler();
@@ -1374,33 +1422,54 @@
grackle_pcibios_read_config_word(0, 0, 0x70, &pmcr1);
pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP);
grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
-
- /* Make sure the PMU is idle */
- while (pmu_state != idle)
- pmu_poll();
-
- sti();
-
+
+ /* Restore things */
feature_wake_up();
-
- /* The PGD is only a placeholder until Dan finds a way to make
- * this work properly on the 8xx processors. It is only used on
- * 8xx processors, it is ignored here.
- */
- set_context(current->mm->context, current->mm->pgd);
-
+ restore_via_state();
+
/* Restore L2 cache */
if (save_l2cr)
- _set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */
+ _set_L2CR(save_l2cr);
+
+ /* Restore userland MMU context */
+ set_context(current->mm->context, current->mm->pgd);
- /* reenable interrupts */
- sleep_restore_intrs();
+ /* Re-enable DEC interrupts and kick DEC */
+ asm volatile("mtdec %0" : : "r" (0x7fffffff));
+ sti();
+ asm volatile("mtdec %0" : : "r" (0x10000000));
- /* Tell PMU we are ready */
- pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2);
+ /* Power things up */
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc);
+ while (!req.complete)
+ pmu_poll();
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL0,
+ PMU_POW0_ON|PMU_POW0_HARD_DRIVE);
+ while (!req.complete)
+ pmu_poll();
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY);
while (!req.complete)
pmu_poll();
-
+
+ /* ack all pending interrupts */
+ timeout = 100000;
+ interrupt_data[0] = 1;
+ while (interrupt_data[0] || pmu_state != idle) {
+ if (--timeout < 0)
+ break;
+ if (pmu_state == idle)
+ adb_int_pending = 1;
+ via_pmu_interrupt(0, 0, 0);
+ udelay(10);
+ }
+
+ /* reenable interrupt controller */
+ sleep_restore_intrs();
+
+ /* Leave some time for HW to settle down */
+ mdelay(100);
+
/* Notify drivers */
mdelay(10);
broadcast_wake();
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)