113 lines
3.5 KiB
C
113 lines
3.5 KiB
C
/* Copyright 2013-2014 IBM Corp.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#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);
|
|
|
|
static inline int64_t i2c_queue_req(struct i2c_request *req)
|
|
{
|
|
int64_t ret = req->bus->queue_req(req);
|
|
|
|
if (!ret)
|
|
req->req_state = i2c_req_queued;
|
|
return ret;
|
|
}
|
|
|
|
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 */
|