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