blob: 80f7caca97f2ba2608b1d92938674ca231d778e5 [file] [log] [blame]
Ben Pai44cee312020-03-16 15:24:46 +08001#include "smbus.hpp"
2
3#include <errno.h>
4#include <fcntl.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/ioctl.h>
10#include <unistd.h>
11
12#include <iostream>
13#include <mutex>
14
15#include "i2c.h"
16
17#define MAX_I2C_BUS 30
18
19static int fd[MAX_I2C_BUS] = {0};
20
21namespace phosphor
22{
23namespace smbus
24{
25
26std::mutex gMutex;
27
28int phosphor::smbus::Smbus::open_i2c_dev(int i2cbus, char* filename,
29 size_t size, int quiet)
30{
31 int file;
32
33 snprintf(filename, size, "/dev/i2c/%d", i2cbus);
34 filename[size - 1] = '\0';
35 file = open(filename, O_RDWR);
36
37 if (file < 0 && (errno == ENOENT || errno == ENOTDIR))
38 {
39 sprintf(filename, "/dev/i2c-%d", i2cbus);
40 file = open(filename, O_RDWR);
41 }
42
43 if (file < 0 && !quiet)
44 {
45 if (errno == ENOENT)
46 {
47 fprintf(stderr,
48 "Error: Could not open file "
49 "`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
50 i2cbus, i2cbus, strerror(ENOENT));
51 }
52 else
53 {
54 fprintf(stderr,
55 "Error: Could not open file "
56 "`%s': %s\n",
57 filename, strerror(errno));
58 if (errno == EACCES)
59 fprintf(stderr, "Run as root?\n");
60 }
61 }
62
63 return file;
64}
65
66int phosphor::smbus::Smbus::smbusInit(int smbus_num)
67{
68 int res = 0;
69 char filename[20];
70
71 gMutex.lock();
72
73 fd[smbus_num] = open_i2c_dev(smbus_num, filename, sizeof(filename), 0);
74 if (fd[smbus_num] < 0)
75 {
76 gMutex.unlock();
77
78 return -1;
79 }
80
81 res = fd[smbus_num];
82
83 gMutex.unlock();
84
85 return res;
86}
87
88void phosphor::smbus::Smbus::smbusClose(int smbus_num)
89{
90 close(fd[smbus_num]);
91}
92
93int phosphor::smbus::Smbus::set_slave_addr(int file, int address, int force)
94{
95 /* With force, let the user read from/write to the registers
96 even when a driver is also running */
97 if (ioctl(file, force ? I2C_SLAVE_FORCE : I2C_SLAVE, address) < 0)
98 {
99 fprintf(stderr, "Error: Could not set address to 0x%02x: %s\n", address,
100 strerror(errno));
101 return -errno;
102 }
103
104 return 0;
105}
106
107int phosphor::smbus::Smbus::SetSmbusCmdByte(int smbus_num, int8_t device_addr,
108 int8_t smbuscmd, int8_t data)
109{
110 int res;
111
112 gMutex.lock();
113 if (fd[smbus_num] > 0)
114 {
115 res = set_slave_addr(fd[smbus_num], device_addr, I2C_SLAVE_FORCE);
116 if (res < 0)
117 {
118 fprintf(stderr,
119 "set PMBUS BUS%d to slave address 0x%02X failed (%s)\n",
120 smbus_num, device_addr, strerror(errno));
121 close(fd[smbus_num]);
122
123 gMutex.unlock();
124 return -1;
125 }
126 }
127
128 res = i2c_smbus_write_byte_data(fd[smbus_num], smbuscmd, data);
129 if (res < 0)
130 {
131 fprintf(stderr, "Error: Read failed\n");
132 gMutex.unlock();
133
134 return -1;
135 }
136
137 gMutex.unlock();
138 return res;
139}
140
141int phosphor::smbus::Smbus::GetSmbusCmdByte(int smbus_num, int8_t device_addr,
142 int8_t smbuscmd)
143{
144 int res;
145
146 gMutex.lock();
147 if (fd[smbus_num] > 0)
148 {
149 res = set_slave_addr(fd[smbus_num], device_addr, I2C_SLAVE_FORCE);
150
151 if (res < 0)
152 {
153 fprintf(stderr,
154 "set PMBUS BUS%d to slave address 0x%02X failed (%s)\n",
155 smbus_num, device_addr, strerror(errno));
156 close(fd[smbus_num]);
157
158 gMutex.unlock();
159 return -1;
160 }
161 }
162
163 res = i2c_smbus_read_byte_data(fd[smbus_num], smbuscmd);
164 if (res < 0)
165 {
166 fprintf(stderr, "Error: Read failed\n");
167 gMutex.unlock();
168
169 return -1;
170 }
171
172 gMutex.unlock();
173 return res;
174}
175
176} // namespace smbus
177} // namespace phosphor