via.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 3 #include "superiotool.h" 4 5 #define DEVICE_ID_VT82C686_REG 0xe0 6 #define DEVICE_REV_VT82C686_REG 0xe1 7 8 #define DEVICE_ID_VT1211_REG 0x20 9 #define DEVICE_REV_VT1211_REG 0x21 10 11 static const struct superio_registers reg_table[] = { 12 {0x3c00, "VT82C686A/VT82C686B", { 13 {EOT}}}, 14 {0x3c01, "VT1211", { 15 {NOLDN, NULL, 16 {0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, 17 0x2e,0x2f,EOT}, 18 {0x3c,0x01,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00, 19 0x00,0x00,EOT}}, 20 {0x0, "Floppy Disk Controller (FDC)", 21 {0x30,0x60,0x61,0x70,0x74,0xf0,0xf1,EOT}, 22 {0x00,0x03,0xf0,0x06,0x01,0x00,0x00,EOT}}, 23 {0x1, "Parallel Port (PP)", 24 {0x30,0x60,0x61,0x70,0x74,0xf0,EOT}, 25 {0x03,0x03,0x78,0x05,0x00,0x00,EOT}}, 26 {0x2, "Serial Port 1 (UART1)", 27 {0x30,0x60,0x61,0x70,0xf0,EOT}, 28 {0x00,0x03,0xf8,0x04,0x00,EOT}}, 29 {0x3, "Serial Port 2 (UART2)", 30 {0x30,0x60,0x61,0x70,0xf0,EOT}, 31 {0x00,0x02,0xf8,0x03,0x00,EOT}}, 32 {0x6, "MIDI", 33 {0x30,0x60,0x61,0x70,EOT}, 34 {0x00,0x03,0x30,0x00,EOT}}, 35 {0x7, "Game Port (GMP)", 36 {0x30,0x60,0x61,EOT}, 37 {0x00,0x02,0x00,EOT}}, 38 {0x8, "GPIO", 39 {0x30,0x60,0x61,0x70,0xf0,0xf1,0xf2,EOT}, 40 {0x00,0xe9,0x00,0x00,0x00,0x00,0x00,EOT}}, 41 {0x9, "Watch Dog (WDG)", 42 {0x30,0x60,0x61,0x70,0xf0,EOT}, 43 {0x00,0xea,0x00,0x00,0x00,EOT}}, 44 {0xa, "Wake-up Control (WUC)", 45 {0x30,0x60,0x61,0x70,EOT}, 46 {0x00,0xeb,0x00,0x00,EOT}}, 47 {0xb, "Hardware Monitor (HM)", 48 {0x30,0x60,0x61,0x70,EOT}, 49 {0x00,0xec,0x00,0x00,EOT}}, 50 {0xc, "Very Fast IR (VFIR)", 51 {0x30,0x60,0x61,0x70,0x74,0xf0,EOT}, 52 {0x00,0xe8,0x00,0x00,0x06,0x00,EOT}}, 53 {0xd, "Flash ROM (ROM)", 54 {0x30,0xf0,EOT}, 55 {0x01,0x00,EOT}}, 56 {EOT}}}, 57 {EOT} 58 }; 59 60 static uint8_t vt82c686_conf = 0; 61 62 static int enter_conf_mode_via_vt82c686(void) 63 { 64 struct pci_dev *dev; 65 66 dev = pci_dev_find(0x1106, 0x0686); 67 if (!dev) { 68 if (verbose) 69 printf(" PCI device 1106:0686 not found.\n"); 70 return 1; 71 } 72 73 vt82c686_conf = pci_read_byte(dev, 0x85); 74 if (verbose) 75 printf(" Super I/O %sabled, Super I/O configuration %sabled\n", 76 (vt82c686_conf & (1 << 0)) ? "en" : "dis", 77 (vt82c686_conf & (1 << 1)) ? "en" : "dis"); 78 79 /* If the Super I/O is not enabled, skip it. */ 80 if (!(vt82c686_conf & (1 << 0))) 81 return 1; 82 83 /* Enable Super I/O configuration mode. */ 84 pci_write_byte(dev, 0x85, vt82c686_conf | (1 << 1)); 85 86 return 0; 87 } 88 89 static void exit_conf_mode_via_vt82c686(void) 90 { 91 struct pci_dev *dev; 92 93 dev = pci_dev_find(0x1106, 0x0686); 94 if (!dev) { 95 printf("Bug: PCI device 1106:0686 not found during shutdown.\n" 96 "Please report to coreboot@coreboot.org.\n"); 97 return; 98 } 99 100 /* Restore (disable?) Super I/O configuration mode setting. */ 101 pci_write_byte(dev, 0x85, vt82c686_conf); 102 } 103 104 void probe_idregs_via(uint16_t port) 105 { 106 uint16_t id; 107 uint8_t devid; 108 uint8_t rev; 109 110 if (port == 0x3f0) { 111 probing_for("VIA", "(init=vt82c686) ", port); 112 if (enter_conf_mode_via_vt82c686()) 113 return; 114 115 devid = regval(port, DEVICE_ID_VT82C686_REG); 116 rev = regval(port, DEVICE_REV_VT82C686_REG); 117 id = devid << 8; 118 119 if (superio_unknown(reg_table, id)) { 120 if (verbose) 121 printf(NOTFOUND "id=0x%02x, rev=0x%02x\n", devid, rev); 122 } else { 123 printf("Found VIA %s (id=0x%02x, rev=0x%02x) at 0x%x\n", 124 get_superio_name(reg_table, id), devid, rev, port); 125 chip_found = 1; 126 } 127 exit_conf_mode_via_vt82c686(); 128 if (chip_found) 129 return; 130 } else { 131 probing_for("VIA", "(init=0x87,0x87) ", port); 132 enter_conf_mode_winbond_fintek_ite_8787(port); 133 134 devid = regval(port, DEVICE_ID_VT1211_REG); 135 rev = regval(port, DEVICE_REV_VT1211_REG); 136 id = (devid << 8) | 1; 137 138 if (superio_unknown(reg_table, id)) { 139 if (verbose) 140 printf(NOTFOUND "id=0x%02x, rev=0x%02x\n", devid, rev); 141 } else { 142 printf("Found VIA %s (id=0x%02x, rev=0x%02x) at 0x%x\n", 143 get_superio_name(reg_table, id), devid, rev, port); 144 chip_found = 1; 145 dump_superio("VIA", reg_table, port, id, LDN_SEL); 146 } 147 } 148 149 exit_conf_mode_winbond_fintek_ite_8787(port); 150 } 151 152 void print_via_chips(void) 153 { 154 print_vendor_chips("VIA", reg_table); 155 }