1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <commonlib/bsd/helpers.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/smbus.h>
7 #include <device/i2c_bus.h>
8 #include <commonlib/endian.h>
11 bool i2c_dev_detect(struct device
*dev
, unsigned int addr
)
13 struct i2c_msg seg
= { .flags
= 0, .slave
= addr
, .buf
= NULL
, .len
= 0 };
16 return dev
->ops
->ops_i2c_bus
->transfer(dev
, &seg
, 1) == 0;
19 struct bus
*i2c_link(const struct device
*const dev
)
21 if (!dev
|| !dev
->upstream
)
24 struct bus
*link
= dev
->upstream
;
26 struct device
*const parent
= link
->dev
;
28 if (parent
&& parent
->ops
&&
29 (parent
->ops
->ops_i2c_bus
|| parent
->ops
->ops_smbus_bus
))
32 if (parent
&& parent
->upstream
&& link
!= parent
->upstream
)
33 link
= parent
->upstream
;
39 printk(BIOS_ALERT
, "%s Cannot find I2C or SMBus bus operations\n",
45 int i2c_dev_readb(struct device
*const dev
)
47 struct device
*const busdev
= i2c_busdev(dev
);
51 if (busdev
->ops
->ops_i2c_bus
) {
53 const struct i2c_msg msg
= {
55 .slave
= dev
->path
.i2c
.device
,
60 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
65 } else if (busdev
->ops
->ops_smbus_bus
->recv_byte
) {
66 return busdev
->ops
->ops_smbus_bus
->recv_byte(dev
);
69 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->recv_byte", dev_path(busdev
));
73 int i2c_dev_writeb(struct device
*const dev
, uint8_t val
)
75 struct device
*const busdev
= i2c_busdev(dev
);
79 if (busdev
->ops
->ops_i2c_bus
) {
80 const struct i2c_msg msg
= {
82 .slave
= dev
->path
.i2c
.device
,
86 return busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
87 } else if (busdev
->ops
->ops_smbus_bus
->send_byte
) {
88 return busdev
->ops
->ops_smbus_bus
->send_byte(dev
, val
);
91 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->send_byte", dev_path(busdev
));
95 int i2c_dev_readb_at(struct device
*const dev
, uint8_t off
)
97 struct device
*const busdev
= i2c_busdev(dev
);
101 if (busdev
->ops
->ops_i2c_bus
) {
103 const struct i2c_msg msg
[] = {
106 .slave
= dev
->path
.i2c
.device
,
112 .slave
= dev
->path
.i2c
.device
,
118 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
124 } else if (busdev
->ops
->ops_smbus_bus
->read_byte
) {
125 return busdev
->ops
->ops_smbus_bus
->read_byte(dev
, off
);
128 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->read_byte", dev_path(busdev
));
132 int i2c_dev_writeb_at(struct device
*const dev
, const uint8_t off
, const uint8_t val
)
134 struct device
*const busdev
= i2c_busdev(dev
);
138 if (busdev
->ops
->ops_i2c_bus
) {
139 uint8_t buf
[] = { off
, val
};
140 const struct i2c_msg msg
= {
142 .slave
= dev
->path
.i2c
.device
,
146 return busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
147 } else if (busdev
->ops
->ops_smbus_bus
->write_byte
) {
148 return busdev
->ops
->ops_smbus_bus
->write_byte(dev
, off
, val
);
151 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->write_byte", dev_path(busdev
));
155 int i2c_dev_read_at16(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
158 struct device
*const busdev
= i2c_busdev(dev
);
162 if (busdev
->ops
->ops_i2c_bus
) {
163 const struct i2c_msg msg
[] = {
166 .slave
= dev
->path
.i2c
.device
,
167 .buf
= (uint8_t *)&off
,
172 .slave
= dev
->path
.i2c
.device
,
178 write_be16(&off
, off
);
179 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
186 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));
191 int i2c_dev_read_at(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
194 struct device
*const busdev
= i2c_busdev(dev
);
198 if (busdev
->ops
->ops_i2c_bus
) {
199 const struct i2c_msg msg
[] = {
202 .slave
= dev
->path
.i2c
.device
,
208 .slave
= dev
->path
.i2c
.device
,
214 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
221 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));
226 int i2c_dev_write_at(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
229 struct device
*const busdev
= i2c_busdev(dev
);
233 if (busdev
->ops
->ops_i2c_bus
) {
234 const struct i2c_msg msg
[] = {
237 .slave
= dev
->path
.i2c
.device
,
242 .flags
= I2C_M_NOSTART
,
243 .slave
= dev
->path
.i2c
.device
,
249 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
256 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));