blob: ed73a6e51befdead4c74bc28df40b104a238978b [file] [log] [blame]
Marc Jones24484842017-05-04 21:17:45 -06001/*
2 * This file is part of the coreboot project.
3 *
Marc Jonesafd03d82017-11-16 10:01:08 -07004 * Copyright (C) 2012, 2017 Advanced Micro Devices, Inc.
Marc Jones24484842017-05-04 21:17:45 -06005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Richard Spiegel0ad74ac2017-12-08 16:53:29 -070016#include <amdblocks/agesawrapper.h>
Elyes HAOUAS20eaef02019-03-29 17:45:28 +010017#include <console/console.h>
Marc Jones24484842017-05-04 21:17:45 -060018#include <device/pci_def.h>
19#include <device/device.h>
Marc Jonesdfeb1c42017-08-07 19:08:24 -060020#include <soc/southbridge.h>
Richard Spiegelc5ecd3e2017-09-29 10:05:35 -070021#include <soc/smbus.h>
Marc Jonesafd03d82017-11-16 10:01:08 -070022#include <amdblocks/dimm_spd.h>
Marc Jones24484842017-05-04 21:17:45 -060023
Richard Spiegelc5ecd3e2017-09-29 10:05:35 -070024/*
Marc Jones24484842017-05-04 21:17:45 -060025 * readspd - Read one or more SPD bytes from a DIMM.
26 * Start with offset zero and read sequentially.
27 * Optimization relies on autoincrement to avoid
28 * sending offset for every byte.
29 * Reads 128 bytes in 7-8 ms at 400 KHz.
30 */
Richard Spiegelb40e1932018-10-24 12:51:21 -070031static int readspd(uint8_t SmbusSlaveAddress, char *buffer, size_t count)
Marc Jones24484842017-05-04 21:17:45 -060032{
Richard Spiegel77fee092017-11-10 08:33:57 -070033 uint8_t dev_addr;
Richard Spiegelcd04e312017-11-08 14:58:30 -070034 size_t index;
35 int error;
36 char *pbuf = buffer;
Marc Jones24484842017-05-04 21:17:45 -060037
38 printk(BIOS_SPEW, "-------------READING SPD-----------\n");
Richard Spiegelb40e1932018-10-24 12:51:21 -070039 printk(BIOS_SPEW, "SmbusSlave: 0x%08X, count: %zd\n",
40 SmbusSlaveAddress, count);
Marc Jones24484842017-05-04 21:17:45 -060041
Richard Spiegelcd04e312017-11-08 14:58:30 -070042 /*
43 * Convert received device address to the format accepted by
44 * do_smbus_read_byte and do_smbus_recv_byte.
45 */
46 dev_addr = (SmbusSlaveAddress >> 1);
Marc Jones24484842017-05-04 21:17:45 -060047
Richard Spiegelcd04e312017-11-08 14:58:30 -070048 /* Read the first SPD byte */
Richard Spiegelb40e1932018-10-24 12:51:21 -070049 error = do_smbus_read_byte(SMBUS_MMIO_BASE, dev_addr, 0);
Richard Spiegelcd04e312017-11-08 14:58:30 -070050 if (error < 0) {
Marc Jones24484842017-05-04 21:17:45 -060051 printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
52 return error;
53 }
Richard Spiegeld46bb6b2018-10-16 13:44:03 -070054 *pbuf = (char) error;
55 pbuf++;
Marc Jones24484842017-05-04 21:17:45 -060056
Richard Spiegelcd04e312017-11-08 14:58:30 -070057 /* Read the remaining SPD bytes using do_smbus_recv_byte for speed */
58 for (index = 1 ; index < count ; index++) {
Richard Spiegelb40e1932018-10-24 12:51:21 -070059 error = do_smbus_recv_byte(SMBUS_MMIO_BASE, dev_addr);
Richard Spiegelcd04e312017-11-08 14:58:30 -070060 if (error < 0) {
Marc Jones24484842017-05-04 21:17:45 -060061 printk(BIOS_ERR, "-------------SPD READ ERROR-----------\n");
62 return error;
63 }
Richard Spiegeld46bb6b2018-10-16 13:44:03 -070064 *pbuf = (char) error;
65 pbuf++;
Marc Jones24484842017-05-04 21:17:45 -060066 }
67 printk(BIOS_SPEW, "\n");
68 printk(BIOS_SPEW, "-------------FINISHED READING SPD-----------\n");
69
70 return 0;
71}
72
Marc Jonesafd03d82017-11-16 10:01:08 -070073int sb_read_spd(uint8_t spdAddress, char *buf, size_t len)
Marc Jones24484842017-05-04 21:17:45 -060074{
Richard Spiegelb40e1932018-10-24 12:51:21 -070075 return readspd(spdAddress, buf, len);
Marc Jones24484842017-05-04 21:17:45 -060076}