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 };
14 return dev
->ops
->ops_i2c_bus
->transfer(dev
, &seg
, 1) == 0;
17 struct bus
*i2c_link(const struct device
*const dev
)
19 if (!dev
|| !dev
->bus
)
22 struct bus
*link
= dev
->bus
;
24 struct device
*const parent
= link
->dev
;
26 if (parent
&& parent
->ops
&&
27 (parent
->ops
->ops_i2c_bus
|| parent
->ops
->ops_smbus_bus
))
30 if (parent
&& parent
->bus
&& link
!= parent
->bus
)
37 printk(BIOS_ALERT
, "%s Cannot find I2C or SMBus bus operations\n",
43 int i2c_dev_readb(struct device
*const dev
)
45 struct device
*const busdev
= i2c_busdev(dev
);
49 if (busdev
->ops
->ops_i2c_bus
) {
51 const struct i2c_msg msg
= {
53 .slave
= dev
->path
.i2c
.device
,
58 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
63 } else if (busdev
->ops
->ops_smbus_bus
->recv_byte
) {
64 return busdev
->ops
->ops_smbus_bus
->recv_byte(dev
);
67 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->recv_byte", dev_path(busdev
));
71 int i2c_dev_writeb(struct device
*const dev
, uint8_t val
)
73 struct device
*const busdev
= i2c_busdev(dev
);
77 if (busdev
->ops
->ops_i2c_bus
) {
78 const struct i2c_msg msg
= {
80 .slave
= dev
->path
.i2c
.device
,
84 return busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
85 } else if (busdev
->ops
->ops_smbus_bus
->send_byte
) {
86 return busdev
->ops
->ops_smbus_bus
->send_byte(dev
, val
);
89 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->send_byte", dev_path(busdev
));
93 int i2c_dev_readb_at(struct device
*const dev
, uint8_t off
)
95 struct device
*const busdev
= i2c_busdev(dev
);
99 if (busdev
->ops
->ops_i2c_bus
) {
101 const struct i2c_msg msg
[] = {
104 .slave
= dev
->path
.i2c
.device
,
110 .slave
= dev
->path
.i2c
.device
,
116 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
122 } else if (busdev
->ops
->ops_smbus_bus
->read_byte
) {
123 return busdev
->ops
->ops_smbus_bus
->read_byte(dev
, off
);
126 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->read_byte", dev_path(busdev
));
130 int i2c_dev_writeb_at(struct device
*const dev
, const uint8_t off
, const uint8_t val
)
132 struct device
*const busdev
= i2c_busdev(dev
);
136 if (busdev
->ops
->ops_i2c_bus
) {
137 uint8_t buf
[] = { off
, val
};
138 const struct i2c_msg msg
= {
140 .slave
= dev
->path
.i2c
.device
,
144 return busdev
->ops
->ops_i2c_bus
->transfer(busdev
, &msg
, 1);
145 } else if (busdev
->ops
->ops_smbus_bus
->write_byte
) {
146 return busdev
->ops
->ops_smbus_bus
->write_byte(dev
, off
, val
);
149 printk(BIOS_ERR
, "%s Missing ops_smbus_bus->write_byte", dev_path(busdev
));
153 int i2c_dev_read_at16(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
156 struct device
*const busdev
= i2c_busdev(dev
);
160 if (busdev
->ops
->ops_i2c_bus
) {
161 const struct i2c_msg msg
[] = {
164 .slave
= dev
->path
.i2c
.device
,
165 .buf
= (uint8_t *)&off
,
170 .slave
= dev
->path
.i2c
.device
,
176 write_be16(&off
, off
);
177 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
184 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));
189 int i2c_dev_read_at(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
192 struct device
*const busdev
= i2c_busdev(dev
);
196 if (busdev
->ops
->ops_i2c_bus
) {
197 const struct i2c_msg msg
[] = {
200 .slave
= dev
->path
.i2c
.device
,
206 .slave
= dev
->path
.i2c
.device
,
212 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
219 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));
224 int i2c_dev_write_at(struct device
*const dev
, uint8_t *const buf
, const size_t len
,
227 struct device
*const busdev
= i2c_busdev(dev
);
231 if (busdev
->ops
->ops_i2c_bus
) {
232 const struct i2c_msg msg
[] = {
235 .slave
= dev
->path
.i2c
.device
,
240 .flags
= I2C_M_NOSTART
,
241 .slave
= dev
->path
.i2c
.device
,
247 const int ret
= busdev
->ops
->ops_i2c_bus
->transfer(busdev
, msg
,
254 printk(BIOS_ERR
, "%s Missing ops_i2c_bus->transfer", dev_path(busdev
));