aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/include/i2c.h
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/include/i2c.h')
-rw-r--r--roms/skiboot/include/i2c.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/roms/skiboot/include/i2c.h b/roms/skiboot/include/i2c.h
new file mode 100644
index 000000000..a644bd427
--- /dev/null
+++ b/roms/skiboot/include/i2c.h
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2013-2019 IBM Corp. */
+
+#ifndef __I2C_H
+#define __I2C_H
+
+struct i2c_request;
+
+struct i2c_bus {
+ struct list_node link;
+ struct dt_node *dt_node;
+ uint32_t opal_id;
+ int (*queue_req)(struct i2c_request *req);
+ uint64_t (*run_req)(struct i2c_request *req);
+ int (*check_quirk)(void *data, struct i2c_request *req, int *rc);
+ void *check_quirk_data;
+};
+
+/*
+ * I2C specific OPAL error codes:
+ *
+ * OPAL_I2C_TIMEOUT I2C request timed out
+ * OPAL_I2C_INVALID_CMD New command given when old not completed yet
+ * OPAL_I2C_LBUS_PARITY Local bus parity error
+ * OPAL_I2C_BKEND_OVERRUN Writing/reading into full/empty fifo respectively
+ * OPAL_I2C_BKEND_ACCESS Writing/reading more data than requested
+ * OPAL_I2C_ARBT_LOST I2C bus is held by some other master
+ * OPAL_I2C_NACK_RCVD Slave is not responding back with the ACK
+ * OPAL_I2C_STOP_ERR Did not able to send the STOP condtion on bus
+ */
+
+struct i2c_request {
+ struct list_node link;
+ struct i2c_bus *bus;
+ enum i2c_operation {
+ I2C_READ, /* RAW read from the device without offset */
+ I2C_WRITE, /* RAW write to the device without offset */
+ SMBUS_READ, /* SMBUS protocol read from the device */
+ SMBUS_WRITE, /* SMBUS protocol write to the device */
+ } op;
+ int result; /* OPAL i2c error code */
+ uint32_t dev_addr; /* Slave device address */
+ uint32_t offset_bytes; /* Internal device offset */
+ uint32_t offset; /* Internal device offset */
+ uint32_t rw_len; /* Length of the data request */
+ void *rw_buf; /* Data request buffer */
+ enum i2c_request_state {
+ i2c_req_new, /* un-initialised */
+ i2c_req_queued, /* waiting in the queue */
+ i2c_req_done, /* request has been completed */
+ } req_state;
+
+ void (*completion)( /* Completion callback */
+ int rc, struct i2c_request *req);
+ void *user_data; /* Client data */
+ int retries;
+ uint64_t timeout; /* in ms */
+};
+
+/* Generic i2c */
+extern void i2c_add_bus(struct i2c_bus *bus);
+extern struct i2c_bus *i2c_find_bus_by_id(uint32_t opal_id);
+
+/* not generic, but useful */
+struct i2c_bus *p8_i2c_find_bus_by_port(uint32_t chip_id, int eng, int port_id);
+struct dt_node *p8_i2c_add_master_node(struct dt_node *xscom, int eng_id);
+struct dt_node *__p8_i2c_add_port_node(struct dt_node *master, int port_id,
+ uint32_t bus_speed);
+struct dt_node *p8_i2c_add_port_node(struct dt_node *xscom, int eng_id,
+ int port_id, uint32_t bus_freq);
+
+struct i2c_bus *p8_i2c_add_bus(uint32_t chip_id, int eng_id, int port_id,
+ uint32_t bus_speed);
+
+int64_t i2c_queue_req(struct i2c_request *req);
+
+static inline uint64_t i2c_run_req(struct i2c_request *req)
+{
+ if (req->bus->run_req)
+ return req->bus->run_req(req);
+ return 0;
+}
+
+static inline int i2c_check_quirk(struct i2c_request *req, int *rc)
+{
+ if (req->bus->check_quirk)
+ return req->bus->check_quirk(req->bus->check_quirk_data, req, rc);
+ return 0;
+}
+
+/* I2C synchronous request API */
+int64_t i2c_request_sync(struct i2c_request *req);
+int64_t i2c_request_send(int bus_id, int dev_addr, int read_write,
+ uint32_t offset, uint32_t offset_bytes, void* buf,
+ size_t buflen, int timeout);
+
+/* P8 implementation details */
+extern void p8_i2c_init(void);
+extern void p8_i2c_interrupt(uint32_t chip_id);
+
+/* P9 I2C Ownership Change OCC interrupt handler */
+extern void p9_i2c_bus_owner_change(u32 chip_id);
+
+#endif /* __I2C_H */