drivers/ipmi: Add IPMI read FRU chassis info area
[coreboot.git] / src / device / i2c_bus.c
bloba65cdada895771dbfaed3327abc70d88d3c43e1b
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <stdint.h>
4 #include <console/console.h>
5 #include <device/smbus.h>
6 #include <device/i2c_bus.h>
7 #include <commonlib/endian.h>
9 struct bus *i2c_link(struct device *const dev)
11 if (!dev || !dev->bus)
12 return NULL;
14 struct bus *link = dev->bus;
15 while (link) {
16 struct device *const parent = link->dev;
18 if (parent && parent->ops &&
19 (parent->ops->ops_i2c_bus || parent->ops->ops_smbus_bus))
20 break;
22 if (parent && parent->bus)
23 link = parent->bus;
24 else
25 link = NULL;
28 if (!link) {
29 printk(BIOS_ALERT, "%s Cannot find I2C or SMBus bus operations",
30 dev_path(dev));
33 return link;
36 int i2c_dev_readb(struct device *const dev)
38 struct device *const busdev = i2c_busdev(dev);
39 if (!busdev)
40 return -1;
42 if (busdev->ops->ops_i2c_bus) {
43 uint8_t val;
44 const struct i2c_msg msg = {
45 .flags = I2C_M_RD,
46 .slave = dev->path.i2c.device,
47 .buf = &val,
48 .len = sizeof(val),
51 const int ret = busdev->ops->ops_i2c_bus->
52 transfer(busdev, &msg, 1);
53 if (ret)
54 return ret;
55 else
56 return val;
57 } else if (busdev->ops->ops_smbus_bus->recv_byte) {
58 return busdev->ops->ops_smbus_bus->recv_byte(dev);
59 } else {
60 printk(BIOS_ERR, "%s Missing ops_smbus_bus->recv_byte",
61 dev_path(busdev));
62 return -1;
66 int i2c_dev_writeb(struct device *const dev, uint8_t val)
68 struct device *const busdev = i2c_busdev(dev);
69 if (!busdev)
70 return -1;
72 if (busdev->ops->ops_i2c_bus) {
73 const struct i2c_msg msg = {
74 .flags = 0,
75 .slave = dev->path.i2c.device,
76 .buf = &val,
77 .len = sizeof(val),
79 return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
80 } else if (busdev->ops->ops_smbus_bus->send_byte) {
81 return busdev->ops->ops_smbus_bus->send_byte(dev, val);
82 } else {
83 printk(BIOS_ERR, "%s Missing ops_smbus_bus->send_byte",
84 dev_path(busdev));
85 return -1;
89 int i2c_dev_readb_at(struct device *const dev, uint8_t off)
91 struct device *const busdev = i2c_busdev(dev);
92 if (!busdev)
93 return -1;
95 if (busdev->ops->ops_i2c_bus) {
96 uint8_t val;
97 const struct i2c_msg msg[] = {
99 .flags = 0,
100 .slave = dev->path.i2c.device,
101 .buf = &off,
102 .len = sizeof(off),
105 .flags = I2C_M_RD,
106 .slave = dev->path.i2c.device,
107 .buf = &val,
108 .len = sizeof(val),
112 const int ret = busdev->ops->ops_i2c_bus->
113 transfer(busdev, msg, ARRAY_SIZE(msg));
114 if (ret)
115 return ret;
116 else
117 return val;
118 } else if (busdev->ops->ops_smbus_bus->read_byte) {
119 return busdev->ops->ops_smbus_bus->read_byte(dev, off);
120 } else {
121 printk(BIOS_ERR, "%s Missing ops_smbus_bus->read_byte",
122 dev_path(busdev));
123 return -1;
127 int i2c_dev_writeb_at(struct device *const dev,
128 const uint8_t off, const uint8_t val)
130 struct device *const busdev = i2c_busdev(dev);
131 if (!busdev)
132 return -1;
134 if (busdev->ops->ops_i2c_bus) {
135 uint8_t buf[] = { off, val };
136 const struct i2c_msg msg = {
137 .flags = 0,
138 .slave = dev->path.i2c.device,
139 .buf = buf,
140 .len = sizeof(buf),
142 return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
143 } else if (busdev->ops->ops_smbus_bus->write_byte) {
144 return busdev->ops->ops_smbus_bus->write_byte(dev, off, val);
145 } else {
146 printk(BIOS_ERR, "%s Missing ops_smbus_bus->write_byte",
147 dev_path(busdev));
148 return -1;
152 int i2c_dev_read_at16(struct device *const dev,
153 uint8_t *const buf, const size_t len, uint16_t off)
155 struct device *const busdev = i2c_busdev(dev);
156 if (!busdev)
157 return -1;
159 if (busdev->ops->ops_i2c_bus) {
160 const struct i2c_msg msg[] = {
162 .flags = 0,
163 .slave = dev->path.i2c.device,
164 .buf = (uint8_t *)&off,
165 .len = sizeof(off),
168 .flags = I2C_M_RD,
169 .slave = dev->path.i2c.device,
170 .buf = buf,
171 .len = len,
175 write_be16(&off, off);
176 const int ret = busdev->ops->ops_i2c_bus->transfer(
177 busdev, msg, ARRAY_SIZE(msg));
178 if (ret)
179 return ret;
180 else
181 return len;
182 } else {
183 printk(BIOS_ERR, "%s Missing ops_i2c_bus->transfer", dev_path(busdev));
184 return -1;