ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
pmbus.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file pmbus.h
6 * @brief PMBus 1.3 power-management command set over SMBus.
7 *
8 * PMBus is SMBus with the command codes fixed and the numbers given an encoding, so a digital
9 * point-of-load converter, a hot-swap controller or a power supply reports its input voltage,
10 * output current, temperature and faults through one set of commands instead of a register map
11 * per part.
12 *
13 * Three encodings carry the numbers, and all three are decoded here rather than in a driver:
14 *
15 * - **LINEAR11** for most telemetry: one word holding a 5-bit signed exponent in bits 15:11 and
16 * an 11-bit signed mantissa in bits 10:0. The value is mantissa * 2^exponent.
17 * - **LINEAR16** for output voltage: the word is a 16-bit unsigned mantissa and the exponent
18 * comes from the part's VOUT_MODE register, so it is read once and applied to every reading.
19 * - **DIRECT** where a part uses it: the value is (word / 10^R - b) / m, with m, b and R coming
20 * from the part's datasheet.
21 *
22 * Values are returned in micro-units (microvolts, microamps, microwatts) and temperatures in
23 * milli-degrees Celsius, which is what the other sensor drivers here report in. No float is
24 * involved: the exponent is a shift.
25 *
26 * The encodings are pure and host-tested. The commands ride the SMBus shapes, so a build with no
27 * bus seam refuses them.
28 *
29 * @author Douglas Quigg (dstroy0)
30 * @date 2026
31 */
32
33#ifndef PROTOCORE_PMBUS_H
34#define PROTOCORE_PMBUS_H
35
36#include "protocore_config.h" // the entry point: protocore_types.h for the widths
37
38#if PROTOCORE_ENABLE_PMBUS
39
41
42// This module holds nothing between calls, so it carves no borrow and states none. An entry
43// takes one all the same, and never reads it, so every namespace in the tree is invoked the
44// same way.
45
46#define PROTOCORE_PMBUS_PAGE 0x00u
47
48#define PROTOCORE_PMBUS_OPERATION 0x01u
49
50#define PROTOCORE_PMBUS_ON_OFF_CONFIG 0x02u
51
52#define PROTOCORE_PMBUS_CLEAR_FAULTS 0x03u
53
54#define PROTOCORE_PMBUS_CAPABILITY 0x19u
55
56#define PROTOCORE_PMBUS_VOUT_MODE 0x20u
57
58#define PROTOCORE_PMBUS_VOUT_COMMAND 0x21u
59
60#define PROTOCORE_PMBUS_VOUT_MAX 0x24u
61
62#define PROTOCORE_PMBUS_VOUT_OV_FAULT_LIM 0x40u
63
64#define PROTOCORE_PMBUS_IOUT_OC_FAULT_LIM 0x46u
65
66#define PROTOCORE_PMBUS_OT_FAULT_LIMIT 0x4Fu
67
68#define PROTOCORE_PMBUS_VIN_OV_FAULT_LIM 0x55u
69
70#define PROTOCORE_PMBUS_STATUS_BYTE 0x78u
71
72#define PROTOCORE_PMBUS_STATUS_WORD 0x79u
73
74#define PROTOCORE_PMBUS_STATUS_VOUT 0x7Au
75
76#define PROTOCORE_PMBUS_STATUS_IOUT 0x7Bu
77
78#define PROTOCORE_PMBUS_STATUS_INPUT 0x7Cu
79
80#define PROTOCORE_PMBUS_STATUS_TEMP 0x7Du
81
82#define PROTOCORE_PMBUS_STATUS_CML 0x7Eu
83
84#define PROTOCORE_PMBUS_READ_VIN 0x88u
85
86#define PROTOCORE_PMBUS_READ_IIN 0x89u
87
88#define PROTOCORE_PMBUS_READ_VOUT 0x8Bu
89
90#define PROTOCORE_PMBUS_READ_IOUT 0x8Cu
91
92#define PROTOCORE_PMBUS_READ_TEMP_1 0x8Du
93
94#define PROTOCORE_PMBUS_READ_TEMP_2 0x8Eu
95
96#define PROTOCORE_PMBUS_READ_FAN_SPEED_1 0x90u
97
98#define PROTOCORE_PMBUS_READ_POUT 0x96u
99
100#define PROTOCORE_PMBUS_READ_PIN 0x97u
101
102#define PROTOCORE_PMBUS_MFR_ID 0x99u
103
104#define PROTOCORE_PMBUS_MFR_MODEL 0x9Au
105
106#define PROTOCORE_PMBUS_MFR_REVISION 0x9Bu
107
108#define PROTOCORE_PMBUS_ST_NONE_ABOVE 0x01u
109
110#define PROTOCORE_PMBUS_ST_CML 0x02u
111
112#define PROTOCORE_PMBUS_ST_TEMPERATURE 0x04u
113
114#define PROTOCORE_PMBUS_ST_VIN_UV 0x08u
115
116#define PROTOCORE_PMBUS_ST_IOUT_OC 0x10u
117
118#define PROTOCORE_PMBUS_ST_VOUT_OV 0x20u
119
120#define PROTOCORE_PMBUS_ST_OFF 0x40u
121
122#define PROTOCORE_PMBUS_ST_BUSY 0x80u
123
124#define PROTOCORE_PMBUS_MODE_LINEAR 0u
125
126#define PROTOCORE_PMBUS_MODE_VID 1u
127
128#define PROTOCORE_PMBUS_MODE_DIRECT 2u
129
130#define PROTOCORE_PMBUS_MODE_IEEE 3u
131
132#define PROTOCORE_PMBUS_INVALID INT32_MIN
133
134/** @brief What vout_mode_kind takes: vout_mode. */
135typedef struct
136{
137 uint8_t vout_mode;
138} PmbusVoutModeKindArgs;
139
140/** @brief What vout_exponent takes: vout_mode. */
141typedef struct
142{
143 uint8_t vout_mode;
144} PmbusVoutExponentArgs;
145
146/** @brief What l11_mantissa takes: word. */
147typedef struct
148{
149 uint16_t word;
150} PmbusL11MantissaArgs;
151
152/** @brief What l11_exponent takes: word. */
153typedef struct
154{
155 uint16_t word;
156} PmbusL11ExponentArgs;
157
158/** @brief What linear11_micro takes: word. */
159typedef struct
160{
161 uint16_t word;
162} PmbusLinear11MicroArgs;
163
164/** @brief What linear11_encode takes: micro. */
165typedef struct
166{
167 int32_t micro;
168} PmbusLinear11EncodeArgs;
169
170/** @brief What linear16_micro takes: word, exponent. */
171typedef struct
172{
173 uint16_t word;
174 int8_t exponent;
175} PmbusLinear16MicroArgs;
176
177/** @brief What linear16_encode takes: micro, exponent. */
178typedef struct
179{
180 int32_t micro;
181 int8_t exponent;
182} PmbusLinear16EncodeArgs;
183
184/** @brief What direct_micro takes: word, m, b, r. */
185typedef struct
186{
187 uint16_t word;
188 int16_t m;
189 int16_t b;
190 int8_t r;
191} PmbusDirectMicroArgs;
192
193/** @brief What set_page takes: addr, page. */
194typedef struct
195{
196 uint8_t addr;
197 uint8_t page;
198} PmbusSetPageArgs;
199
200/** @brief What read_vout_mode takes: addr, out. */
201typedef struct
202{
203 uint8_t addr;
204 uint8_t *out;
205} PmbusReadVoutModeArgs;
206
207/** @brief What read_linear11 takes: addr, cmd, micro. */
208typedef struct
209{
210 uint8_t addr;
211 uint8_t cmd;
212 int32_t *micro;
213} PmbusReadLinear11Args;
214
215/** @brief What read_linear16 takes: addr, cmd, exponent, micro. */
216typedef struct
217{
218 uint8_t addr;
219 uint8_t cmd;
220 int8_t exponent;
221 int32_t *micro;
222} PmbusReadLinear16Args;
223
224/** @brief What write_linear16 takes: addr, cmd, exponent, micro. */
225typedef struct
226{
227 uint8_t addr;
228 uint8_t cmd;
229 int8_t exponent;
230 int32_t micro;
231} PmbusWriteLinear16Args;
232
233/** @brief What status_byte takes: addr, out. */
234typedef struct
235{
236 uint8_t addr;
237 uint8_t *out;
238} PmbusStatusByteArgs;
239
240/** @brief What status_word takes: addr, out. */
241typedef struct
242{
243 uint8_t addr;
244 uint16_t *out;
245} PmbusStatusWordArgs;
246
247/** @brief What clear_faults takes: addr. */
248typedef struct
249{
250 uint8_t addr;
251} PmbusClearFaultsArgs;
252
253/** @brief What read_mfr_string takes: addr, cmd, out, cap, len. */
254typedef struct
255{
256 uint8_t addr;
257 uint8_t cmd;
258 uint8_t *out; ///< caller-owned, cap bytes; not terminated, the length comes back in len
259 size_t cap;
260 size_t *len;
261} PmbusReadMfrStringArgs;
262
263/**
264 * @brief PMBus 1.3 power-management command set over SMBus. PMBus is SMBus with the command codes fixed and the ...
265 *
266 * A caller sets the members a call takes, invokes it through ::Pmbus with the bytes it runs
267 * out of, and reads the outcome off the same handle.
268 *
269 * Pmbus.vout_mode_kind_args.vout_mode = ...;
270 * Pmbus.vout_mode_kind(work);
271 * // Pmbus.kind is what the call reports
272 *
273 * @var PmbusNs::vout_mode_kind_args what vout_mode_kind takes: vout_mode
274 * @var PmbusNs::vout_exponent_args what vout_exponent takes: vout_mode
275 * @var PmbusNs::l11_mantissa_args what l11_mantissa takes: word
276 * @var PmbusNs::l11_exponent_args what l11_exponent takes: word
277 * @var PmbusNs::linear11_micro_args what linear11_micro takes: word
278 * @var PmbusNs::linear11_encode_args what linear11_encode takes: micro
279 * @var PmbusNs::linear16_micro_args what linear16_micro takes: word, exponent
280 * @var PmbusNs::linear16_encode_args what linear16_encode takes: micro, exponent
281 * @var PmbusNs::direct_micro_args what direct_micro takes: word, m, b, r
282 * @var PmbusNs::set_page_args what set_page takes: addr, page
283 * @var PmbusNs::read_vout_mode_args what read_vout_mode takes: addr, out
284 * @var PmbusNs::read_linear11_args what read_linear11 takes: addr, cmd, micro
285 * @var PmbusNs::read_linear16_args what read_linear16 takes: addr, cmd, exponent, micro
286 * @var PmbusNs::write_linear16_args what write_linear16 takes: addr, cmd, exponent, micro
287 * @var PmbusNs::status_byte_args what status_byte takes: addr, out
288 * @var PmbusNs::status_word_args what status_word takes: addr, out
289 * @var PmbusNs::clear_faults_args what clear_faults takes: addr
290 * @var PmbusNs::read_mfr_string_args what read_mfr_string takes: addr, cmd, out, cap, len
291 * @var PmbusNs::ok a call's true/false outcome
292 * @var PmbusNs::kind what a call reports
293 * @var PmbusNs::exp what a call reports
294 * @var PmbusNs::mantissa what a call reports
295 * @var PmbusNs::micro the value, or ::PROTOCORE_PMBUS_INVALID if it does not fit in an ...
296 * @var PmbusNs::word what a call reports
297 * @var PmbusNs::vout_mode_kind the encoding VOUT_MODE names, from its bits 7:5
298 * @var PmbusNs::vout_exponent the exponent VOUT_MODE carries in its bits 4:0, sign-extended from ...
299 * @var PmbusNs::l11_mantissa the 11-bit signed mantissa of a LINEAR11 word, sign-extended
300 * @var PmbusNs::l11_exponent the 5-bit signed exponent of a LINEAR11 word, sign-extended
301 * @var PmbusNs::linear11_micro decode a LINEAR11 word to micro-units: mantissa * 2^exponent, ...
302 * @var PmbusNs::linear11_encode encode micro micro-units as a LINEAR11 word, picking the exponent ...
303 * @var PmbusNs::linear16_micro decode a LINEAR16 word to micro-units: an unsigned mantissa scaled ...
304 * @var PmbusNs::linear16_encode encode micro micro-units as a LINEAR16 word at exponent
305 * @var PmbusNs::direct_micro decode a DIRECT-format word to micro-units: (word / 10^r - b) / m, ...
306 * @var PmbusNs::begin bring up the bus for PMBus traffic
307 * @var PmbusNs::set_page select page page on addr; a multi-rail part answers per page
308 * @var PmbusNs::read_vout_mode read VOUT_MODE, whose exponent every LINEAR16 reading on this part ...
309 * @var PmbusNs::read_linear11 read a LINEAR11 telemetry command (READ_VIN, READ_IOUT, READ_PIN, ...
310 * @var PmbusNs::read_linear16 read a LINEAR16 command (READ_VOUT, VOUT_COMMAND) in microvolts at ...
311 * @var PmbusNs::write_linear16 write micro microvolts to a LINEAR16 command at exponent
312 * @var PmbusNs::status_byte read STATUS_BYTE
313 * @var PmbusNs::status_word read STATUS_WORD, whose low half is STATUS_BYTE
314 * @var PmbusNs::clear_faults clear every latched fault on addr
315 * @var PmbusNs::read_mfr_string read one of the block-encoded manufacturer strings (MFR_ID, ...
316 *
317 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
318 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
319 * a caller drives every namespace the same way.
320 */
321typedef struct
322{
323 PmbusVoutModeKindArgs vout_mode_kind_args;
324 PmbusVoutExponentArgs vout_exponent_args;
325 PmbusL11MantissaArgs l11_mantissa_args;
326 PmbusL11ExponentArgs l11_exponent_args;
327 PmbusLinear11MicroArgs linear11_micro_args;
328 PmbusLinear11EncodeArgs linear11_encode_args;
329 PmbusLinear16MicroArgs linear16_micro_args;
330 PmbusLinear16EncodeArgs linear16_encode_args;
331 PmbusDirectMicroArgs direct_micro_args;
332 PmbusSetPageArgs set_page_args;
333 PmbusReadVoutModeArgs read_vout_mode_args;
334 PmbusReadLinear11Args read_linear11_args;
335 PmbusReadLinear16Args read_linear16_args;
336 PmbusWriteLinear16Args write_linear16_args;
337 PmbusStatusByteArgs status_byte_args;
338 PmbusStatusWordArgs status_word_args;
339 PmbusClearFaultsArgs clear_faults_args;
340 PmbusReadMfrStringArgs read_mfr_string_args;
341
342 proto_bool ok;
343 uint8_t kind;
344 int8_t exp;
345 int16_t mantissa;
346 int32_t micro;
347 uint16_t word;
348
349 void (*const vout_mode_kind)(uint8_t *work);
350 void (*const vout_exponent)(uint8_t *work);
351 void (*const l11_mantissa)(uint8_t *work);
352 void (*const l11_exponent)(uint8_t *work);
353 void (*const linear11_micro)(uint8_t *work);
354 void (*const linear11_encode)(uint8_t *work);
355 void (*const linear16_micro)(uint8_t *work);
356 void (*const linear16_encode)(uint8_t *work);
357 void (*const direct_micro)(uint8_t *work);
358 void (*const begin)(uint8_t *work);
359 void (*const set_page)(uint8_t *work);
360 void (*const read_vout_mode)(uint8_t *work);
361 void (*const read_linear11)(uint8_t *work);
362 void (*const read_linear16)(uint8_t *work);
363 void (*const write_linear16)(uint8_t *work);
364 void (*const status_byte)(uint8_t *work);
365 void (*const status_word)(uint8_t *work);
366 void (*const clear_faults)(uint8_t *work);
367 void (*const read_mfr_string)(uint8_t *work);
368} PmbusNs;
369
370/** @brief The one symbol this module exports. */
371extern PmbusNs Pmbus;
372
374
375#endif // PROTOCORE_ENABLE_PMBUS
376
377#endif // PROTOCORE_PMBUS_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97