blob: c333c34bef58fe1a833d78d5454dac50bc27ef22 [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>
AppaRao Pulidcf13122020-05-28 01:21:39 +053023#include <unistd.h>
AppaRao Puli67d184c2020-05-29 00:48:33 +053024
AppaRao Pulic532f552019-07-05 15:23:50 +053025#include <phosphor-logging/log.hpp>
26
AppaRao Puli67d184c2020-05-29 00:48:33 +053027#include <experimental/filesystem>
28
29extern "C"
30{
AppaRao Pulic532f552019-07-05 15:23:50 +053031#include <i2c/smbus.h>
32#include <linux/i2c-dev.h>
33}
34
AppaRao Pulic532f552019-07-05 15:23:50 +053035namespace pfr
36{
37
38/** @class I2CFile
39 * @brief Responsible for handling file pointer
40 */
41class I2CFile
42{
43 private:
44 /** @brief handler for operating on file */
45 int fd;
46
47 public:
48 I2CFile() = delete;
49 I2CFile(const I2CFile&) = delete;
50 I2CFile& operator=(const I2CFile&) = delete;
51 I2CFile(I2CFile&&) = delete;
52 I2CFile& operator=(I2CFile&&) = delete;
53
54 /** @brief Opens i2c device file and sets slave
55 *
56 * @param[in] i2cBus - I2C bus number
57 * @param[in] slaveAddr - I2C slave address
58 * @param[in] flags - Flags
59 */
60 I2CFile(const int& i2cBus, const int& slaveAddr, const int& flags)
61 {
62 std::string i2cDev = "/dev/i2c-" + std::to_string(i2cBus);
63
64 fd = open(i2cDev.c_str(), flags);
65 if (fd < 0)
66 {
67 throw std::runtime_error("Unable to open i2c device.");
68 }
69
70 if (ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
71 {
72 close(fd);
73 fd = -1;
74 throw std::runtime_error("Unable to set i2c slave address.");
75 }
76 }
77
78 /** @brief Reads the byte data from I2C dev
79 *
80 * @param[in] Offset - Offset value
81 * @param[out] byte data - Offset value
82 */
83 uint8_t i2cReadByteData(const uint8_t& offset)
84 {
Zhikui Renc1db6da2020-07-30 12:19:32 -070085 int value = i2c_smbus_read_byte_data(fd, offset);
AppaRao Pulic532f552019-07-05 15:23:50 +053086
87 if (value < 0)
88 {
89 throw std::runtime_error("i2c_smbus_read_byte_data() failed");
90 }
Zhikui Renc1db6da2020-07-30 12:19:32 -070091 return static_cast<uint8_t>(value);
AppaRao Pulic532f552019-07-05 15:23:50 +053092 }
93
Chalapathi Venkataramashetty53b87002020-07-03 09:52:44 +000094 /** @brief Reads the block of data from I2C dev
95 *
96 * @param[in] Offset - Offset value
97 * @param[in] length - length value
98 * @param[out] value - data pointer
99 * @param[out] bool - true or false
100 */
101 bool i2cReadBlockData(const uint8_t& offset, uint8_t length, uint8_t* value)
102 {
103 int ret;
104 ret = i2c_smbus_read_i2c_block_data(fd, offset, length, value);
105
106 if (ret < 0)
107 {
108 throw std::runtime_error("i2c_smbus_read_i2c_block_data() failed");
109 return false;
110 }
111 return true;
112 }
113
AppaRao Puli46cead92019-07-22 16:50:09 +0530114 /** @brief Writes the byte data to I2C dev
115 *
116 * @param[in] Offset - Offset value
117 * @param[in] Byte data - Data
118 */
119 void i2cWriteByteData(const uint8_t offset, const uint8_t value)
120 {
121 int retries = 3;
122 while (i2c_smbus_write_byte_data(fd, offset, value) < 0)
123 {
AppaRao Pulib7e172c2019-12-13 14:46:25 +0530124 phosphor::logging::log<phosphor::logging::level::WARNING>(
125 "PFR: I2c write failed, retrying....",
126 phosphor::logging::entry("COUNT=%d", retries));
AppaRao Puli46cead92019-07-22 16:50:09 +0530127 if (!retries--)
128 {
129 throw std::runtime_error("i2c_smbus_write_byte_data() failed");
130 }
131 std::this_thread::sleep_for(std::chrono::milliseconds(10));
132 }
133 return;
134 }
135
AppaRao Pulic532f552019-07-05 15:23:50 +0530136 ~I2CFile()
137 {
138 if (!(fd < 0))
139 {
140 close(fd);
141 }
142 }
143
144 auto operator()()
145 {
146 return fd;
147 }
148};
149
150} // namespace pfr