blob: 6079eac2cc5aa5bd0bca0c184a047e85d3b5aa56 [file] [log] [blame]
AppaRao Pulic532f552019-07-05 15:23:50 +05301/*
2// Copyright (c) 2019 Intel 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
17#pragma once
18
19#include <errno.h>
20#include <fcntl.h>
AppaRao Pulic532f552019-07-05 15:23:50 +053021#include <stdio.h>
AppaRao Puli67d184c2020-05-29 00:48:33 +053022#include <sys/ioctl.h>
23
AppaRao Pulic532f552019-07-05 15:23:50 +053024#include <phosphor-logging/log.hpp>
25
AppaRao Puli67d184c2020-05-29 00:48:33 +053026#include <experimental/filesystem>
27
28extern "C"
29{
AppaRao Pulic532f552019-07-05 15:23:50 +053030#include <i2c/smbus.h>
31#include <linux/i2c-dev.h>
32}
33
34namespace intel
35{
36namespace pfr
37{
38
39/** @class I2CFile
40 * @brief Responsible for handling file pointer
41 */
42class I2CFile
43{
44 private:
45 /** @brief handler for operating on file */
46 int fd;
47
48 public:
49 I2CFile() = delete;
50 I2CFile(const I2CFile&) = delete;
51 I2CFile& operator=(const I2CFile&) = delete;
52 I2CFile(I2CFile&&) = delete;
53 I2CFile& operator=(I2CFile&&) = delete;
54
55 /** @brief Opens i2c device file and sets slave
56 *
57 * @param[in] i2cBus - I2C bus number
58 * @param[in] slaveAddr - I2C slave address
59 * @param[in] flags - Flags
60 */
61 I2CFile(const int& i2cBus, const int& slaveAddr, const int& flags)
62 {
63 std::string i2cDev = "/dev/i2c-" + std::to_string(i2cBus);
64
65 fd = open(i2cDev.c_str(), flags);
66 if (fd < 0)
67 {
68 throw std::runtime_error("Unable to open i2c device.");
69 }
70
71 if (ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
72 {
73 close(fd);
74 fd = -1;
75 throw std::runtime_error("Unable to set i2c slave address.");
76 }
77 }
78
79 /** @brief Reads the byte data from I2C dev
80 *
81 * @param[in] Offset - Offset value
82 * @param[out] byte data - Offset value
83 */
84 uint8_t i2cReadByteData(const uint8_t& offset)
85 {
86 uint8_t value = i2c_smbus_read_byte_data(fd, offset);
87
88 if (value < 0)
89 {
90 throw std::runtime_error("i2c_smbus_read_byte_data() failed");
91 }
92 return value;
93 }
94
AppaRao Puli46cead92019-07-22 16:50:09 +053095 /** @brief Writes the byte data to I2C dev
96 *
97 * @param[in] Offset - Offset value
98 * @param[in] Byte data - Data
99 */
100 void i2cWriteByteData(const uint8_t offset, const uint8_t value)
101 {
102 int retries = 3;
103 while (i2c_smbus_write_byte_data(fd, offset, value) < 0)
104 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530105 phosphor::logging::log<phosphor::logging::level::WARNING>(
106 "PFR: I2c write failed, retrying....",
107 phosphor::logging::entry("COUNT=%d", retries));
AppaRao Puli46cead92019-07-22 16:50:09 +0530108 if (!retries--)
109 {
110 throw std::runtime_error("i2c_smbus_write_byte_data() failed");
111 }
112 std::this_thread::sleep_for(std::chrono::milliseconds(10));
113 }
114 return;
115 }
116
AppaRao Pulic532f552019-07-05 15:23:50 +0530117 ~I2CFile()
118 {
119 if (!(fd < 0))
120 {
121 close(fd);
122 }
123 }
124
125 auto operator()()
126 {
127 return fd;
128 }
129};
130
131} // namespace pfr
132} // namespace intel