Lines 51-66
Link Here
|
51 |
#include "imcsmb_reg.h" |
51 |
#include "imcsmb_reg.h" |
52 |
#include "imcsmb_var.h" |
52 |
#include "imcsmb_var.h" |
53 |
|
53 |
|
54 |
/* (Sandy,Ivy)bridge-Xeon and (Has,Broad)well-Xeon CPUs contain one or two |
54 |
/* (Sandy,Ivy)bridge-Xeon, (Has,Broad)well-Xeon, and Skylake-Xeon CPUs contain |
55 |
* "Integrated Memory Controllers" (iMCs), and each iMC contains two separate |
55 |
* one or two "Integrated Memory Controllers" (iMCs), and each iMC contains |
56 |
* SMBus controllers. These are used for reading SPD data from the DIMMs, and |
56 |
* two separate SMBus controllers. These are used for reading SPD data from the |
57 |
* for reading the "Thermal Sensor on DIMM" (TSODs). The iMC SMBus controllers |
57 |
* DIMMs, and for reading the "Thermal Sensor on DIMM" (TSODs). The iMC SMBus |
58 |
* are very simple devices, and have limited functionality compared to |
58 |
* controllers are very simple devices, and have limited functionality compared |
59 |
* full-fledged SMBus controllers, like the one in Intel ICHs and PCHs. |
59 |
* to full-fledged SMBus controllers, like the one in Intel ICHs and PCHs. |
60 |
* |
60 |
* |
61 |
* The publicly available documentation for the iMC SMBus controllers can be |
61 |
* The publicly available documentation for the iMC SMBus controllers can be |
62 |
* found in the CPU datasheets for (Sandy,Ivy)bridge-Xeon and |
62 |
* found in the CPU datasheets for (Sandy,Ivy)bridge-Xeon, (Has,Broad)well-Xeon, |
63 |
* (Has,broad)well-Xeon, respectively: |
63 |
* and Skylake-Xeon, respectively: |
64 |
* |
64 |
* |
65 |
* https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/ |
65 |
* https://www.intel.com/content/dam/www/public/us/en/documents/datasheets/ |
66 |
* Sandybridge xeon-e5-1600-2600-vol-2-datasheet.pdf |
66 |
* Sandybridge xeon-e5-1600-2600-vol-2-datasheet.pdf |
Lines 67-72
Link Here
|
67 |
* Ivybridge xeon-e5-v2-datasheet-vol-2.pdf |
67 |
* Ivybridge xeon-e5-v2-datasheet-vol-2.pdf |
68 |
* Haswell xeon-e5-v3-datasheet-vol-2.pdf |
68 |
* Haswell xeon-e5-v3-datasheet-vol-2.pdf |
69 |
* Broadwell xeon-e5-v4-datasheet-vol-2.pdf |
69 |
* Broadwell xeon-e5-v4-datasheet-vol-2.pdf |
|
|
70 |
* Skylake xeon-scalable-datasheet-vol-2.pdf |
70 |
* |
71 |
* |
71 |
* Another useful resource is the Linux driver. It is not in the main tree. |
72 |
* Another useful resource is the Linux driver. It is not in the main tree. |
72 |
* |
73 |
* |
Lines 101-149
Link Here
|
101 |
* driver such as this one. |
102 |
* driver such as this one. |
102 |
*/ |
103 |
*/ |
103 |
|
104 |
|
104 |
/* PCIe device IDs for (Sandy,Ivy)bridge)-Xeon and (Has,Broad)well-Xeon */ |
105 |
/* PCIe device IDs for (Sandy,Ivy)bridge)-Xeon, (Has,Broad)well-Xeon, and |
|
|
106 |
* Skylake-Xeon |
107 |
*/ |
105 |
#define PCI_VENDOR_INTEL 0x8086 |
108 |
#define PCI_VENDOR_INTEL 0x8086 |
106 |
#define IMCSMB_PCI_DEV_ID_IMC0_SBX 0x3ca8 |
109 |
#define IMCSMB_PCI_DEV_ID_IMC0_SBX 0x3ca8 |
107 |
#define IMCSMB_PCI_DEV_ID_IMC0_IBX 0x0ea8 |
110 |
#define IMCSMB_PCI_DEV_ID_IMC0_IBX 0x0ea8 |
108 |
#define IMCSMB_PCI_DEV_ID_IMC0_HSX 0x2fa8 |
111 |
#define IMCSMB_PCI_DEV_ID_IMC0_HSX 0x2fa8 |
109 |
#define IMCSMB_PCI_DEV_ID_IMC0_BDX 0x6fa8 |
112 |
#define IMCSMB_PCI_DEV_ID_IMC0_BDX 0x6fa8 |
110 |
/* (Sandy,Ivy)bridge-Xeon only have a single memory controller per socket */ |
113 |
#define IMCSMB_PCI_DEV_ID_IMC0_SLX 0x2085 |
|
|
114 |
/* Sandybridge-Xeon only has a single memory controller per socket */ |
115 |
#define IMCSMB_PCI_DEV_ID_IMC1_IBX 0x0e68 |
111 |
#define IMCSMB_PCI_DEV_ID_IMC1_HSX 0x2f68 |
116 |
#define IMCSMB_PCI_DEV_ID_IMC1_HSX 0x2f68 |
112 |
#define IMCSMB_PCI_DEV_ID_IMC1_BDX 0x6f68 |
117 |
#define IMCSMB_PCI_DEV_ID_IMC1_BDX 0x6f68 |
|
|
118 |
#define IMCSMB_PCI_DEV_ID_IMC1_SLX 0x2086 |
113 |
|
119 |
|
114 |
/* There are two SMBus controllers in each device. These define the registers |
120 |
/* There are two SMBus controllers in each device. These define the registers |
115 |
* for each of these devices. |
121 |
* for each of these devices. |
116 |
*/ |
122 |
*/ |
117 |
static struct imcsmb_reg_set imcsmb_regs[] = { |
123 |
static struct imcsmb_reg_set imcsmb_regs[2]; |
118 |
{ |
|
|
119 |
.smb_stat = IMCSMB_REG_STATUS0, |
120 |
.smb_cmd = IMCSMB_REG_COMMAND0, |
121 |
.smb_cntl = IMCSMB_REG_CONTROL0 |
122 |
}, |
123 |
{ |
124 |
.smb_stat = IMCSMB_REG_STATUS1, |
125 |
.smb_cmd = IMCSMB_REG_COMMAND1, |
126 |
.smb_cntl = IMCSMB_REG_CONTROL1 |
127 |
}, |
128 |
}; |
129 |
|
124 |
|
130 |
static struct imcsmb_pci_device { |
125 |
static struct imcsmb_pci_device { |
131 |
uint16_t id; |
126 |
uint16_t id; |
132 |
char *name; |
127 |
char *name; |
|
|
128 |
uint16_t base; |
133 |
} imcsmb_pci_devices[] = { |
129 |
} imcsmb_pci_devices[] = { |
134 |
{IMCSMB_PCI_DEV_ID_IMC0_SBX, |
130 |
{IMCSMB_PCI_DEV_ID_IMC0_SBX, |
135 |
"Intel Sandybridge Xeon iMC 0 SMBus controllers" }, |
131 |
"Intel Sandybridge Xeon iMC 0 SMBus controllers", |
|
|
132 |
IMCSMB_REG_BASE_SBX}, |
136 |
{IMCSMB_PCI_DEV_ID_IMC0_IBX, |
133 |
{IMCSMB_PCI_DEV_ID_IMC0_IBX, |
137 |
"Intel Ivybridge Xeon iMC 0 SMBus controllers" }, |
134 |
"Intel Ivybridge Xeon iMC 0 SMBus controllers", |
|
|
135 |
IMCSMB_REG_BASE_IBX}, |
136 |
{IMCSMB_PCI_DEV_ID_IMC1_IBX, |
137 |
"Intel Ivybridge Xeon iMC 1 SMBus controllers", |
138 |
IMCSMB_REG_BASE_IBX}, |
138 |
{IMCSMB_PCI_DEV_ID_IMC0_HSX, |
139 |
{IMCSMB_PCI_DEV_ID_IMC0_HSX, |
139 |
"Intel Haswell Xeon iMC 0 SMBus controllers" }, |
140 |
"Intel Haswell Xeon iMC 0 SMBus controllers", |
|
|
141 |
IMCSMB_REG_BASE_HSX}, |
140 |
{IMCSMB_PCI_DEV_ID_IMC1_HSX, |
142 |
{IMCSMB_PCI_DEV_ID_IMC1_HSX, |
141 |
"Intel Haswell Xeon iMC 1 SMBus controllers" }, |
143 |
"Intel Haswell Xeon iMC 1 SMBus controllers", |
|
|
144 |
IMCSMB_REG_BASE_HSX}, |
142 |
{IMCSMB_PCI_DEV_ID_IMC0_BDX, |
145 |
{IMCSMB_PCI_DEV_ID_IMC0_BDX, |
143 |
"Intel Broadwell Xeon iMC 0 SMBus controllers" }, |
146 |
"Intel Broadwell Xeon iMC 0 SMBus controllers", |
|
|
147 |
IMCSMB_REG_BASE_BDX}, |
144 |
{IMCSMB_PCI_DEV_ID_IMC1_BDX, |
148 |
{IMCSMB_PCI_DEV_ID_IMC1_BDX, |
145 |
"Intel Broadwell Xeon iMC 1 SMBus controllers" }, |
149 |
"Intel Broadwell Xeon iMC 1 SMBus controllers", |
146 |
{0, NULL}, |
150 |
IMCSMB_REG_BASE_BDX}, |
|
|
151 |
{IMCSMB_PCI_DEV_ID_IMC0_SLX, |
152 |
"Intel Skylake Xeon iMC 0 SMBus controllers", |
153 |
IMCSMB_REG_BASE_SLX}, |
154 |
{IMCSMB_PCI_DEV_ID_IMC1_SLX, |
155 |
"Intel Skylake Xeon iMC 1 SMBus controllers", |
156 |
IMCSMB_REG_BASE_SLX}, |
157 |
{0, NULL, 0}, |
147 |
}; |
158 |
}; |
148 |
|
159 |
|
149 |
/* Device methods. */ |
160 |
/* Device methods. */ |
Lines 165-170
Link Here
|
165 |
imcsmb_pci_attach(device_t dev) |
176 |
imcsmb_pci_attach(device_t dev) |
166 |
{ |
177 |
{ |
167 |
struct imcsmb_pci_softc *sc; |
178 |
struct imcsmb_pci_softc *sc; |
|
|
179 |
struct imcsmb_pci_device *pci_device; |
180 |
uint16_t pci_dev_id; |
181 |
uint16_t base; |
168 |
device_t child; |
182 |
device_t child; |
169 |
int rc; |
183 |
int rc; |
170 |
int unit; |
184 |
int unit; |
Lines 174-179
Link Here
|
174 |
sc->dev = dev; |
188 |
sc->dev = dev; |
175 |
sc->semaphore = 0; |
189 |
sc->semaphore = 0; |
176 |
|
190 |
|
|
|
191 |
/* Walk the list of supported devices again to find the base address; |
192 |
* we only get here if imcsmb_pci_probe() found a match, so it |
193 |
* shouldn't be possible to end up with 'base' of 0; handle it anyway. |
194 |
*/ |
195 |
base = 0; |
196 |
pci_dev_id = pci_get_device(dev); |
197 |
for (pci_device = imcsmb_pci_devices; |
198 |
pci_device->base != 0; |
199 |
pci_device++) { |
200 |
if (pci_dev_id == pci_device->id) { |
201 |
base = pci_device->base; |
202 |
break; |
203 |
} |
204 |
} |
205 |
if (base == 0) { |
206 |
device_printf(dev, "Could not find register base address\n"); |
207 |
rc = ENXIO; |
208 |
goto out; |
209 |
} |
210 |
|
177 |
/* Create the imcsmbX children */ |
211 |
/* Create the imcsmbX children */ |
178 |
for (unit = 0; unit < 2; unit++) { |
212 |
for (unit = 0; unit < 2; unit++) { |
179 |
child = device_add_child(dev, "imcsmb", -1); |
213 |
child = device_add_child(dev, "imcsmb", -1); |
Lines 183-188
Link Here
|
183 |
rc = ENXIO; |
217 |
rc = ENXIO; |
184 |
goto out; |
218 |
goto out; |
185 |
} |
219 |
} |
|
|
220 |
/* Initialize the register array for the base address and |
221 |
* unit. |
222 |
*/ |
223 |
imcsmb_regs[unit].smb_stat = IMCSMB_REG_STATUS(base, unit); |
224 |
imcsmb_regs[unit].smb_cmd = IMCSMB_REG_COMMAND(base, unit); |
225 |
imcsmb_regs[unit].smb_cntl = IMCSMB_REG_CONTROL(base, unit); |
186 |
/* Set the child's ivars to point to the appropriate set of |
226 |
/* Set the child's ivars to point to the appropriate set of |
187 |
* the PCI device's registers. |
227 |
* the PCI device's registers. |
188 |
*/ |
228 |
*/ |