acpi: Add IORT helper functions
[coreboot2.git] / src / drivers / i2c / at24rf08c / lenovo_serials.c
blobdd09dda7fe71638eb5cce7696c98be2939dd1b07
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <build.h>
4 #include <types.h>
5 #include <string.h>
6 #include <device/device.h>
7 #include <device/smbus.h>
8 #include <smbios.h>
9 #include <console/console.h>
10 #include <version.h>
11 #include "lenovo.h"
13 #define ERROR_STRING "*INVALID*"
15 static struct device *at24rf08c_find_bank(u8 bank)
17 struct device *dev;
18 dev = dev_find_slot_on_smbus(1, 0x54 | bank);
19 if (!dev)
20 printk(BIOS_WARNING, "EEPROM not found\n");
21 return dev;
24 static int at24rf08c_read_byte(struct device *dev, u8 addr)
26 int t = -1;
27 int j;
29 /* After a register write AT24RF08C (which we issued in init function)
30 sometimes stops responding. Retry several times in case of failure.
32 for (j = 0; j < 100; j++) {
33 t = smbus_read_byte(dev, addr);
34 if (t >= 0)
35 return t;
38 return t;
41 static void at24rf08c_read_string_dev(struct device *dev, u8 start,
42 u8 len, char *result)
44 int i;
45 for (i = 0; i < len; i++) {
46 int t = at24rf08c_read_byte(dev, start + i);
48 if (t < 0x20 || t > 0x7f) {
49 memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
50 return;
52 result[i] = t;
54 result[len] = '\0';
57 static void at24rf08c_read_string(u8 bank, u8 start, u8 len, char *result)
59 struct device *dev;
61 dev = at24rf08c_find_bank(bank);
62 if (dev == NULL) {
63 printk(BIOS_WARNING, "EEPROM not found\n");
64 memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
65 return;
68 at24rf08c_read_string_dev(dev, start, len, result);
71 const char *smbios_mainboard_serial_number(void)
73 static char result[12];
74 static int already_read;
76 if (already_read)
77 return result;
79 memset(result, 0, sizeof(result));
80 at24rf08c_read_string(0, 0x2e, 7, result);
82 already_read = 1;
83 return result;
86 const char *lenovo_mainboard_partnumber(void)
88 static char result[12];
89 static int already_read;
91 if (already_read)
92 return result;
94 memset(result, 0, sizeof(result));
95 at24rf08c_read_string(0, 0x27, 7, result);
97 already_read = 1;
98 return result;
101 const char *smbios_mainboard_product_name(void)
103 return lenovo_mainboard_partnumber();
106 void smbios_system_set_uuid(u8 *uuid)
108 static char result[16];
109 unsigned int i;
110 static int already_read;
111 struct device *dev;
112 const int remap[16] = {
113 /* UUID byteswap. */
114 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15
117 if (already_read) {
118 memcpy(uuid, result, 16);
119 return;
122 memset(result, 0, sizeof(result));
124 dev = dev_find_slot_on_smbus(1, 0x56);
125 if (dev == NULL) {
126 printk(BIOS_WARNING, "EEPROM not found\n");
127 already_read = 1;
128 memset(uuid, 0, 16);
129 return;
132 for (i = 0; i < 16; i++) {
133 int t;
134 int j;
135 /* After a register write AT24RF08C (which we issued in init function) sometimes stops responding.
136 Retry several times in case of failure.
138 for (j = 0; j < 100; j++) {
139 t = smbus_read_byte(dev, 0x12 + i);
140 if (t >= 0)
141 break;
143 if (t < 0) {
144 memset(result, 0, sizeof(result));
145 break;
147 result[remap[i]] = t;
150 already_read = 1;
152 memcpy(uuid, result, 16);
155 const char *smbios_mainboard_version(void)
157 static char result[100];
158 static int already_read;
159 struct device *dev;
160 int len;
162 if (already_read)
163 return result;
165 memset(result, 0, sizeof(result));
167 dev = at24rf08c_find_bank(2);
168 if (dev == NULL) {
169 memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
170 return result;
173 len = at24rf08c_read_byte(dev, 0x26) - 2;
174 if (len < 0 || len > sizeof(result) - 1) {
175 memcpy(result, ERROR_STRING, sizeof(ERROR_STRING));
176 return result;
179 at24rf08c_read_string_dev(dev, 0x27, len, result);
181 already_read = 1;
182 return result;
185 const char *smbios_mainboard_bios_version(void)
187 /* Satisfy thinkpad_acpi. */
188 if (strlen(CONFIG_LOCALVERSION))
189 return "CBET4000 " CONFIG_LOCALVERSION;
191 return "CBET4000 " COREBOOT_VERSION;
194 const char *smbios_mainboard_manufacturer(void)
196 return "LENOVO";