cpufreq Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Pavel Machek <pavel@ucw.cz>
To: linux@dominikbrodowski.de, paul.devriendt@amd.com,
	Cpufreq mailing list <cpufreq@www.linux.org.uk>
Subject: powernow-k8 updates
Date: Fri, 26 Mar 2004 13:01:51 +0100	[thread overview]
Message-ID: <20040326120151.GA3102@elf.ucw.cz> (raw)

Hi!

Few updates, enable ACPI, add common printing function, fix typo, move
"pst out of sequence" where it belongs, fix formating in
powernow-k8.h. I'm not quite sure what this is against, so this is
"eyes only".
								Pavel

--- tmp/linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-03-26 12:51:45.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c	2004-03-26 12:28:01.000000000 +0100
@@ -33,6 +33,9 @@
 #include <asm/io.h>
 #include <asm/delay.h>
 
+#ifdef CONFIG_ACPI
+#define CONFIG_X86_POWERNOW_K8_ACPI
+#endif
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
 
 #include <linux/acpi.h>
@@ -42,7 +45,7 @@
 
 
 #define PFX "powernow-k8: "
-#define VERSION "version 1.20.07 - March 18, 2004"
+#define VERSION "version 1.20.08b - March 20, 2004"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -63,6 +66,12 @@
 	return 1000 * find_freq_from_fid(fid);
 }
 
+/* Return a voltage in miliVolts, given an input vid */
+static inline u32 find_milivolts_from_vid(struct powernow_k8_data *data, u32 vid)
+{
+	return 1550-vid*25;
+}
+
 /* Return the vco fid for an input fid */
 static u32 convert_fid_to_vco_fid(u32 fid)
 {
@@ -498,16 +507,36 @@
 	return 0;
 }
 
+static void print_basics(struct powernow_k8_data *data)
+{
+	int j;
+	for (j = 0; j < data->numps; j++) {
+		printk(KERN_INFO PFX "   %d : fid %x (%d MHz), vid %x (%d mV)\n", j,
+		       data->powernow_table[j].index & 0xff, 
+		       data->powernow_table[j].frequency/1000, 
+		       data->powernow_table[j].index >> 8, 
+		       find_milivolts_from_vid(data, data->powernow_table[j].index >> 8));
+	}
+	if (data->batps)
+		printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
+}
+
 static inline int fill_powernow_table(struct powernow_k8_data *data, struct pst_s *pst, u8 maxvid)
 {
 	struct cpufreq_frequency_table *powernow_table;
 	unsigned int j;
 
 	if (data->batps) {    /* use ACPI support to get full speed on mains power */
-		printk(KERN_INFO PFX "only %d pstates on battery\n", data->batps);
+		printk(KERN_WARNING PFX "Only %d pstates usable (use ACPI driver for full range\n", data->batps);
 		data->numps = data->batps;
 	}
 
+	for ( j=1; j<data->numps; j++ )
+		if (pst[j-1].fid >= pst[j].fid) {
+			printk(KERN_ERR PFX "PST out of sequence\n");
+			return -EINVAL;
+		}
+
 	if (data->numps < 2) {
 		printk(KERN_ERR PFX "no p states to transition\n");
 		return -ENODEV;
@@ -527,10 +556,6 @@
 		powernow_table[j].index = pst[j].fid; /* lower 8 bits */
 		powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */
 		powernow_table[j].frequency = find_khz_freq_from_fid(pst[j].fid);
-
-		printk(KERN_INFO PFX "   %d : fid %x (%d MHz), vid %x\n", j,
-		       pst[j].fid, powernow_table[j].frequency/1000, pst[j].vid);
-
 	}
 	powernow_table[data->numps].frequency = CPUFREQ_TABLE_END;
 	powernow_table[data->numps].index = 0;
@@ -540,14 +565,15 @@
 		return -EIO;
 	}
 
-	printk(KERN_INFO PFX "cfid %x, cvid %x\n", data->currfid, data->currvid);
+	dprintk(KERN_INFO PFX "cfid %x, cvid %x\n", data->currfid, data->currvid);
 	data->powernow_table = powernow_table;
+	print_basics(data);
 
 	for (j = 0; j < data->numps; j++)
 		if ((pst[j].fid==data->currfid) && (pst[j].vid==data->currvid))
 			return 0;
 
-	printk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n");
+	dprintk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n");
 	return 0;
 }
 
@@ -616,6 +642,17 @@
 		return fill_powernow_table(data, (struct pst_s *)(psb+1), maxvid);
 	}
 
