xref: /openbmc/linux/tools/power/cpupower/debug/i386/dump_psb.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*fa82cce7SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2*fa82cce7SThomas Gleixner // dump_psb. (c) 2004, Dave Jones, Red Hat Inc.
37fe2f639SDominik Brodowski 
47fe2f639SDominik Brodowski #include <fcntl.h>
57fe2f639SDominik Brodowski #include <stdio.h>
67fe2f639SDominik Brodowski #include <stdlib.h>
77fe2f639SDominik Brodowski #include <string.h>
87fe2f639SDominik Brodowski #include <unistd.h>
97fe2f639SDominik Brodowski 
107fe2f639SDominik Brodowski #define _GNU_SOURCE
117fe2f639SDominik Brodowski #include <getopt.h>
127fe2f639SDominik Brodowski 
137fe2f639SDominik Brodowski #include <sys/mman.h>
147fe2f639SDominik Brodowski 
157fe2f639SDominik Brodowski #define LEN (0x100000 - 0xc0000)
167fe2f639SDominik Brodowski #define OFFSET (0xc0000)
177fe2f639SDominik Brodowski 
187fe2f639SDominik Brodowski #ifndef __packed
197fe2f639SDominik Brodowski #define __packed __attribute((packed))
207fe2f639SDominik Brodowski #endif
217fe2f639SDominik Brodowski 
227fe2f639SDominik Brodowski static long relevant;
237fe2f639SDominik Brodowski 
247fe2f639SDominik Brodowski static const int fid_to_mult[32] = {
257fe2f639SDominik Brodowski 	110, 115, 120, 125, 50, 55, 60, 65,
267fe2f639SDominik Brodowski 	70, 75, 80, 85, 90, 95, 100, 105,
277fe2f639SDominik Brodowski 	30, 190, 40, 200, 130, 135, 140, 210,
287fe2f639SDominik Brodowski 	150, 225, 160, 165, 170, 180, -1, -1,
297fe2f639SDominik Brodowski };
307fe2f639SDominik Brodowski 
317fe2f639SDominik Brodowski static const int vid_to_voltage[32] = {
327fe2f639SDominik Brodowski 	2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
337fe2f639SDominik Brodowski 	1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
347fe2f639SDominik Brodowski 	1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
357fe2f639SDominik Brodowski 	1075, 1050, 1024, 1000, 975, 950, 925, 0,
367fe2f639SDominik Brodowski };
377fe2f639SDominik Brodowski 
387fe2f639SDominik Brodowski struct psb_header {
397fe2f639SDominik Brodowski 	char signature[10];
407fe2f639SDominik Brodowski 	u_char version;
417fe2f639SDominik Brodowski 	u_char flags;
427fe2f639SDominik Brodowski 	u_short settlingtime;
437fe2f639SDominik Brodowski 	u_char res1;
447fe2f639SDominik Brodowski 	u_char numpst;
457fe2f639SDominik Brodowski } __packed;
467fe2f639SDominik Brodowski 
477fe2f639SDominik Brodowski struct pst_header {
487fe2f639SDominik Brodowski 	u_int32_t cpuid;
497fe2f639SDominik Brodowski 	u_char fsb;
507fe2f639SDominik Brodowski 	u_char maxfid;
517fe2f639SDominik Brodowski 	u_char startvid;
527fe2f639SDominik Brodowski 	u_char numpstates;
537fe2f639SDominik Brodowski } __packed;
547fe2f639SDominik Brodowski 
557fe2f639SDominik Brodowski static u_int fsb;
567fe2f639SDominik Brodowski static u_int sgtc;
577fe2f639SDominik Brodowski 
587fe2f639SDominik Brodowski static int
decode_pst(char * p,int npstates)597fe2f639SDominik Brodowski decode_pst(char *p, int npstates)
607fe2f639SDominik Brodowski {
617fe2f639SDominik Brodowski 	int i;
627fe2f639SDominik Brodowski 	int freq, fid, vid;
637fe2f639SDominik Brodowski 
647fe2f639SDominik Brodowski 	for (i = 0; i < npstates; ++i) {
657fe2f639SDominik Brodowski 		fid = *p++;
667fe2f639SDominik Brodowski 		vid = *p++;
677fe2f639SDominik Brodowski 		freq = 100 * fid_to_mult[fid] * fsb;
687fe2f639SDominik Brodowski 
697fe2f639SDominik Brodowski 		printf("   %2d %8dkHz  FID %02x (%2d.%01d)  VID %02x (%4dmV)\n",
707fe2f639SDominik Brodowski 		       i,
717fe2f639SDominik Brodowski 		       freq,
727fe2f639SDominik Brodowski 		       fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,
737fe2f639SDominik Brodowski 		       vid, vid_to_voltage[vid]);
747fe2f639SDominik Brodowski 	}
757fe2f639SDominik Brodowski 
767fe2f639SDominik Brodowski 	return 0;
777fe2f639SDominik Brodowski }
787fe2f639SDominik Brodowski 
797fe2f639SDominik Brodowski static
decode_psb(char * p,int numpst)807fe2f639SDominik Brodowski void decode_psb(char *p, int numpst)
817fe2f639SDominik Brodowski {
827fe2f639SDominik Brodowski 	int i;
837fe2f639SDominik Brodowski 	struct psb_header *psb;
847fe2f639SDominik Brodowski 	struct pst_header *pst;
857fe2f639SDominik Brodowski 
867fe2f639SDominik Brodowski 	psb = (struct psb_header*) p;
877fe2f639SDominik Brodowski 
887fe2f639SDominik Brodowski 	if (psb->version != 0x12)
897fe2f639SDominik Brodowski 		return;
907fe2f639SDominik Brodowski 
917fe2f639SDominik Brodowski 	printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",
927fe2f639SDominik Brodowski 			psb->version,
937fe2f639SDominik Brodowski 			psb->flags,
947fe2f639SDominik Brodowski 			psb->settlingtime,
957fe2f639SDominik Brodowski 			psb->res1,
967fe2f639SDominik Brodowski 			psb->numpst);
977fe2f639SDominik Brodowski 	sgtc = psb->settlingtime * 100;
987fe2f639SDominik Brodowski 
997fe2f639SDominik Brodowski 	if (sgtc < 10000)
1007fe2f639SDominik Brodowski 		sgtc = 10000;
1017fe2f639SDominik Brodowski 
1027fe2f639SDominik Brodowski 	p = ((char *) psb) + sizeof(struct psb_header);
1037fe2f639SDominik Brodowski 
1047fe2f639SDominik Brodowski 	if (numpst < 0)
1057fe2f639SDominik Brodowski 		numpst = psb->numpst;
1067fe2f639SDominik Brodowski 	else
1077fe2f639SDominik Brodowski 		printf("Overriding number of pst :%d\n", numpst);
1087fe2f639SDominik Brodowski 
1097fe2f639SDominik Brodowski 	for (i = 0; i < numpst; i++) {
1107fe2f639SDominik Brodowski 		pst = (struct pst_header*) p;
1117fe2f639SDominik Brodowski 
1127fe2f639SDominik Brodowski 		if (relevant != 0) {
1137fe2f639SDominik Brodowski 			if (relevant!= pst->cpuid)
1147fe2f639SDominik Brodowski 				goto next_one;
1157fe2f639SDominik Brodowski 		}
1167fe2f639SDominik Brodowski 
1177fe2f639SDominik Brodowski 		printf("  PST %d  cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",
1187fe2f639SDominik Brodowski 				i+1,
1197fe2f639SDominik Brodowski 				pst->cpuid,
1207fe2f639SDominik Brodowski 				pst->fsb,
1217fe2f639SDominik Brodowski 				pst->maxfid,
1227fe2f639SDominik Brodowski 				pst->startvid,
1237fe2f639SDominik Brodowski 				pst->numpstates);
1247fe2f639SDominik Brodowski 
1257fe2f639SDominik Brodowski 		fsb = pst->fsb;
1267fe2f639SDominik Brodowski 		decode_pst(p + sizeof(struct pst_header), pst->numpstates);
1277fe2f639SDominik Brodowski 
1287fe2f639SDominik Brodowski next_one:
1297fe2f639SDominik Brodowski 		p += sizeof(struct pst_header) + 2*pst->numpstates;
1307fe2f639SDominik Brodowski 	}
1317fe2f639SDominik Brodowski 
1327fe2f639SDominik Brodowski }
1337fe2f639SDominik Brodowski 
1347fe2f639SDominik Brodowski static struct option info_opts[] = {
13557ab3b08SSriram Raghunathan      {"numpst", no_argument, NULL, 'n'},
1367fe2f639SDominik Brodowski };
1377fe2f639SDominik Brodowski 
print_help(void)1387fe2f639SDominik Brodowski void print_help(void)
1397fe2f639SDominik Brodowski {
1407fe2f639SDominik Brodowski 	printf ("Usage: dump_psb [options]\n");
1417fe2f639SDominik Brodowski 	printf ("Options:\n");
1427fe2f639SDominik Brodowski 	printf ("  -n, --numpst     Set number of PST tables to scan\n");
1437fe2f639SDominik Brodowski 	printf ("  -r, --relevant   Only display PSTs relevant to cpuid N\n");
1447fe2f639SDominik Brodowski }
1457fe2f639SDominik Brodowski 
1467fe2f639SDominik Brodowski int
main(int argc,char * argv[])1477fe2f639SDominik Brodowski main(int argc, char *argv[])
1487fe2f639SDominik Brodowski {
1497fe2f639SDominik Brodowski 	int fd;
1507fe2f639SDominik Brodowski 	int numpst=-1;
1517fe2f639SDominik Brodowski 	int ret=0, cont=1;
1527fe2f639SDominik Brodowski 	char *mem = NULL;
1537fe2f639SDominik Brodowski 	char *p;
1547fe2f639SDominik Brodowski 
1557fe2f639SDominik Brodowski 	do {
1567fe2f639SDominik Brodowski 		ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);
1577fe2f639SDominik Brodowski 		switch (ret){
1587fe2f639SDominik Brodowski 		case '?':
1597fe2f639SDominik Brodowski 		case 'h':
1607fe2f639SDominik Brodowski 			print_help();
1617fe2f639SDominik Brodowski 			cont = 0;
1627fe2f639SDominik Brodowski 			break;
1637fe2f639SDominik Brodowski 		case 'r':
1647fe2f639SDominik Brodowski 			relevant = strtol(optarg, NULL, 16);
1657fe2f639SDominik Brodowski 			break;
1667fe2f639SDominik Brodowski 		case 'n':
1677fe2f639SDominik Brodowski 			numpst = strtol(optarg, NULL, 10);
1687fe2f639SDominik Brodowski 			break;
1697fe2f639SDominik Brodowski 		case -1:
1707fe2f639SDominik Brodowski 			cont = 0;
1717fe2f639SDominik Brodowski 			break;
1727fe2f639SDominik Brodowski 		}
1737fe2f639SDominik Brodowski 
1747fe2f639SDominik Brodowski 	} while(cont);
1757fe2f639SDominik Brodowski 
1767fe2f639SDominik Brodowski 	fd = open("/dev/mem", O_RDONLY);
1777fe2f639SDominik Brodowski 	if (fd < 0) {
1787fe2f639SDominik Brodowski 		printf ("Couldn't open /dev/mem. Are you root?\n");
1797fe2f639SDominik Brodowski 		exit(1);
1807fe2f639SDominik Brodowski 	}
1817fe2f639SDominik Brodowski 
1827fe2f639SDominik Brodowski 	mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);
1837fe2f639SDominik Brodowski 	close(fd);
1847fe2f639SDominik Brodowski 
1857fe2f639SDominik Brodowski 	for (p = mem; p - mem < LEN; p+=16) {
1867fe2f639SDominik Brodowski 		if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
1877fe2f639SDominik Brodowski 			decode_psb(p, numpst);
1887fe2f639SDominik Brodowski 			break;
1897fe2f639SDominik Brodowski 		}
1907fe2f639SDominik Brodowski 	}
1917fe2f639SDominik Brodowski 
1927fe2f639SDominik Brodowski 	munmap(mem, LEN);
1937fe2f639SDominik Brodowski 	return 0;
1947fe2f639SDominik Brodowski }
195