blob: a92f88018c545cde0dca890fe5fd36753db8c4f7 [file] [log] [blame]
Angel Pons0612b272020-04-05 15:46:56 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aamir Bohra52f29742017-04-19 18:19:14 +05302
Kyösti Mälkki75664672020-01-01 17:42:45 +02003#include <console/console.h>
Kyösti Mälkki75664672020-01-01 17:42:45 +02004#include <spd_bin.h>
Wim Vervoorn30e91492020-05-01 13:50:08 +02005#include <device/smbus_def.h>
Kyösti Mälkki1cae4542020-01-06 12:31:34 +02006#include <device/smbus_host.h>
Aamir Bohra52f29742017-04-19 18:19:14 +05307#include "smbuslib.h"
8
Kyösti Mälkki75664672020-01-01 17:42:45 +02009static void update_spd_len(struct spd_block *blk)
10{
11 u8 i, j = 0;
12 for (i = 0 ; i < CONFIG_DIMM_MAX; i++)
13 if (blk->spd_array[i] != NULL)
14 j |= blk->spd_array[i][SPD_DRAM_TYPE];
15
16 /* If spd used is DDR4, then its length is 512 byte. */
17 if (j == SPD_DRAM_DDR4)
18 blk->len = SPD_PAGE_LEN_DDR4;
19 else
20 blk->len = SPD_PAGE_LEN;
21}
22
23static void smbus_read_spd(u8 *spd, u8 addr)
24{
25 u16 i;
26 u8 step = 1;
27
28 if (CONFIG(SPD_READ_BY_WORD))
29 step = sizeof(uint16_t);
30
31 for (i = 0; i < SPD_PAGE_LEN; i += step) {
32 if (CONFIG(SPD_READ_BY_WORD))
33 ((u16*)spd)[i / sizeof(uint16_t)] =
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020034 smbus_read_word(addr, i);
Kyösti Mälkki75664672020-01-01 17:42:45 +020035 else
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020036 spd[i] = smbus_read_byte(addr, i);
Kyösti Mälkki75664672020-01-01 17:42:45 +020037 }
38}
39
Eric Lai0ee9b14c2020-04-21 15:32:20 +080040/* return -1 if SMBus errors otherwise return 0 */
41static int get_spd(u8 *spd, u8 addr)
Kyösti Mälkki75664672020-01-01 17:42:45 +020042{
Eric Lai0ee9b14c2020-04-21 15:32:20 +080043 /* If address is not 0, it will return CB_ERR(-1) if no dimm */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020044 if (smbus_read_byte(addr, 0) < 0) {
Kyösti Mälkki75664672020-01-01 17:42:45 +020045 printk(BIOS_INFO, "No memory dimm at address %02X\n",
46 addr << 1);
Eric Lai0ee9b14c2020-04-21 15:32:20 +080047 return -1;
Kyösti Mälkki75664672020-01-01 17:42:45 +020048 }
Wim Vervoorn30e91492020-05-01 13:50:08 +020049
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020050 if (i2c_eeprom_read(addr, 0, SPD_PAGE_LEN, spd) < 0) {
Wim Vervoorn30e91492020-05-01 13:50:08 +020051 printk(BIOS_INFO, "do_i2c_eeprom_read failed, using fallback\n");
52 smbus_read_spd(spd, addr);
53 }
Kyösti Mälkki75664672020-01-01 17:42:45 +020054
55 /* Check if module is DDR4, DDR4 spd is 512 byte. */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020056 if (spd[SPD_DRAM_TYPE] == SPD_DRAM_DDR4 && CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) {
Kyösti Mälkki75664672020-01-01 17:42:45 +020057 /* Switch to page 1 */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020058 smbus_write_byte(SPD_PAGE_1, 0, 0);
Wim Vervoorn30e91492020-05-01 13:50:08 +020059
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020060 if (i2c_eeprom_read(addr, 0, SPD_PAGE_LEN, spd + SPD_PAGE_LEN) < 0) {
Wim Vervoorn30e91492020-05-01 13:50:08 +020061 printk(BIOS_INFO, "do_i2c_eeprom_read failed, using fallback\n");
62 smbus_read_spd(spd + SPD_PAGE_LEN, addr);
63 }
Kyösti Mälkki75664672020-01-01 17:42:45 +020064 /* Restore to page 0 */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +020065 smbus_write_byte(SPD_PAGE_0, 0, 0);
Kyösti Mälkki75664672020-01-01 17:42:45 +020066 }
Eric Lai0ee9b14c2020-04-21 15:32:20 +080067 return 0;
Kyösti Mälkki75664672020-01-01 17:42:45 +020068}
69
70static u8 spd_data[CONFIG_DIMM_MAX * CONFIG_DIMM_SPD_SIZE];
71
72void get_spd_smbus(struct spd_block *blk)
73{
74 u8 i;
75 for (i = 0 ; i < CONFIG_DIMM_MAX; i++) {
Eric Lai0ee9b14c2020-04-21 15:32:20 +080076 if (blk->addr_map[i] == 0) {
77 blk->spd_array[i] = NULL;
78 continue;
79 }
80
81 if (get_spd(&spd_data[i * CONFIG_DIMM_SPD_SIZE], blk->addr_map[i]) == 0)
82 blk->spd_array[i] = &spd_data[i * CONFIG_DIMM_SPD_SIZE];
83 else
84 blk->spd_array[i] = NULL;
Kyösti Mälkki75664672020-01-01 17:42:45 +020085 }
86
87 update_spd_len(blk);
88}
Jamie Chen7adcfde2020-04-16 01:20:29 +080089
90/*
91 * get_spd_sn returns the SODIMM serial number. It only supports DDR3 and DDR4.
92 * return CB_SUCCESS, sn is the serial number and sn=0xffffffff if the dimm is not present.
93 * return CB_ERR, if dram_type is not supported or addr is a zero.
94 */
95enum cb_err get_spd_sn(u8 addr, u32 *sn)
96{
97 u8 i;
98 u8 dram_type;
99 int smbus_ret;
100
101 /* addr is not a zero. */
102 if (addr == 0x0)
103 return CB_ERR;
104
105 /* If dimm is not present, set sn to 0xff. */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +0200106 smbus_ret = smbus_read_byte(addr, SPD_DRAM_TYPE);
Jamie Chen7adcfde2020-04-16 01:20:29 +0800107 if (smbus_ret < 0) {
Kane Chenbe9cef92022-05-12 16:58:38 +0800108 printk(BIOS_INFO, "No memory dimm at address %02X\n", addr << 1);
Jamie Chen7adcfde2020-04-16 01:20:29 +0800109 *sn = 0xffffffff;
110 return CB_SUCCESS;
111 }
112
113 dram_type = smbus_ret & 0xff;
114
115 /* Check if module is DDR4, DDR4 spd is 512 byte. */
116 if (dram_type == SPD_DRAM_DDR4 && CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) {
117 /* Switch to page 1 */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +0200118 smbus_write_byte(SPD_PAGE_1, 0, 0);
Jamie Chen7adcfde2020-04-16 01:20:29 +0800119
120 for (i = 0; i < SPD_SN_LEN; i++)
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +0200121 *((u8 *)sn + i) = smbus_read_byte(addr,
Jamie Chen7adcfde2020-04-16 01:20:29 +0800122 i + DDR4_SPD_SN_OFF);
123
124 /* Restore to page 0 */
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +0200125 smbus_write_byte(SPD_PAGE_0, 0, 0);
Jamie Chen7adcfde2020-04-16 01:20:29 +0800126 } else if (dram_type == SPD_DRAM_DDR3) {
127 for (i = 0; i < SPD_SN_LEN; i++)
Kyösti Mälkki1a1b04e2020-01-07 22:34:33 +0200128 *((u8 *)sn + i) = smbus_read_byte(addr,
Jamie Chen7adcfde2020-04-16 01:20:29 +0800129 i + DDR3_SPD_SN_OFF);
130 } else {
131 printk(BIOS_ERR, "Unsupported dram_type\n");
132 return CB_ERR;
133 }
134
135 return CB_SUCCESS;
136}