1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/dram/rcd.h>
9 * Registering Clock Driver (RCD) is responsible for driving address and control
10 * nets on RDIMM and LRDIMM applications. Its operation is configurable by a set
11 * of Register Control Words (RCWs). There are two ways of accessing RCWs:
12 * in-band on the memory channel as an MRS commands ("MR7") or through I2C.
14 * From JESD82-31: "For changes to the control word setting, (...) the
15 * controller needs to wait tMRD after _the last control word access_, before
16 * further access _to the DRAM_ can take place". MRS is passed to rank 0 of the
17 * DRAM, but MR7 is reserved so it is ignored by DRAM. tMRD (8nCK) applies here,
18 * unless longer delay is needed for RCWs which control the clock timing (see
19 * JESD82-31 for list of such). This makes sense from DRAMs point of view,
20 * however we are talking to the Registering Clock Driver (RCD), not DRAM. From
21 * parts marked in the sentence above one may assume that only one delay at the
22 * end is necessary and RCWs can be written back to back; however, in the same
23 * document in table 141 tMRD is defined as "Number of clock cycles between two
24 * control word accesses, MRS accesses, or any DRAM commands".
26 * I2C access to RCWs is required to support byte (8b), word (16b) and double
27 * word (32b) write size. Bigger blocks are not required. Reads must always be
28 * 32b, 32b-aligned blocks, even when reading just one RCW. RCD ignores the two
29 * lowest bits so unaligned accesses would return shifted values. RCWs are
30 * tightly packed in I2C space, so it is not possible to write just one 4b RCW
31 * without writing its neighbor. This is especially important for F0RC06,
32 * Command Space Control Word, as it is able to reset the state of RCD. For this
33 * reason, the mentioned register has NOP command (all 1's). JESD82-31 does not
34 * specify timeouts required for such multi-RCWs writes, or any other writes.
35 * These are not MRS accesses, so it would be strange to apply those timeouts.
36 * Perhaps only the registers that actually change the clock settings require
37 * time to stabilize. On the other hand, I2C is relatively slow, so it is
38 * possible that the write itself is long enough.
40 * RCD I2C address is 0xBx (or 0x58 + DIMM number, depending on convention), it
41 * is located on the same bus as SPD. It uses a bus command encoding, see
42 * section 3.3 in JESD82-31 for description of reading and writing register
45 * This file includes only functions for access through I2C - it is generic,
46 * while MRS commands are passed to memory controller registers in an
47 * implementation specific way.
50 #define RCD_CMD_BEGIN 0x80
51 #define RCD_CMD_END 0x40
52 #define RCD_CMD_PEC 0x10
53 #define RCD_CMD_RD_DWORD 0x00
54 #define RCD_CMD_WR_BYTE 0x04
55 #define RCD_CMD_WR_WORD 0x08
56 #define RCD_CMD_WR_DWORD 0x0C
57 #define RCD_CMD_BUS_BYTE 0x00
58 #define RCD_CMD_BUS_BLOCK 0x02
60 /* Shorthand for block transfers */
61 #define RCD_CMD_BLOCK (RCD_CMD_BEGIN | RCD_CMD_END | RCD_CMD_BUS_BLOCK)
63 /* Excluding size of data */
64 #define RCD_CMD_BYTES 4
66 /* Use byte fields to get rid of endianness issues. */
69 uint8_t bytes
; /* From next byte up to PEC (excluding) */
74 union { /* Not used for reads, can use 1, 2 or 4 for writes */
81 #define RCD_STS_SUCCESS 0x01
82 #define RCD_STS_INTERNAL_TARGET_ABORT 0x10
84 /* Always 4 bytes data + status (for block commands) */
85 #define RCD_RSP_BYTES 5
88 uint8_t bytes
; /* From next byte up to PEC (excluding) */
97 /* Reads a register storing its value in the host's byte order. Returns non-zero on success. */
98 static int rcd_readd(unsigned int bus
, uint8_t slave
, uint8_t reg
, uint32_t *data
)
100 struct i2c_msg seg
[2];
101 struct rcd_i2c_cmd cmd
= {
102 .cmd
= RCD_CMD_BLOCK
| RCD_CMD_RD_DWORD
,
103 .bytes
= RCD_CMD_BYTES
,
106 struct rcd_i2c_rsp rsp
= { 0xaa, 0x55 };
109 seg
[0].slave
= slave
;
110 seg
[0].buf
= (uint8_t *)&cmd
;
111 seg
[0].len
= cmd
.bytes
+ 2; /* + .cmd and .bytes fields */
113 i2c_transfer(bus
, seg
, 1);
115 seg
[0].len
= 1; /* Send just the command again */
116 seg
[1].flags
= I2C_M_RD
;
117 seg
[1].slave
= slave
;
118 seg
[1].buf
= (uint8_t *)&rsp
;
119 seg
[1].len
= RCD_RSP_BYTES
+ 1; /* + .bytes field */
121 i2c_transfer(bus
, seg
, ARRAY_SIZE(seg
));
123 /* Data is sent MSB to LSB, i.e. higher registers to lower. */
124 *data
= be32toh(rsp
.ddata
);
126 return rsp
.status
== RCD_STS_SUCCESS
;
129 static int rcd_writed(unsigned int bus
, uint8_t slave
, uint8_t reg
, uint32_t data
)
132 struct rcd_i2c_cmd cmd
= {
133 .cmd
= RCD_CMD_BLOCK
| RCD_CMD_WR_DWORD
,
134 .bytes
= RCD_CMD_BYTES
+ sizeof(data
),
136 /* Data is sent MSB to LSB, i.e. higher registers to lower. */
137 .ddata
= htobe32(data
)
142 seg
.buf
= (uint8_t *)&cmd
;
143 seg
.len
= cmd
.bytes
+ 2; /* + .cmd and .bytes fields */
145 return i2c_transfer(bus
, &seg
, 1);
148 static int rcd_writeb(unsigned int bus
, uint8_t slave
, uint8_t reg
, uint8_t data
)
151 struct rcd_i2c_cmd cmd
= {
152 .cmd
= RCD_CMD_BLOCK
| RCD_CMD_WR_BYTE
,
153 .bytes
= RCD_CMD_BYTES
+ sizeof(data
),
160 seg
.buf
= (uint8_t *)&cmd
;
161 seg
.len
= cmd
.bytes
+ 2; /* + .cmd and .bytes fields */
163 return i2c_transfer(bus
, &seg
, 1);
166 int rcd_write_reg(unsigned int bus
, uint8_t slave
, enum rcw_idx reg
,
169 if (reg
< F0RC00_01
|| reg
> F0RCFx
) {
170 printk(BIOS_ERR
, "Trying to write to illegal RCW %#2.2x\n",
175 return rcd_writeb(bus
, slave
, reg
, data
);
178 int rcd_write_32b(unsigned int bus
, uint8_t slave
, enum rcw_idx reg
,
181 if (reg
< F0RC00_01
|| reg
> F0RCFx
) {
182 printk(BIOS_ERR
, "Trying to write to illegal RCW %#2.2x\n",
189 * RCD would silently mask out the lowest bits, assume that this
190 * is not what caller wanted.
192 printk(BIOS_ERR
, "Unaligned RCW %#2.2x, aborting\n", reg
);
196 return rcd_writed(bus
, slave
, reg
, data
);
199 void dump_rcd(unsigned int bus
, u8 addr
)
201 /* Can only read in 32b chunks */
202 uint8_t buf
[RCW_ALL_ALIGNED
];
205 for (i
= 0; i
< RCW_ALL_ALIGNED
; i
+= sizeof(uint32_t)) {
207 if (!rcd_readd(bus
, addr
, i
, &data
)) {
208 printk(BIOS_ERR
, "Failed to read RCD (%d-%02x) at offset %#2.2x\n",
212 /* We want to dump memory the way it's stored, so make sure it's in LE. */
213 *(uint32_t *)&buf
[i
] = htole32(data
);
216 printk(BIOS_DEBUG
, "RCD dump for I2C address %#2.2x:\n", addr
);
217 hexdump(buf
, sizeof(buf
));