Skip to content

Commit 97aa879

Browse files
committed
capability: add 1Mhz i2c, AVS, num format
Based on the PMBus specifiations, add few cases that were not clearly described by the Flex/BMR documentation.
1 parent ecd26a0 commit 97aa879

File tree

3 files changed

+80
-33
lines changed

3 files changed

+80
-33
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ Then use `operation set --margin high|low` during validation.
355355

356356
```bash
357357
bmr ... capability get
358-
bmr ... capability check --need-pec on|off --min-speed 100|400 --need-alert on|off [--strict]
358+
bmr ... capability check --need-pec on|off --min-speed 100|400|1000 --need-alert on|off [--strict]
359359
```
360360

361361
### What it does

src/capability_cmd.c

Lines changed: 78 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,48 +8,61 @@
88
#include <stdlib.h>
99
#include <errno.h>
1010

11-
static void usage_cap_short(void) {
11+
static void
12+
usage_cap_short(void) {
1213
fprintf(stderr,
1314
"capability get\n"
14-
"capability check [--need-pec on|off] [--min-speed 100|400] [--need-alert on|off] [--strict]\n"
15+
"capability check [--need-pec on|off] [--min-speed 100|400|1000] [--need-alert on|off]\n"
16+
" [--need-fp on|off] [--need-avsbus on|off] [--strict]\n"
1517
"capability help\n"
1618
);
1719
}
1820

19-
static void usage_cap_long(void) {
21+
static void
22+
usage_cap_long(void) {
2023
fprintf(stderr,
2124
"\n"
2225
"NAME\n"
2326
" capability — Decode PMBUS_CAPABILITY (0x19) and optionally check requirements\n"
2427
"\n"
2528
"SYNOPSIS\n"
2629
" capability get\n"
27-
" capability check [--need-pec on|off] [--min-speed 100|400] [--need-alert on|off] [--strict]\n"
30+
" capability check [--need-pec on|off] [--min-speed 100|400|1000]\n"
31+
" [--need-alert on|off] [--need-fp on|off] [--need-avsbus on|off]\n"
32+
" [--strict]\n"
2833
"\n"
2934
"DESCRIPTION (0x19 is a READ BYTE)\n"
3035
" Bit 7 : PEC support (1 = device supports SMBus Packet Error Checking)\n"
31-
" Bits 6:5: Max bus speed code (00=100 kHz, 01=400 kHz, 10/11 reserved)\n"
36+
" Bits 6:5: Max bus speed code (00=100 kHz, 01=400 kHz, 10=1 MHz, 11=reserved)\n"
3237
" Bit 4 : SMBALERT# support (1 = device supports alert protocol/pin)\n"
33-
" Bits 3:0: Reserved (should be 0)\n"
38+
" Bit 3 : Numeric format (0 = LINEAR/ULINEAR/DIRECT; 1 = IEEE-754 half-precision)\n"
39+
" Bit 2 : AVSBus support (1 = device supports AVSBus)\n"
40+
" Bits 1:0: Reserved (should be 0)\n"
3441
"\n"
3542
"OUTPUT (JSON) TBC\n"
3643
" capability get ->\n"
3744
" {\n"
3845
" \"capability\": {\n"
3946
" \"raw\": <byte>,\n"
4047
" \"pec_supported\": true|false,\n"
41-
" \"max_bus_speed\": { \"code\": 0|1|2|3, \"khz\": 100|400|null, \"text\": \"...\" },\n"
48+
" \"max_bus_speed\": { \"code\": 0|1|2|3, \"khz\": 100|400|1000|null, \"text\": \"...\" },\n"
4249
" \"smbalert_supported\": true|false,\n"
43-
" \"reserved_low_bits\": <0..15>\n"
50+
" \"numeric_format\": \"linear/direct\" | \"ieee754_half\",\n"
51+
" \"avsbus_supported\": true|false,\n"
52+
" \"reserved_low_bits\": <0..3>\n"
4453
" }\n"
4554
" }\n"
4655
"\n"
4756
" capability check -> adds\n"
48-
" \"checks\": { \"pec_ok\": bool, \"bus_speed_ok\": bool, \"alert_ok\": bool, \"reserved_low_zero\": bool },\n"
57+
" \"checks\": {\n"
58+
" \"pec_ok\": bool, \"bus_speed_ok\": bool, \"alert_ok\": bool,\n"
59+
" \"numeric_format_ok\": bool, \"avsbus_ok\": bool,\n"
60+
" \"reserved_low_zero\": bool, \"speed_code_valid\": bool\n"
61+
" },\n"
4962
" \"mismatches\": [ list of failed checks ]\n"
5063
"\n"
5164
"NOTES\n"
52-
" * --strict also fails if reserved low bits (3..0) are non-zero.\n"
65+
" * --strict fails if reserved low bits (1..0) are non-zero and if speed code==3 (reserved).\n"
5366
" * This command intentionally does NOT include any MFR_* identity fields.\n"
5467
"\n"
5568
);
@@ -68,24 +81,24 @@ speed_text(unsigned code, int *khz_out) {
6881
return "400 kHz";
6982
case 2:
7083
if (khz_out)
71-
*khz_out = -1;
72-
return "reserved";
84+
*khz_out = 1000;
85+
return "1 MHz";
7386
case 3:
87+
default:
7488
if (khz_out)
7589
*khz_out = -1;
7690
return "reserved";
7791
}
78-
if (khz_out)
79-
*khz_out = -1;
80-
return "reserved";
8192
}
8293

8394
static void
8495
decode_cap(uint8_t cap, json_t *dst) {
8596
unsigned pec = (cap >> 7) & 0x1u;
8697
unsigned spd = (cap >> 5) & 0x3u;
8798
unsigned sal = (cap >> 4) & 0x1u;
88-
unsigned rsv = cap & 0x0Fu;
99+
unsigned num = (cap >> 3) & 0x1u;
100+
unsigned avs = (cap >> 2) & 0x1u;
101+
unsigned rsv = cap & 0x03u; /* only bits [1:0] are reserved */
89102

90103
int khz = -1;
91104
const char *txt = speed_text(spd, &khz);
@@ -95,16 +108,13 @@ decode_cap(uint8_t cap, json_t *dst) {
95108

96109
json_t *bs = json_object();
97110
json_object_set_new(bs, "code", json_integer(spd));
98-
99-
if (khz > 0)
100-
json_object_set_new(bs, "khz", json_integer(khz));
101-
else
102-
json_object_set_new(bs, "khz", json_null());
103-
111+
json_object_set_new(bs, "khz", (khz > 0) ? json_integer(khz) : json_null());
104112
json_object_set_new(bs, "text", json_string(txt));
105113
json_object_set_new(dst, "max_bus_speed", bs);
106114

107115
json_object_set_new(dst, "smbalert_supported", json_boolean(sal));
116+
json_object_set_new(dst, "numeric_format", json_string(num ? "ieee754_half" : "linear/direct"));
117+
json_object_set_new(dst, "avsbus_supported", json_boolean(avs));
108118
json_object_set_new(dst, "reserved_low_bits", json_integer(rsv));
109119
}
110120

@@ -115,6 +125,23 @@ add_check(json_t *checks, const char *k, int ok, json_t *mism) {
115125
json_array_append_new(mism, json_string(k));
116126
}
117127

128+
static int
129+
parse_onoff(const char *s, int *out) {
130+
if (!s || !out)
131+
return -1;
132+
133+
if (!strcmp(s, "on") || !strcmp(s, "yes") || !strcmp(s, "true")) {
134+
*out = 1;
135+
return 0;
136+
}
137+
if (!strcmp(s, "off") || !strcmp(s, "no") || !strcmp(s, "false")) {
138+
*out = 0;
139+
return 0;
140+
}
141+
142+
return -1;
143+
}
144+
118145
int
119146
cmd_capability(int fd, int argc, char *const *argv, int pretty) {
120147
if (argc == 0) {
@@ -147,6 +174,7 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
147174
/* capability check [opts] */
148175
if (!strcmp(argv[0], "check")) {
149176
const char *need_pec = NULL, *need_alert = NULL, *min_speed = NULL;
177+
const char *need_fp = NULL, *need_avsbus = NULL;
150178
int strict = 0;
151179

152180
for (int i = 1; i < argc; i++) {
@@ -156,6 +184,10 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
156184
need_alert = argv[++i];
157185
else if (!strcmp(argv[i], "--min-speed") && i + 1 < argc)
158186
min_speed = argv[++i];
187+
else if (!strcmp(argv[i], "--need-fp") && i + 1 < argc)
188+
need_fp = argv[++i];
189+
else if (!strcmp(argv[i], "--need-avsbus") && i + 1 < argc)
190+
need_avsbus = argv[++i];
159191
else if (!strcmp(argv[i], "--strict"))
160192
strict = 1;
161193
else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
@@ -181,14 +213,14 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
181213

182214
/* PEC check */
183215
if (need_pec) {
184-
int want = (!strcmp(need_pec, "on") || !strcmp(need_pec, "yes") || !strcmp(need_pec, "true"));
185-
int have = !!(cap & 0x80u);
186-
add_check(checks, "pec_ok", (want == have), mism);
216+
int want, have = !!(cap & 0x80u);
217+
if (parse_onoff(need_pec, &want) == 0)
218+
add_check(checks, "pec_ok", (want == have), mism);
187219
}
188220

189221
/* Speed check */
190222
if (min_speed) {
191-
int req = atoi(min_speed); /* expect 100 or 400 */
223+
int req = atoi(min_speed); /* expect 100 or 400 or 1000 */
192224
unsigned code = (cap >> 5) & 0x3u;
193225
int khz = -1;
194226
(void) speed_text(code, &khz);
@@ -198,15 +230,30 @@ cmd_capability(int fd, int argc, char *const *argv, int pretty) {
198230

199231
/* ALERT check */
200232
if (need_alert) {
201-
int want = (!strcmp(need_alert, "on") || !strcmp(need_alert, "yes") || !strcmp(need_alert, "true"));
202-
int have = !!(cap & 0x10u);
203-
add_check(checks, "alert_ok", (want == have), mism);
233+
int want, have = !!(cap & 0x10u);
234+
if (parse_onoff(need_alert, &want) == 0)
235+
add_check(checks, "alert_ok", (want == have), mism);
236+
}
237+
238+
/* Numeric format check (bit 3) */
239+
if (need_fp) {
240+
int want_fp, have_fp = !!(cap & 0x08u);
241+
if (parse_onoff(need_fp, &want_fp) == 0)
242+
add_check(checks, "numeric_format_ok", (want_fp == have_fp), mism);
243+
}
244+
245+
/* AVSBus check (bit 2) */
246+
if (need_avsbus) {
247+
int want_avs, have_avs = !!(cap & 0x04u);
248+
if (parse_onoff(need_avsbus, &want_avs) == 0)
249+
add_check(checks, "avsbus_ok", (want_avs == have_avs), mism);
204250
}
205251

206252
/* Reserved bits strictness */
207253
if (strict) {
208-
int rsv_ok = ((cap & 0x0Fu) == 0);
209-
add_check(checks, "reserved_low_zero", rsv_ok, mism);
254+
add_check(checks, "reserved_low_zero", (cap & 0x03u) == 0, mism);
255+
256+
add_check(checks, "speed_code_valid", ((cap >> 5) & 0x3u) != 3u, mism);
210257
}
211258

212259
json_object_set_new(out, "checks", checks);

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ usage(const char *p) {
6767
" vout get|set [--command V] [--mhigh V] [--mlow V]\n"
6868
" [--set-all NOM --margin-pct +/-PCT]\n"
6969
" capability get\n"
70-
" capability check [--need-pec on|off] [--min-speed 100|400] [--need-alert on|off] [--strict]\n"
70+
" capability check [--need-pec on|off] [--min-speed 100|400|1000] [--need-alert on|off] [--strict]\n"
7171
" interleave get|set [--set 0xNN] [--phases 1..16 --index 0..15]\n"
7272
" hrr get|set [--pec on|off] [--hrr on|off] [--dls linear|nonlinear]\n"
7373
" [--artdlc on|off] [--dbv on|off] [--raw 0xNN]\n"

0 commit comments

Comments
 (0)