blob: e77ced1b42da1aa188e42d763166d32c97fa16ec [file] [log] [blame]
Shawn McCarneya8119f22020-03-02 16:20:18 -06001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include "action_environment.hpp"
19#include "i2c_action.hpp"
20#include "i2c_interface.hpp"
21#include "pmbus_utils.hpp"
22
23#include <cstdint>
24#include <optional>
25#include <stdexcept>
26#include <string>
27
28namespace phosphor::power::regulators
29{
30
31/**
32 * @class PMBusWriteVoutCommandAction
33 *
34 * Writes the value of VOUT_COMMAND to set the output voltage of a PMBus
35 * regulator rail. Communicates with the device directly using the I2C
36 * interface.
37 *
38 * Implements the pmbus_write_vout_command action in the JSON config file.
39 *
40 * The volts value to write can be specified in the constructor. Otherwise, the
41 * volts value will be obtained from the ActionEnvironment.
42 *
43 * The PMBus specification defines four data formats for the value of
44 * VOUT_COMMAND:
45 * - Linear
46 * - VID
47 * - Direct
48 * - IEEE Half-Precision Floating Point
49 * Currently only the linear data format is supported. The volts value is
50 * converted into linear format before being written.
51 *
52 * The linear data format requires an exponent value. The exponent value can be
53 * specified in the constructor. Otherwise the exponent value will be obtained
54 * from the PMBus VOUT_MODE command. Note that some PMBus devices do not
55 * support the VOUT_MODE command. The exponent value for a device is often
56 * found in the device documentation (data sheet).
57 *
58 * If desired, write verification can be performed. The value of VOUT_COMMAND
59 * will be read from the device after it is written to ensure that it contains
60 * the expected value. If VOUT_COMMAND contains an unexpected value, a
61 * WriteVerificationError is thrown. To perform verification, the device must
62 * return all 16 bits of voltage data that were written to VOUT_COMMAND.
63 */
64class PMBusWriteVoutCommandAction : public I2CAction
65{
66 public:
67 // Specify which compiler-generated methods we want
68 PMBusWriteVoutCommandAction() = delete;
69 PMBusWriteVoutCommandAction(const PMBusWriteVoutCommandAction&) = delete;
70 PMBusWriteVoutCommandAction(PMBusWriteVoutCommandAction&&) = delete;
71 PMBusWriteVoutCommandAction&
72 operator=(const PMBusWriteVoutCommandAction&) = delete;
73 PMBusWriteVoutCommandAction&
74 operator=(PMBusWriteVoutCommandAction&&) = delete;
75 virtual ~PMBusWriteVoutCommandAction() = default;
76
77 /**
78 * Constructor.
79 *
80 * Throws an exception if any of the input parameters are invalid.
81 *
82 * @param volts Optional volts value to write to VOUT_COMMAND.
83 * @param format Data format of the volts value written to VOUT_COMMAND.
84 * Currently the only supported format is linear.
85 * @param exponent Optional exponent to use to convert the volts value to
86 * linear data format.
87 * @param isVerified Specifies whether the updated value of VOUT_COMMAND is
88 * verified by reading it from the device.
89 */
90 explicit PMBusWriteVoutCommandAction(std::optional<double> volts,
91 pmbus_utils::VoutDataFormat format,
92 std::optional<int8_t> exponent,
93 bool isVerified) :
94 volts{volts},
95 format{format}, exponent{exponent}, isWriteVerified{isVerified}
96 {
97 // Currently only linear format is supported
98 if (format != pmbus_utils::VoutDataFormat::linear)
99 {
100 throw std::invalid_argument{"Unsupported data format specified"};
101 }
102 }
103
104 /**
105 * Executes this action.
106 *
107 * Writes a volts value to VOUT_COMMAND using the I2C interface.
108 *
109 * If a volts value was specified in the constructor, that value will be
110 * used. Otherwise the volts value will be obtained from the
111 * ActionEnvironment.
112 *
113 * The data format is specified in the constructor. Currently only the
114 * linear format is supported.
115 *
116 * An exponent value is required to convert the volts value to linear
117 * format. If an exponent value was specified in the constructor, that
118 * value will be used. Otherwise the exponent value will be obtained from
119 * the VOUT_MODE command.
120 *
121 * Write verification will be performed if specified in the constructor.
122 *
123 * The device is obtained from the ActionEnvironment.
124 *
125 * Throws an exception if an error occurs.
126 *
127 * @param environment action execution environment
128 * @return true
129 */
130 virtual bool execute(ActionEnvironment& environment) override;
131
132 /**
133 * Returns the optional exponent value used to convert the volts value to
134 * linear data format.
135 *
136 * @return optional exponent value
137 */
138 std::optional<int8_t> getExponent() const
139 {
140 return exponent;
141 }
142
143 /**
144 * Returns the data format of the value written to VOUT_COMMAND.
145 *
146 * @return data format
147 */
148 pmbus_utils::VoutDataFormat getFormat() const
149 {
150 return format;
151 }
152
153 /**
154 * Returns the optional volts value to write to VOUT_COMMAND.
155 *
156 * @return optional volts value
157 */
158 std::optional<double> getVolts() const
159 {
160 return volts;
161 }
162
163 /**
164 * Returns whether write verification will be performed when writing to
165 * VOUT_COMMAND.
166 *
167 * @return true if write verification will be performed, false otherwise
168 */
169 bool isVerified() const
170 {
171 return isWriteVerified;
172 }
173
174 /**
175 * Returns a string description of this action.
176 *
177 * @return description of action
178 */
179 virtual std::string toString() const override;
180
181 private:
182 /**
183 * Gets the exponent value to use to convert the volts value to linear data
184 * format.
185 *
186 * If an exponent value is defined for this action, that value is returned.
187 * Otherwise VOUT_MODE is read from the current device to obtain the
188 * exponent value.
189 *
190 * Throws an exception if an error occurs.
191 *
Shawn McCarney5b819f42021-03-16 14:41:15 -0500192 * @param environment action execution environment
Shawn McCarneya8119f22020-03-02 16:20:18 -0600193 * @param interface I2C interface to the current device
194 * @return exponent value
195 */
Shawn McCarney5b819f42021-03-16 14:41:15 -0500196 int8_t getExponentValue(ActionEnvironment& environment,
197 i2c::I2CInterface& interface);
Shawn McCarneya8119f22020-03-02 16:20:18 -0600198
199 /**
200 * Gets the volts value to write to VOUT_COMMAND.
201 *
202 * If a volts value is defined for this action, that value is returned.
203 * Otherwise the volts value is obtained from the specified
204 * ActionEnvironment.
205 *
206 * Throws an exception if no volts value is defined.
207 *
208 * @param environment action execution environment
209 * @return volts value
210 */
211 double getVoltsValue(ActionEnvironment& environment);
212
213 /**
214 * Verifies the value written to VOUT_COMMAND. Reads the current value of
215 * VOUT_COMMAND and ensures that it matches the value written.
216 *
217 * Throws an exception if the values do not match or a communication error
218 * occurs.
219 *
220 * @param environment action execution environment
221 * @param interface I2C interface to the current device
222 * @param valueWritten linear format volts value written to VOUT_COMMAND
223 */
224 void verifyWrite(ActionEnvironment& environment,
225 i2c::I2CInterface& interface, uint16_t valueWritten);
226
227 /**
228 * Optional volts value to write.
229 */
230 const std::optional<double> volts{};
231
232 /**
233 * Data format of the volts value written to VOUT_COMMAND.
234 */
235 const pmbus_utils::VoutDataFormat format{};
236
237 /**
238 * Optional exponent value to use to convert the volts value to linear data
239 * format.
240 */
241 const std::optional<int8_t> exponent{};
242
243 /**
244 * Indicates whether write verification will be performed when writing to
245 * VOUT_COMMAND.
246 */
247 const bool isWriteVerified{false};
248};
249
250} // namespace phosphor::power::regulators