blob: 1f83448cd3db124ab482904db11221dac53276bd [file] [log] [blame]
Angel Ponsae593872020-04-04 18:50:57 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Marc Jones24484842017-05-04 21:17:45 -06002
Richard Spiegel0ad74ac2017-12-08 16:53:29 -07003#include <amdblocks/agesawrapper.h>
Kyösti Mälkkid7865202020-07-01 13:15:27 +03004#include <amdblocks/acpimmio.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +01005#include <console/console.h>
Marc Jones24484842017-05-04 21:17:45 -06006#include <device/pci_def.h>
7#include <device/device.h>
Aaron Durbin178d6442020-01-28 11:10:23 -07008#include <device/smbus_host.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -06009#include <soc/southbridge.h>
Marc Jonesafd03d82017-11-16 10:01:08 -070010#include <amdblocks/dimm_spd.h>
Marc Jones24484842017-05-04 21:17:45 -060011
Richard Spiegelc5ecd3e2017-09-29 10:05:35 -070012/*
Marc Jones24484842017-05-04 21:17:45 -060013 * readspd - Read one or more SPD bytes from a DIMM.
14 * Start with offset zero and read sequentially.
15 * Optimization relies on autoincrement to avoid
16 * sending offset for every byte.
17 * Reads 128 bytes in 7-8 ms at 400 KHz.
18 */
Richard Spiegelb40e1932018-10-24 12:51:21 -070019static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count)
Marc Jones24484842017-05-04 21:17:45 -060020{
Richard Spiegel77fee092017-11-10 08:33:57 -070021 uint8_t dev_addr;
Richard Spiegelcd04e312017-11-08 14:58:30 -070022 size_t index;
23 int error;
24 char *pbuf = buffer;
Marc Jones24484842017-05-04 21:17:45 -060025
26 printk(BIOS_SPEW, "-------------READING SPD-----------\n");
Richard Spiegelb40e1932018-10-24 12:51:21 -070027 printk(BIOS_SPEW, "SmbusSlave: 0x%08X, count: %zd\n",
28 SmbusSlaveAddress, count);
Marc Jones24484842017-05-04 21:17:45 -060029
Richard Spiegelcd04e312017-11-08 14:58:30 -070030 /*
31 * Convert received device address to the format accepted by
32 * do_smbus_read_byte and do_smbus_recv_byte.
33 */
34 dev_addr = (SmbusSlaveAddress >> 1);
Marc Jones24484842017-05-04 21:17:45 -060035
Richard Spiegelcd04e312017-11-08 14:58:30 -070036 /* Read the first SPD byte */
Kyösti Mälkkid7865202020-07-01 13:15:27 +030037 error = do_smbus_read_byte((uintptr_t)acpimmio_smbus, dev_addr, 0);
Richard Spiegelcd04e312017-11-08 14:58:30 -070038 if (error < 0) {
Marc Jones24484842017-05-04 21:17:45 -060039 printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
40 return error;
41 }
Elyes Haouas55d0f402022-07-16 09:53:05 +020042 *pbuf = (char)error;
Richard Spiegeld46bb6b2018-10-16 13:44:03 -070043 pbuf++;
Marc Jones24484842017-05-04 21:17:45 -060044
Richard Spiegelcd04e312017-11-08 14:58:30 -070045 /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */
46 for (index = 1 ; index < count ; index++) {
Kyösti Mälkkid7865202020-07-01 13:15:27 +030047 error = do_smbus_recv_byte((uintptr_t)acpimmio_smbus, dev_addr);
Richard Spiegelcd04e312017-11-08 14:58:30 -070048 if (error < 0) {
Marc Jones24484842017-05-04 21:17:45 -060049 printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
50 return error;
51 }
Elyes Haouas55d0f402022-07-16 09:53:05 +020052 *pbuf = (char)error;
Richard Spiegeld46bb6b2018-10-16 13:44:03 -070053 pbuf++;
Marc Jones24484842017-05-04 21:17:45 -060054 }
55 printk(BIOS_SPEW, "\n");
56 printk(BIOS_SPEW, "-------------FINISHED READING SPD-----------\n");
57
58 return 0;
59}
60
Marc Jonesafd03d82017-11-16 10:01:08 -070061int sb_read_spd(uint8_t spdAddress, char *buf, size_t len)
Marc Jones24484842017-05-04 21:17:45 -060062{
Richard Spiegelb40e1932018-10-24 12:51:21 -070063 return readspd(spdAddress, buf, len);
Marc Jones24484842017-05-04 21:17:45 -060064}