coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
i2c_bus.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
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>
8 
9 struct bus *i2c_link(const struct device *const dev)
10 {
11  if (!dev || !dev->bus)
12  return NULL;
13 
14  struct bus *link = dev->bus;
15  while (link) {
16  struct device *const parent = link->dev;
17 
18  if (parent && parent->ops &&
19  (parent->ops->ops_i2c_bus || parent->ops->ops_smbus_bus))
20  break;
21 
22  if (parent && parent->bus)
23  link = parent->bus;
24  else
25  link = NULL;
26  }
27 
28  if (!link)
29  printk(BIOS_ALERT, "%s Cannot find I2C or SMBus bus operations", dev_path(dev));
30 
31  return link;
32 }
33 
34 int i2c_dev_readb(struct device *const dev)
35 {
36  struct device *const busdev = i2c_busdev(dev);
37  if (!busdev)
38  return -1;
39 
40  if (busdev->ops->ops_i2c_bus) {
41  uint8_t val;
42  const struct i2c_msg msg = {
43  .flags = I2C_M_RD,
44  .slave = dev->path.i2c.device,
45  .buf = &val,
46  .len = sizeof(val),
47  };
48 
49  const int ret = busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
50  if (ret)
51  return ret;
52  else
53  return val;
54  } else if (busdev->ops->ops_smbus_bus->recv_byte) {
55  return busdev->ops->ops_smbus_bus->recv_byte(dev);
56  }
57 
58  printk(BIOS_ERR, "%s Missing ops_smbus_bus->recv_byte", dev_path(busdev));
59  return -1;
60 }
61 
62 int i2c_dev_writeb(struct device *const dev, uint8_t val)
63 {
64  struct device *const busdev = i2c_busdev(dev);
65  if (!busdev)
66  return -1;
67 
68  if (busdev->ops->ops_i2c_bus) {
69  const struct i2c_msg msg = {
70  .flags = 0,
71  .slave = dev->path.i2c.device,
72  .buf = &val,
73  .len = sizeof(val),
74  };
75  return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
76  } else if (busdev->ops->ops_smbus_bus->send_byte) {
77  return busdev->ops->ops_smbus_bus->send_byte(dev, val);
78  }
79 
80  printk(BIOS_ERR, "%s Missing ops_smbus_bus->send_byte", dev_path(busdev));
81  return -1;
82 }
83 
84 int i2c_dev_readb_at(struct device *const dev, uint8_t off)
85 {
86  struct device *const busdev = i2c_busdev(dev);
87  if (!busdev)
88  return -1;
89 
90  if (busdev->ops->ops_i2c_bus) {
91  uint8_t val;
92  const struct i2c_msg msg[] = {
93  {
94  .flags = 0,
95  .slave = dev->path.i2c.device,
96  .buf = &off,
97  .len = sizeof(off),
98  },
99  {
100  .flags = I2C_M_RD,
101  .slave = dev->path.i2c.device,
102  .buf = &val,
103  .len = sizeof(val),
104  },
105  };
106 
107  const int ret = busdev->ops->ops_i2c_bus->transfer(busdev, msg,
108  ARRAY_SIZE(msg));
109  if (ret)
110  return ret;
111  else
112  return val;
113  } else if (busdev->ops->ops_smbus_bus->read_byte) {
114  return busdev->ops->ops_smbus_bus->read_byte(dev, off);
115  }
116 
117  printk(BIOS_ERR, "%s Missing ops_smbus_bus->read_byte", dev_path(busdev));
118  return -1;
119 }
120 
121 int i2c_dev_writeb_at(struct device *const dev, const uint8_t off, const uint8_t val)
122 {
123  struct device *const busdev = i2c_busdev(dev);
124  if (!busdev)
125  return -1;
126 
127  if (busdev->ops->ops_i2c_bus) {
128  uint8_t buf[] = { off, val };
129  const struct i2c_msg msg = {
130  .flags = 0,
131  .slave = dev->path.i2c.device,
132  .buf = buf,
133  .len = sizeof(buf),
134  };
135  return busdev->ops->ops_i2c_bus->transfer(busdev, &msg, 1);
136  } else if (busdev->ops->ops_smbus_bus->write_byte) {
137  return busdev->ops->ops_smbus_bus->write_byte(dev, off, val);
138  }
139 
140  printk(BIOS_ERR, "%s Missing ops_smbus_bus->write_byte", dev_path(busdev));
141  return -1;
142 }
143 
144 int i2c_dev_read_at16(struct device *const dev, uint8_t *const buf, const size_t len,
145  uint16_t off)
146 {
147  struct device *const busdev = i2c_busdev(dev);
148  if (!busdev)
149  return -1;
150 
151  if (busdev->ops->ops_i2c_bus) {
152  const struct i2c_msg msg[] = {
153  {
154  .flags = 0,
155  .slave = dev->path.i2c.device,
156  .buf = (uint8_t *)&off,
157  .len = sizeof(off),
158  },
159  {
160  .flags = I2C_M_RD,
161  .slave = dev->path.i2c.device,
162  .buf = buf,
163  .len = len,
164  },
165  };
166 
167  write_be16(&off, off);
168  const int ret = busdev->ops->ops_i2c_bus->transfer(busdev, msg,
169  ARRAY_SIZE(msg));
170  if (ret)
171  return ret;
172  else
173  return len;
174  } else {
175  printk(BIOS_ERR, "%s Missing ops_i2c_bus->transfer", dev_path(busdev));
176  return -1;
177  }
178 }
#define ARRAY_SIZE(a)
Definition: helpers.h:12
static void write_be16(void *dest, uint16_t val)
Definition: endian.h:72
#define printk(level,...)
Definition: stdlib.h:16
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
int i2c_dev_writeb_at(struct device *const dev, const uint8_t off, const uint8_t val)
Definition: i2c_bus.c:121
int i2c_dev_readb(struct device *const dev)
Definition: i2c_bus.c:34
struct bus * i2c_link(const struct device *const dev)
Definition: i2c_bus.c:9
int i2c_dev_writeb(struct device *const dev, uint8_t val)
Definition: i2c_bus.c:62
int i2c_dev_read_at16(struct device *const dev, uint8_t *const buf, const size_t len, uint16_t off)
Definition: i2c_bus.c:144
int i2c_dev_readb_at(struct device *const dev, uint8_t off)
Definition: i2c_bus.c:84
static DEVTREE_CONST struct device * i2c_busdev(const struct device *dev)
Definition: i2c_bus.h:31
#define I2C_M_RD
Definition: i2c.h:34
#define BIOS_ALERT
BIOS_ALERT - Dying / Unrecoverable.
Definition: loglevel.h:41
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
static uint8_t * buf
Definition: uart.c:7
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
DEVTREE_CONST struct device * dev
Definition: device.h:78
const struct smbus_bus_operations * ops_smbus_bus
Definition: device.h:65
const struct i2c_bus_operations * ops_i2c_bus
Definition: device.h:63
struct i2c_path i2c
Definition: path.h:118
Definition: device.h:107
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST struct bus * bus
Definition: device.h:108
int(* transfer)(struct device *, const struct i2c_msg *, size_t count)
Definition: i2c_bus.h:13
struct i2c_msg - an I2C transaction segment beginning with START @addr: Slave address,...
Definition: i2c.h:32
uint16_t len
Definition: i2c.h:39
uint16_t flags
Definition: i2c.h:33
unsigned int device
Definition: path.h:63
int(* recv_byte)(struct device *dev)
Definition: smbus.h:10
int(* write_byte)(struct device *dev, u8 addr, u8 value)
Definition: smbus.h:13
int(* send_byte)(struct device *dev, u8 value)
Definition: smbus.h:11
int(* read_byte)(struct device *dev, u8 addr)
Definition: smbus.h:12
u8 val
Definition: sys.c:300