diff options
author | Oliver O'Halloran <oohall@gmail.com> | 2019-03-26 19:18:18 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2019-03-28 15:24:13 +1100 |
commit | 319e7d935f1354f317f32816293ade0dfd827b81 (patch) | |
tree | 33062251a9fc4bace5264a068228b12873330e10 /core/i2c.c | |
parent | d290b244efbc03c9a89e858a57b7a91186dcf364 (diff) | |
download | skiboot-319e7d935f1354f317f32816293ade0dfd827b81.zip skiboot-319e7d935f1354f317f32816293ade0dfd827b81.tar.gz skiboot-319e7d935f1354f317f32816293ade0dfd827b81.tar.bz2 |
core/i2c: split i2c_request_send()
Split the i2c_request_send() method into two methods: i2c_request_send()
which allocates and populates and i2c_request structure, and
i2c_request_sync() which take a request structure and blocks until it
completes.
This allows code that allocates a i2c_request structure elsewhere to
make use of the existing busy-wait and request retry logic. Fix the
return types to use int64_t while we're here since these are returning
OPAL_API error codes.
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'core/i2c.c')
-rw-r--r-- | core/i2c.c | 97 |
1 files changed, 53 insertions, 44 deletions
@@ -140,6 +140,56 @@ opal_call(OPAL_I2C_REQUEST, opal_i2c_request, 3); #define MAX_NACK_RETRIES 2 #define REQ_COMPLETE_POLLING 5 /* Check if req is complete in 5ms interval */ +int64_t i2c_request_sync(struct i2c_request *req) +{ + uint64_t timer_period = msecs_to_tb(5), timer_count; + uint64_t time_to_wait = 0; + int64_t rc, waited, retries; + + for (retries = 0; retries <= MAX_NACK_RETRIES; retries++) { + waited = 0; + timer_count = 0; + + i2c_queue_req(req); + + do { + time_to_wait = i2c_run_req(req); + if (!time_to_wait) + time_to_wait = REQ_COMPLETE_POLLING; + time_wait(time_to_wait); + waited += time_to_wait; + timer_count += time_to_wait; + if (timer_count > timer_period) { + /* + * The above request may be relying on + * timers to complete, yet there may + * not be called, especially during + * opal init. We could be looping here + * forever. So explicitly check the + * timers once in a while + */ + check_timers(false); + timer_count = 0; + } + } while (req->req_state != i2c_req_done); + + lwsync(); + rc = req->result; + + /* retry on NACK, otherwise exit */ + if (rc != OPAL_I2C_NACK_RCVD) + break; + req->req_state = i2c_req_new; + } + + prlog(PR_DEBUG, "I2C: %s req op=%x offset=%x buf=%016llx buflen=%d " + "delay=%lu/%lld rc=%lld\n", + (rc) ? "!!!!" : "----", req->op, req->offset, + *(uint64_t*) req->rw_buf, req->rw_len, tb_to_msecs(waited), req->timeout, rc); + + return rc; +} + /** * i2c_request_send - send request to i2c bus synchronously * @bus_id: i2c bus id @@ -155,15 +205,13 @@ opal_call(OPAL_I2C_REQUEST, opal_i2c_request, 3); * * Returns: Zero on success otherwise a negative error code */ -int i2c_request_send(int bus_id, int dev_addr, int read_write, +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) { - int rc, waited, retries; struct i2c_request *req; struct i2c_bus *bus; - uint64_t time_to_wait = 0; - uint64_t timer_period = msecs_to_tb(5), timer_count; + int64_t rc; bus = i2c_find_bus_by_id(bus_id); if (!bus) { @@ -197,46 +245,7 @@ int i2c_request_send(int bus_id, int dev_addr, int read_write, req->rw_len = buflen; req->timeout = timeout; - for (retries = 0; retries <= MAX_NACK_RETRIES; retries++) { - waited = 0; - timer_count = 0; - - i2c_queue_req(req); - - do { - time_to_wait = i2c_run_req(req); - if (!time_to_wait) - time_to_wait = REQ_COMPLETE_POLLING; - time_wait(time_to_wait); - waited += time_to_wait; - timer_count += time_to_wait; - if (timer_count > timer_period) { - /* - * The above request may be relying on - * timers to complete, yet there may - * not be called, especially during - * opal init. We could be looping here - * forever. So explicitly check the - * timers once in a while - */ - check_timers(false); - timer_count = 0; - } - } while (req->req_state != i2c_req_done); - - lwsync(); - rc = req->result; - - /* retry on NACK, otherwise exit */ - if (rc != OPAL_I2C_NACK_RCVD) - break; - req->req_state = i2c_req_new; - } - - prlog(PR_DEBUG, "I2C: %s req op=%x offset=%x buf=%016llx buflen=%d " - "delay=%lu/%d rc=%d\n", - (rc) ? "!!!!" : "----", req->op, req->offset, - *(uint64_t*) buf, req->rw_len, tb_to_msecs(waited), timeout, rc); + rc = i2c_request_sync(req); free(req); if (rc) |