i2c-imc-skylake: implement Receive Byte and Send Byte
The engine encodes an address-only transaction in command word bit 18, which is what SMBus Receive Byte and Send Byte need and what was missing for ee1004 to bind. The bit is not documented for the PCU function. It was located by structure rather than by sweeping: SMBCMD on the iMC channel function (datasheet ref. 614073 section 3.1.8) places PNTR_SEL immediately above WORD_ACCESS, and word access here is bit 17. Bit 17 had itself been unknown until it turned out to be word access, and an earlier sweep of this register covered bits 31:20 only, so 18 was untried rather than already ruled out. Validated against the device rather than against the register. An EEPROM auto-increments its pointer after a read, so priming the pointer and repeating the read with the bit set has a predicted answer: the next byte, not the one named. Eight consecutive reads returned SPD bytes 0x01 through 0x08 in order, matching an ordinary dump. Send Byte was confirmed on the DDR4 page-select addresses, which hold a latch and store no data, so the page state is itself the readout. Result: ee1004 binds on all four SPD addresses and decode-dimms decodes all four modules with both CRCs valid on each. The part number comes off page 1, so the page select runs end to end. The four module serial numbers are unchanged from the baseline recorded before this series. SMBus Quick stays unimplemented. Beyond having no obvious encoding, a write into the 0x30-0x37 range is how an EE1004 SPD is write-protected, permanently on many modules, so an adapter on the memory bus should not advertise a probe that writes. i2cdetect scans in read mode. Also fix test-smoke.sh resolving the module through modinfo, which silently tested the installed DKMS build instead of the one just compiled. It now prefers the local .ko and prints which it loaded. Smoke suite: 19 passed, 0 failed. checkpatch --strict 0/0/0, in-tree W=1 and Sparse clean.
This commit is contained in:
@@ -64,3 +64,72 @@ Two results matter:
|
||||
|
||||
Requirements: `msr-tools` (`rdmsr`), `pciutils` (`setpci`, `lspci`), and the
|
||||
`msr` module (`modprobe msr`).
|
||||
|
||||
## 4. `probe-cf8-transaction.sh` — does CF8/CFC start a transfer? (WRITES TO HARDWARE)
|
||||
|
||||
Follow-up to §3. `probe-cf8-write.sh` shows whether the register accepts a
|
||||
value; this shows whether the engine acts on it, by setting the GO bit for a
|
||||
read of an unpopulated address and watching STATUS.
|
||||
|
||||
```bash
|
||||
sudo ./tools/probe-cf8-transaction.sh --i-understand
|
||||
```
|
||||
|
||||
It does start one. That result retired the plan to reach these registers
|
||||
through ECAM with a PCI-core change, and the driver uses the ordinary config
|
||||
accessors.
|
||||
|
||||
## 5. `probe-imc-documented.sh` — the interface Intel documents (WRITES TO HARDWARE)
|
||||
|
||||
Issues a read through `SMB_STAT`/`SMBCMD`/`SMBCNTL` on the iMC channel
|
||||
functions (`8086:2040`), the interface the datasheet describes, rather than the
|
||||
PCU registers this driver uses.
|
||||
|
||||
```bash
|
||||
sudo ./tools/probe-imc-documented.sh --i-understand
|
||||
```
|
||||
|
||||
On the development board it reports `RDO=1, SBE=0, RDATA=0x00` identically for
|
||||
a populated 0x50, a populated 0x52 and an absent 0x57: it completes but cannot
|
||||
tell a populated slot from an empty one, so it is not reaching this bus.
|
||||
|
||||
## 6. `probe-pntr-sel.sh` — find the address-only bit (read-only on the bus)
|
||||
|
||||
Finds the command-word bit that suppresses the register byte, which is what
|
||||
SMBus Receive Byte and Send Byte need.
|
||||
|
||||
```bash
|
||||
sudo ./tools/probe-pntr-sel.sh --i-understand --channel 1
|
||||
```
|
||||
|
||||
Not a blind sweep. An EEPROM auto-increments its pointer after a read, so
|
||||
priming the pointer with an ordinary read and then repeating it with the
|
||||
candidate bit set has a predicted answer: the *next* byte, not the one named.
|
||||
The script checks that prediction at two different offsets and then walks eight
|
||||
consecutive reads, which an ordinary dump must reproduce exactly.
|
||||
|
||||
The answer on this engine is bit 18, matching the position of `PNTR_SEL`
|
||||
relative to `WORD_ACCESS` in the documented `SMBCMD` layout. Reads only, and
|
||||
never to the page-select addresses, so the DDR4 page latch does not move.
|
||||
|
||||
## 7. `probe-send-byte.sh` — the write half (WRITES TO HARDWARE)
|
||||
|
||||
Confirms the same bit produces a Send Byte, against the page-select addresses
|
||||
`0x36`/`0x37`. Those hold a latch and store no data, so the only thing a write
|
||||
there can do is choose which half of the SPD is visible — and that choice is
|
||||
itself the readout, since byte 0x00 is the JEDEC `0x23` on page 0 and something
|
||||
else on page 1. Nothing is written to `0x50`-`0x57`.
|
||||
|
||||
```bash
|
||||
sudo ./tools/probe-send-byte.sh --i-understand --channel 0 --restore
|
||||
```
|
||||
|
||||
`--restore` is the safe first run: it targets a channel already stuck on page 1
|
||||
and selects page 0, so a working Send Byte repairs that channel and a broken one
|
||||
leaves it exactly as found. There is no outcome worse than the starting state.
|
||||
`--flip` does the full round trip on a healthy channel, after `--restore` has
|
||||
shown the encoding works.
|
||||
|
||||
A channel found on page 1 is not a fault of this driver: `ee1004`, and
|
||||
OpenRGB's `DDR4DirectAccessor::set_page()`, both select a page and leave it
|
||||
selected.
|
||||
|
||||
Reference in New Issue
Block a user