+	/*
+	 * If you see this message, complain to BIOS manufacturer. If
+	 * he tells you "we do not support Linux" or some similar
+	 * nonsense, remember that Windows 2000 uses the same legacy
+	 * mechanism that the old Linux PSB driver uses. Tell them it
+	 * is broken with Windows 2000.
+	 *
+	 * The reference to the AMD documentation is chapter 9 in the
+	 * BIOS and Kernel Developer's Guide, which is available on
+	 * www.amd.com
+	 */
 	printk(KERN_ERR PFX "BIOS error - no PSB\n");
 
 #if 1
@@ -632,17 +669,17 @@
 	data->irt = 2;
 	mvs = 1;
 	data->vidmvs = 1 << mvs;
-	data->batps = 3;
-	data->numps = 3;
+	data->batps = 4;
+	data->numps = 4;
 	data->plllock = 2;
 	{
-		struct pst_s override[3] = {{ .vid = 0x12, .fid = 0x00 },   /* 0.8GHz @ 1.100v */
+		struct pst_s override[4] = {{ .vid = 0x12, .fid = 0x00 },   /* 0.8GHz @ 1.100v */
 					    { .vid = 0x06, .fid = 0x08 },   /* 1.6GHz @ 1.400v */
-					    { .vid = 0x02, .fid = 0x0a }};  /* 1.8GHz @ 1.500v */
+					    { .vid = 0x04, .fid = 0x0a },   /* 1.8GHz @ 1.450v */
+					    { .vid = 0x02, .fid = 0x0c }};  /* 2.0GHz @ 1.500v */
 		return fill_powernow_table(data, override, 0);
  	}
 #endif
-
 	return -ENODEV;
 }
 
@@ -664,6 +701,7 @@
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) 
 { 
 	int i;
+	int cntlofreq = 0;
 	struct cpufreq_frequency_table *powernow_table;
 
 	if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
@@ -683,8 +721,6 @@
 		goto err_out;
 	}
 
-	/* FIXME: more tests? */
-
 	/* fill in data->powernow_table */
 	powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) 
 				  * (data->acpi_data.state_count + 1)), GFP_KERNEL);
@@ -704,12 +740,19 @@
 		powernow_table[i].frequency = find_khz_freq_from_fid(fid);
 
 		/* verify frequency is OK */
-		if (powernow_table[i].frequency > (MAX_FREQ * 1000)) {
+		if ((powernow_table[i].frequency > (MAX_FREQ * 1000)) ||
+		    (powernow_table[i].frequency < (MIN_FREQ * 1000))) {
 			dprintk(KERN_INFO PFX "invalid freq %u kHz\n", powernow_table[i].frequency);
 			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 			continue;
 		}
 
+		/* verify only 1 entry from the lo frequency table */
+		if ((fid < HI_FID_TABLE_BOTTOM) && (cntlofreq++)) {
+			printk(KERN_ERR PFX "Too many lo freq table entries\n");
+			goto err_out;
+		}
+
 		if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
 			printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n", 
 			       powernow_table[i].frequency, 
@@ -719,11 +762,13 @@
 		}
 	}
 	powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
-
+	powernow_table[data->acpi_data.state_count].index = 0;
 	data->powernow_table = powernow_table;
 
 	/* fill in data */
 	data->numps = data->acpi_data.state_count;
+	print_basics(data);
+
 	powernow_k8_acpi_pst_values(data, 0);
 
 	return 0;
@@ -899,8 +944,7 @@
 
 	data->cpu = pol->cpu;
 
