cpufreq Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafał Bilski" <rafalbilski@interia.pl>
To: cpufreq@lists.linux.org.uk
Subject: Longhaul - patch proposal
Date: Fri, 12 May 2006 22:37:14 +0200	[thread overview]
Message-ID: <4464F1FA.4010304@interia.pl> (raw)

[-- Attachment #1: Type: text/plain, Size: 241 bytes --]

Sorry. Bad English inside.
Idea is simple - write ide suspend which waits for end of DMA transfer.



----------------------------------------------------------------------
Poznaj Stefana! Zmien komunikator! >>> http://link.interia.pl/f1924

[-- Attachment #2: longhaul.patch --]
[-- Type: text/plain, Size: 5812 bytes --]

--- longhaul.orig.c	2006-03-20 06:53:29.000000000 +0100
+++ longhaul.c	2006-05-12 22:05:08.000000000 +0200
@@ -30,6 +30,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pci.h>
+#include <linux/pm.h>
 
 #include <asm/msr.h>
 #include <asm/timex.h>
@@ -114,17 +115,114 @@
 	return eblcr_table[invalue];
 }
 
+/* This is copy from pci.c and pci-driver.c
+ * Better export this functions there 
+ */
 
-static void do_powersaver(union msr_longhaul *longhaul,
-			unsigned int clock_ratio_index)
+static void goto_sleep_pci(void)
 {
 	struct pci_dev *dev;
+	struct pci_driver *drv;
+	struct pm_message pm_freeze;
+	u16 pci_command;
+
+	/*
+	 * Get current pci bus master state for all devices
+	 * and clear bus master bit
+	 */
+
+	pm_freeze.event = PM_EVENT_FREEZE;
+	dev = NULL;
+	do {
+		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+		if (dev != NULL) {
+			drv = dev->driver;
+			if (drv && drv->suspend)
+				drv->suspend(dev, pm_freeze);
+			else
+	    			pci_save_state(dev);
+			pci_read_config_word(dev, PCI_COMMAND, &pci_command);
+			if (pci_command & PCI_COMMAND_MASTER) {
+				pci_command &= ~PCI_COMMAND_MASTER;
+				pci_write_config_word(dev, PCI_COMMAND, pci_command);
+			}
+			/* pcibios_disable_device omited because
+			   USB devices don't respond after resume
+			   on EPIA M10000 */
+		}
+	} while (dev != NULL);
+}
+
+static void wakeup_pci(void)
+{
+	struct pci_dev *dev;
+	struct pci_driver *drv;
+
+	/* Restore pci bus master state for all devices */
+
+	dev = NULL;
+	do {
+		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+		if (dev != NULL) {
+			drv = dev->driver;
+			if (drv && drv->resume)
+				drv->resume(dev);
+			else
+				/* restore the PCI config space */
+				pci_restore_state(dev);
+	    		/* if the device was busmaster before the suspend, make it busmaster again */
+			if (dev->is_busmaster)
+				pci_set_master(dev);
+			/* if the device was enabled before suspend, reenable */
+			if (dev->is_enabled)
+				pci_enable_device(dev);
+		}
+	} while (dev != NULL);
+}
+
+static void do_longhaul1(int reserved, unsigned int clock_ratio_index)
+{
 	unsigned long flags;
 	unsigned int tmp_mask;
+	union msr_bcr2 bcr2;
+
+	preempt_disable();
+	goto_sleep_pci();
+
+	local_irq_save(flags);
+
+	tmp_mask=inb(0x21);	/* works on C3. save mask. */
+	outb(0xFE, 0x21);	/* TMR0 only */
+
+	local_irq_disable();
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	/* Enable software clock multiplier */
+	bcr2.bits.ESOFTBF = 1;
+	bcr2.bits.CLOCKMUL = clock_ratio_index;
+	safe_halt();		/* Sync */
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);	/* Change */
+	halt();
+
+	/* Disable software clock multiplier */
+	local_irq_disable();
+	rdmsrl(MSR_VIA_BCR2, bcr2.val);
+	bcr2.bits.ESOFTBF = 0;
+	wrmsrl(MSR_VIA_BCR2, bcr2.val);
+	local_irq_enable();
+
+	outb(tmp_mask, 0x21);	/* restore mask */
+	local_irq_restore(flags);
+
+	wakeup_pci();
+	preempt_enable();
+}
+
+static void do_powersaver(union msr_longhaul *longhaul,
+			unsigned int clock_ratio_index)
+{
+	unsigned long flags;
+	unsigned int pic1_mask, pic2_mask;
 	int version;
-	int i;
-	u16 pci_cmd;
-	u16 cmd_state[64];
 
 	switch (cpu_model) {
 	case CPU_EZRA_T:
@@ -137,61 +235,40 @@
 		return;
 	}
 
+	preempt_disable();
+	goto_sleep_pci();
+
+	local_irq_save(flags);
+
+	pic2_mask=inb(0xA1);
+	pic1_mask=inb(0x21);	/* works on C3. save mask. */
+	outb(0xFF,0xA1);	/* Overkill */
+	outb(0xFE,0x21);	/* TMR0 only */
+
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
 	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
 	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
 	longhaul->bits.EnableSoftBusRatio = 1;
 	longhaul->bits.RevisionKey = 0;
 
-	preempt_disable();
-	local_irq_save(flags);
-
-	/*
-	 * get current pci bus master state for all devices
-	 * and clear bus master bit
-	 */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-			cmd_state[i++] = pci_cmd;
-			pci_cmd &= ~PCI_COMMAND_MASTER;
-			pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
-
-	tmp_mask=inb(0x21);	/* works on C3. save mask. */
-	outb(0xFE,0x21);	/* TMR0 only */
-	outb(0xFF,0x80);	/* delay */
-
-	safe_halt();
+	safe_halt();		/* Sync */
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
 	halt();
 
 	local_irq_disable();
 
-	outb(tmp_mask,0x21);	/* restore mask */
-
-	/* restore pci bus master state for all devices */
-	dev = NULL;
-	i = 0;
-	do {
-		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
-		if (dev != NULL) {
-			pci_cmd = cmd_state[i++];
-			pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
-		}
-	} while (dev != NULL);
-	local_irq_restore(flags);
-	preempt_enable();
-
 	/* disable bus ratio bit */
 	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
 	longhaul->bits.EnableSoftBusRatio = 0;
 	longhaul->bits.RevisionKey = version;
 	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+
+	outb(pic2_mask,0xA1);
+	outb(pic1_mask,0x21);	/* restore mask */
+	local_irq_restore(flags);
+
+	wakeup_pci();
+	preempt_enable();
 }
 
 /**
@@ -206,7 +283,6 @@
 	int speed, mult;
 	struct cpufreq_freqs freqs;
 	union msr_longhaul longhaul;
-	union msr_bcr2 bcr2;
 	static unsigned int old_ratio=-1;
 
 	if (old_ratio == clock_ratio_index)
@@ -241,20 +317,7 @@
 	 */
 	case TYPE_LONGHAUL_V1:
 	case TYPE_LONGHAUL_V2:
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		/* Enable software clock multiplier */
-		bcr2.bits.ESOFTBF = 1;
-		bcr2.bits.CLOCKMUL = clock_ratio_index;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		safe_halt();
-
-		/* Disable software clock multiplier */
-		rdmsrl (MSR_VIA_BCR2, bcr2.val);
-		bcr2.bits.ESOFTBF = 0;
-		local_irq_disable();
-		wrmsrl (MSR_VIA_BCR2, bcr2.val);
-		local_irq_enable();
+		do_longhaul1(0, clock_ratio_index);
 		break;
 
 	/*

[-- Attachment #3: Type: text/plain, Size: 147 bytes --]

_______________________________________________
Cpufreq mailing list
Cpufreq@lists.linux.org.uk
http://lists.linux.org.uk/mailman/listinfo/cpufreq

             reply	other threads:[~2006-05-12 20:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-05-12 20:37 Rafał Bilski [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-05-14  6:51 Longhaul - patch proposal Rafał Bilski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4464F1FA.4010304@interia.pl \
    --to=rafalbilski@interia.pl \
    --cc=cpufreq@lists.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox