2017-04-07 12:26:07 +02:00
|
|
|
/*
|
|
|
|
* inteltool - dump all registers on an Intel CPU + chipset based system.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2017 secunet Security Networks AG
|
2019-08-17 13:54:02 +02:00
|
|
|
* Copyright (C) 2019 YADRO
|
2017-04-07 12:26:07 +02:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include "inteltool.h"
|
|
|
|
#include "pcr.h"
|
|
|
|
|
2020-01-29 09:20:23 +01:00
|
|
|
#include "gpio_names/apollolake.h"
|
2020-01-29 09:16:06 +01:00
|
|
|
#include "gpio_names/cannonlake.h"
|
2019-06-12 06:23:46 +02:00
|
|
|
#include "gpio_names/cannonlake_lp.h"
|
2020-01-29 09:51:25 +01:00
|
|
|
#include "gpio_names/denverton.h"
|
2020-01-29 09:14:18 +01:00
|
|
|
#include "gpio_names/icelake.h"
|
2020-01-29 09:29:39 +01:00
|
|
|
#include "gpio_names/lewisburg.h"
|
2020-01-29 09:25:45 +01:00
|
|
|
#include "gpio_names/sunrise.h"
|
2020-01-29 09:14:18 +01:00
|
|
|
|
2017-04-07 12:26:07 +02:00
|
|
|
#define SBBAR_SIZE (16 * MiB)
|
|
|
|
#define PCR_PORT_SIZE (64 * KiB)
|
|
|
|
|
|
|
|
static const char *decode_pad_mode(const struct gpio_group *const group,
|
|
|
|
const size_t pad, const uint32_t dw0)
|
|
|
|
{
|
|
|
|
const size_t pad_mode = dw0 >> 10 & 7;
|
2018-11-27 12:27:22 +01:00
|
|
|
const char *const pad_name =
|
|
|
|
group->pad_names[pad * group->func_count + pad_mode];
|
|
|
|
|
2017-04-07 12:26:07 +02:00
|
|
|
if (!pad_mode)
|
2018-11-27 12:27:22 +01:00
|
|
|
return pad_name[0] == '*' ? "*GPIO" : "GPIO";
|
2017-04-07 12:26:07 +02:00
|
|
|
else if (pad_mode < group->func_count)
|
|
|
|
return group->pad_names[pad * group->func_count + pad_mode];
|
|
|
|
else
|
|
|
|
return "RESERVED";
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_gpio_group(const uint8_t pid, size_t pad_cfg,
|
2019-02-19 11:51:34 +01:00
|
|
|
const struct gpio_group *const group,
|
|
|
|
size_t pad_stepping)
|
2017-04-07 12:26:07 +02:00
|
|
|
{
|
|
|
|
size_t p;
|
|
|
|
|
|
|
|
printf("%s\n", group->display);
|
|
|
|
|
2019-02-19 11:51:34 +01:00
|
|
|
for (p = 0; p < group->pad_count; ++p, pad_cfg += pad_stepping) {
|
2017-04-07 12:26:07 +02:00
|
|
|
const uint32_t dw0 = read_pcr32(pid, pad_cfg);
|
|
|
|
const uint32_t dw1 = read_pcr32(pid, pad_cfg + 4);
|
2018-11-27 12:27:22 +01:00
|
|
|
const char *const pad_name =
|
|
|
|
group->pad_names[p * group->func_count];
|
2017-04-07 12:26:07 +02:00
|
|
|
|
2018-11-27 12:27:22 +01:00
|
|
|
printf("0x%04zx: 0x%016"PRIx64" %-12s %-20s\n", pad_cfg,
|
2017-04-07 12:26:07 +02:00
|
|
|
(uint64_t)dw1 << 32 | dw0,
|
2018-11-27 12:27:22 +01:00
|
|
|
pad_name[0] == '*' ? &pad_name[1] : pad_name,
|
2017-04-07 12:26:07 +02:00
|
|
|
decode_pad_mode(group, p, dw0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-19 11:51:34 +01:00
|
|
|
static void print_gpio_community(const struct gpio_community *const community,
|
|
|
|
size_t pad_stepping)
|
2017-04-07 12:26:07 +02:00
|
|
|
{
|
|
|
|
size_t group, pad_count;
|
|
|
|
size_t pad_cfg; /* offset in bytes under this communities PCR port */
|
|
|
|
|
|
|
|
printf("%s\n\nPCR Port ID: 0x%06zx\n\n",
|
|
|
|
community->name, (size_t)community->pcr_port_id << 16);
|
|
|
|
|
|
|
|
for (group = 0, pad_count = 0; group < community->group_count; ++group)
|
|
|
|
pad_count += community->groups[group]->pad_count;
|
|
|
|
assert(pad_count * 8 <= PCR_PORT_SIZE - 0x10);
|
|
|
|
|
|
|
|
pad_cfg = read_pcr32(community->pcr_port_id, 0x0c);
|
|
|
|
if (pad_cfg + pad_count * 8 > PCR_PORT_SIZE) {
|
|
|
|
fprintf(stderr, "Bad Pad Base Address: 0x%08zx\n", pad_cfg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (group = 0; group < community->group_count; ++group) {
|
|
|
|
print_gpio_group(community->pcr_port_id,
|
2019-02-19 11:51:34 +01:00
|
|
|
pad_cfg, community->groups[group],
|
|
|
|
pad_stepping);
|
|
|
|
pad_cfg += community->groups[group]->pad_count * pad_stepping;
|
2017-04-07 12:26:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-29 10:08:17 +01:00
|
|
|
const struct gpio_community *const *get_gpio_communities(struct pci_dev *const sb,
|
|
|
|
size_t* community_count,
|
|
|
|
size_t* pad_stepping)
|
2017-04-07 12:26:07 +02:00
|
|
|
{
|
2020-01-29 10:08:17 +01:00
|
|
|
*pad_stepping = 8;
|
2017-04-07 12:26:07 +02:00
|
|
|
|
|
|
|
switch (sb->device_id) {
|
2019-07-28 19:09:08 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_H110:
|
2019-07-29 21:53:14 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_H170:
|
|
|
|
case PCI_DEVICE_ID_INTEL_Z170:
|
|
|
|
case PCI_DEVICE_ID_INTEL_Q170:
|
|
|
|
case PCI_DEVICE_ID_INTEL_Q150:
|
2017-10-03 16:03:07 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_B150:
|
2019-05-06 17:50:57 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_C236:
|
2019-07-29 21:53:14 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_C232:
|
|
|
|
case PCI_DEVICE_ID_INTEL_QM170:
|
|
|
|
case PCI_DEVICE_ID_INTEL_HM170:
|
|
|
|
case PCI_DEVICE_ID_INTEL_CM236:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(sunrise_communities);
|
|
|
|
return sunrise_communities;
|
2019-02-19 23:49:11 +01:00
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL:
|
2018-07-24 06:09:47 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM:
|
|
|
|
case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(sunrise_lp_communities);
|
|
|
|
return sunrise_lp_communities;
|
2019-08-17 13:54:02 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_C621:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C622:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C624:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C625:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C626:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C627:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C628:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C629:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C624_SUPER:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C627_SUPER_1:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C621_SUPER:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C627_SUPER_2:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C628_SUPER:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(lewisburg_communities);
|
|
|
|
return lewisburg_communities;
|
2019-01-12 19:20:50 +01:00
|
|
|
case PCI_DEVICE_ID_INTEL_DNV_LPC:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(denverton_communities);
|
|
|
|
return denverton_communities;
|
2018-11-27 12:27:22 +01:00
|
|
|
case PCI_DEVICE_ID_INTEL_APL_LPC:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(apl_communities);
|
|
|
|
return apl_communities;
|
2019-06-12 06:23:46 +02:00
|
|
|
case PCI_DEVICE_ID_INTEL_CANNONPOINT_LP_U_PREM:
|
|
|
|
*community_count = ARRAY_SIZE(cannonlake_pch_lp_communities);
|
|
|
|
*pad_stepping = 16;
|
|
|
|
return cannonlake_pch_lp_communities;
|
2019-02-19 11:51:34 +01:00
|
|
|
case PCI_DEVICE_ID_INTEL_H310:
|
|
|
|
case PCI_DEVICE_ID_INTEL_H370:
|
|
|
|
case PCI_DEVICE_ID_INTEL_Z390:
|
|
|
|
case PCI_DEVICE_ID_INTEL_Q370:
|
|
|
|
case PCI_DEVICE_ID_INTEL_B360:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C246:
|
|
|
|
case PCI_DEVICE_ID_INTEL_C242:
|
|
|
|
case PCI_DEVICE_ID_INTEL_QM370:
|
|
|
|
case PCI_DEVICE_ID_INTEL_HM370:
|
|
|
|
case PCI_DEVICE_ID_INTEL_CM246:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(cannonlake_pch_h_communities);
|
|
|
|
*pad_stepping = 16;
|
|
|
|
return cannonlake_pch_h_communities;
|
2020-01-04 15:14:59 +01:00
|
|
|
case PCI_DEVICE_ID_INTEL_ICELAKE_LP_U:
|
2020-01-29 10:08:17 +01:00
|
|
|
*community_count = ARRAY_SIZE(icelake_pch_h_communities);
|
|
|
|
*pad_stepping = 16;
|
|
|
|
return icelake_pch_h_communities;
|
2017-04-07 12:26:07 +02:00
|
|
|
default:
|
2020-01-29 10:08:17 +01:00
|
|
|
return NULL;
|
2017-04-07 12:26:07 +02:00
|
|
|
}
|
2020-01-29 10:08:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void print_gpio_groups(struct pci_dev *const sb)
|
|
|
|
{
|
|
|
|
size_t community_count;
|
|
|
|
const struct gpio_community *const *communities;
|
|
|
|
size_t pad_stepping;
|
|
|
|
|
|
|
|
communities = get_gpio_communities(sb, &community_count, &pad_stepping);
|
|
|
|
|
|
|
|
if (!communities)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pcr_init(sb);
|
2017-04-07 12:26:07 +02:00
|
|
|
|
|
|
|
printf("\n============= GPIOS =============\n\n");
|
|
|
|
|
|
|
|
for (; community_count; --community_count)
|
2019-02-19 11:51:34 +01:00
|
|
|
print_gpio_community(*communities++, pad_stepping);
|
2017-04-07 12:26:07 +02:00
|
|
|
}
|