-	if (powernow_k8_cpu_init_acpi(data))
-	{
+	if (powernow_k8_cpu_init_acpi(data)) {
 		/* 
 		 * Use the PSB BIOS structure. This is only availabe on
 		 * an UP version, and is deprecated by AMD.
@@ -912,9 +956,8 @@
 			return -ENODEV;
 		}
 
-		if ((num_online_cpus() != 1) ||
-		    (num_possible_cpus() != 1)) {
-			printk(KERN_INFO PFX "multiprocessor systems not supported by PSB BIOS structure\n");
+		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
+			printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
 			kfree(data);
 			return 0;
 		}
@@ -971,7 +1014,7 @@
 	}
 	cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
-	printk(KERN_INFO PFX "init, curr fid %x vid %x\n", data->currfid, data->currvid);
+	dprintk(KERN_INFO PFX "init, curr fid %x vid %x\n", data->currfid, data->currvid);
 
 	powernow_data[pol->cpu] = data;
 
@@ -1017,7 +1060,6 @@
 	.attr = powernow_k8_attr,
 };
 
-
 /* driver entry point for init */
 static int __init powernowk8_init(void)
 {
@@ -1031,7 +1073,8 @@
 	}
 
 	if (supported_cpus == num_online_cpus()) {
-		printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n", supported_cpus);
+		printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron processors (" VERSION ")\n",
+		       supported_cpus);
 		return cpufreq_register_driver(&cpufreq_amd64_driver);
 	}
 
--- tmp/linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.h	2004-03-26 12:51:45.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.h	2004-03-26 12:44:27.000000000 +0100
@@ -6,36 +6,32 @@
  */
 
 struct powernow_k8_data {
-	unsigned int			cpu;
+	unsigned int	cpu;
 
-	u32				numps;	/* number of p-states */
-	u32				batps; 	/* number of p-states 
-						 * supported on battery */
+	u32	numps;	/* number of p-states */
+	u32	batps; 	/* number of p-states supported on battery */
 
 	/* these values are constant when the PSB is used to determine
 	 * vid/fid pairings, but are modified during the ->target() call
 	 * when ACPI is used */
-	u32				rvo;	/* ramp voltage offset */
-	u32				irt;	/* isochronous relief time */
-	u32				vidmvs;	/* usable value calculated 
-						 * from mvs */
-	u32				vstable;/* voltage stabilization time, 
-						 * units 20 us */
-	u32 				plllock;/* pll lock time, 
-						 * units 1 us */
+	u32	rvo;	 /* ramp voltage offset */
+	u32	irt;	 /* isochronous relief time */
+	u32	vidmvs;	 /* usable value calculated from mvs */
+	u32	vstable; /* voltage stabilization time, units 20 us */
+	u32 	plllock; /* pll lock time, units 1 us */
 
 	/* keep track of the current fid / vid */
-	u32				currvid;
-	u32				currfid;
+	u32	currvid;
+	u32	currfid;
 
 	/* the powernow_table includes all frequency and vid/fid pairings:
 	 * fid are the lower 8 bits of the index, vid are the upper 8 bits.
 	 * frequency is in kHz */
 	struct cpufreq_frequency_table	*powernow_table;
 
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 	/* the acpi table needs to be kept. it's only available if ACPI was
 	 * used to determine valid frequency/vid/fid states */
-#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 	struct acpi_processor_performance acpi_data;
 #endif
 };
@@ -78,6 +74,19 @@
 #define MSR_S_HI_CURRENT_VID      0x0000001f
 #define MSR_C_HI_STP_GNT_BENIGN   0x00000001
 
+/*
+   There are restrictions frequencies have to follow:
+   - only 1 entry in the low fid table ( <=1.4GHz )
+   - lowest entry in the high fid table must be >= 2 * the
+     entry in the low fid table
+   - lowest entry in the high fid table must be a <= 200MHz +
+     2 * the entry in the low fid table
+   - the parts can only step at 200 MHz intervals, so 1.9 GHz is
+     never valid
+   - lowest frequency must be >= interprocessor hypertransport link
+     speed (only applies to MP systems obviously)
+ */
+
 /* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
 #define LO_FID_TABLE_TOP           6   /* fid values marking the boundary    */
 #define HI_FID_TABLE_BOTTOM        8   /* between the low and high tables    */

-- 
When do you have a heart between your knees?
[Johanka's followup: and *two* hearts?]

             reply	other threads:[~2004-03-26 12:01 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-26 12:01 Pavel Machek [this message]
2004-03-26 12:19 ` powernow-k8 updates Pavel Machek
2004-03-26 12:27   ` Dominik Brodowski
2004-03-26 12:32     ` Pavel Machek
2004-03-26 13:02       ` Dominik Brodowski
2004-03-26 12:23 ` Dominik Brodowski
2004-03-26 12:33   ` Pavel Machek
  -- strict thread matches above, loose matches on Subject: below --
2004-03-09 21:48 Pavel Machek
2004-03-10 11:09 ` Bruno Ducrot
2004-03-10 11:32   ` Pavel Machek
2004-03-10 13:48     ` Bruno Ducrot
2004-03-14 16:33       ` Dominik Brodowski
2004-03-14 16:32 ` Dominik Brodowski

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=20040326120151.GA3102@elf.ucw.cz \
    --to=pavel@ucw.cz \
    --cc=cpufreq@www.linux.org.uk \
    --cc=linux@dominikbrodowski.de \
    --cc=paul.devriendt@amd.com \
    /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