aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/p8-i2c.c267
-rw-r--r--include/fsp-elog.h8
-rw-r--r--include/i2c.h14
-rw-r--r--include/opal.h10
4 files changed, 226 insertions, 73 deletions
diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
index b1f7a28..7cddb26 100644
--- a/hw/p8-i2c.c
+++ b/hw/p8-i2c.c
@@ -23,6 +23,22 @@
#include <xscom.h>
#include <timebase.h>
#include <timer.h>
+#include <opal-msg.h>
+#include <errorlog.h>
+/* XXX SRC's will be moved to errorlog.h and then remove fsp-elog.h */
+#include <fsp-elog.h>
+
+DEFINE_LOG_ENTRY(OPAL_RC_I2C_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_I2C,
+ OPAL_IO_SUBSYSTEM, OPAL_PREDICTIVE_ERR_DEGRADED_PERF,
+ OPAL_NA, NULL);
+DEFINE_LOG_ENTRY(OPAL_RC_I2C_START_REQ, OPAL_INPUT_OUTPUT_ERR_EVT, OPAL_I2C,
+ OPAL_IO_SUBSYSTEM, OPAL_INFO, OPAL_NA, NULL);
+DEFINE_LOG_ENTRY(OPAL_RC_I2C_TIMEOUT, OPAL_INPUT_OUTPUT_ERR_EVT, OPAL_I2C,
+ OPAL_IO_SUBSYSTEM, OPAL_INFO, OPAL_NA, NULL);
+DEFINE_LOG_ENTRY(OPAL_RC_I2C_TRANSFER, OPAL_INPUT_OUTPUT_ERR_EVT, OPAL_I2C,
+ OPAL_IO_SUBSYSTEM, OPAL_INFO, OPAL_NA, NULL);
+DEFINE_LOG_ENTRY(OPAL_RC_I2C_RESET, OPAL_INPUT_OUTPUT_ERR_EVT, OPAL_I2C,
+ OPAL_IO_SUBSYSTEM, OPAL_INFO, OPAL_NA, NULL);
#ifdef DEBUG
#define DBG(fmt...) prlog(PR_ERR, "I2C: " fmt)
@@ -39,8 +55,6 @@
#define I2C_RESET_DELAY_MS 5 /* 5 msecs */
#define I2C_FIFO_HI_LVL 4
#define I2C_FIFO_LO_LVL 4
-#define I2C_PAGE_WRITE_SIZE (0x1u << 8)
-#define I2C_PAGE_WRITE_MASK (I2C_PAGE_WRITE_SIZE - 1)
/*
* I2C registers set.
@@ -200,6 +214,65 @@ struct p8_i2c_request {
uint64_t timeout;
};
+static void p8_i2c_print_debug_info(struct p8_i2c_master *master,
+ struct i2c_request *req)
+{
+ uint64_t cmd, mode, stat, estat, intr;
+ int rc;
+
+ /* Print master and request structure bits */
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Master info--\n"
+ "chip_id:%d\txscom_base:0x%016llx\tstate:%d\t"
+ "bytes_sent:%d\n", master->chip_id, master->xscom_base,
+ master->state, master->bytes_sent);
+
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Request info--\n"
+ "addr:0x%04x\toffset_bytes:%d\toffset:%d\tlength:%d\n",
+ req->dev_addr, req->offset_bytes, req->offset,
+ req->rw_len);
+
+ /* Dump the current state of i2c registers */
+ rc = xscom_read(master->chip_id, master->xscom_base + I2C_CMD_REG,
+ &cmd);
+ if (rc) {
+ prlog(PR_DEBUG, "I2C: Failed to read CMD_REG\n");
+ cmd = 0ull;
+ }
+
+ rc = xscom_read(master->chip_id, master->xscom_base + I2C_MODE_REG,
+ &mode);
+ if (rc) {
+ prlog(PR_DEBUG, "I2C: Failed to read MODE_REG\n");
+ mode = 0ull;
+ }
+
+ rc = xscom_read(master->chip_id, master->xscom_base + I2C_STAT_REG,
+ &stat);
+ if (rc) {
+ prlog(PR_DEBUG, "I2C: Failed to read STAT_REG\n");
+ stat = 0ull;
+ }
+
+ rc = xscom_read(master->chip_id, master->xscom_base + I2C_EXTD_STAT_REG,
+ &estat);
+ if (rc) {
+ prlog(PR_DEBUG, "I2C: Failed to read EXTD_STAT_REG\n");
+ estat = 0ull;
+ }
+
+ rc = xscom_read(master->chip_id, master->xscom_base + I2C_INTR_MASK_REG,
+ &intr);
+ if (rc) {
+ prlog(PR_DEBUG, "I2C: Failed to read INTR_MASK_REG\n");
+ intr = 0ull;
+ }
+
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Register dump--\n"
+ "cmd:0x%016llx\tmode:0x%016llx\tstat:0x%016llx\n"
+ "estat:0x%016llx\tintr:0x%016llx\n", cmd, mode, stat,
+ estat, intr);
+}
+
static bool p8_i2c_has_irqs(void)
{
struct proc_chip *chip = next_chip(NULL);
@@ -244,7 +317,7 @@ static int p8_i2c_prog_watermark(struct p8_i2c_master *master)
&watermark);
if (rc) {
prlog(PR_ERR, "I2C: Failed to read the WATERMARK_REG\n");
- return OPAL_HARDWARE;
+ return rc;
}
/* Set the high/low watermark */
@@ -252,12 +325,10 @@ static int p8_i2c_prog_watermark(struct p8_i2c_master *master)
watermark = SETFIELD(I2C_WATERMARK_LOW, watermark, I2C_FIFO_LO_LVL);
rc = xscom_write(master->chip_id, master->xscom_base +
I2C_WATERMARK_REG, watermark);
- if (rc) {
+ if (rc)
prlog(PR_ERR, "I2C: Failed to set high/low watermark level\n");
- return OPAL_HARDWARE;
- }
- return 0;
+ return rc;
}
static int p8_i2c_prog_mode(struct p8_i2c_master *master, bool enhanced_mode)
@@ -273,7 +344,7 @@ static int p8_i2c_prog_mode(struct p8_i2c_master *master, bool enhanced_mode)
I2C_MODE_REG, &mode);
if (rc) {
prlog(PR_ERR, "I2C: Failed to read the MODE_REG\n");
- return OPAL_HARDWARE;
+ return rc;
}
omode = mode;
mode = SETFIELD(I2C_MODE_PORT_NUM, mode, request->port_num);
@@ -287,12 +358,10 @@ static int p8_i2c_prog_mode(struct p8_i2c_master *master, bool enhanced_mode)
rc = xscom_write(master->chip_id, master->xscom_base + I2C_MODE_REG,
mode);
- if (rc) {
+ if (rc)
prlog(PR_ERR, "I2C: Failed to write the MODE_REG\n");
- return OPAL_HARDWARE;
- }
- return 0;
+ return rc;
}
static void p8_i2c_complete_request(struct p8_i2c_master *master,
@@ -320,31 +389,62 @@ static int p8_i2c_engine_reset(struct p8_i2c_master *master)
rc = xscom_write(master->chip_id, master->xscom_base +
I2C_RESET_I2C_REG, 0);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to reset the i2c engine\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_RESET), "I2C: Failed "
+ "to reset the i2c engine\n");
return rc;
}
/* Reprogram the watermark and mode */
rc = p8_i2c_prog_watermark(master);
- if (rc == 0)
- rc = p8_i2c_prog_mode(master, false);
+ if (rc) {
+ log_simple_error(&e_info(OPAL_RC_I2C_RESET), "I2C: Failed to"
+ "program the WATERMARK_REG\n");
+ return rc;
+ }
+
+ rc = p8_i2c_prog_mode(master, false);
+ if (rc)
+ log_simple_error(&e_info(OPAL_RC_I2C_RESET), "I2C: Failed to"
+ "program the MODE_REG\n");
+
return rc;
}
+static void p8_i2c_translate_error(struct i2c_request *req, uint64_t status)
+{
+ /* Assuming there are not more than one type of error simultaneously */
+ if (status & I2C_STAT_NACK_RCVD_ERR)
+ req->result = OPAL_I2C_NACK_RCVD;
+ else if (status & I2C_STAT_INVALID_CMD)
+ req->result = OPAL_I2C_INVALID_CMD;
+ else if (status & I2C_STAT_LBUS_PARITY_ERR)
+ req->result = OPAL_I2C_LBUS_PARITY;
+ else if (status & I2C_STAT_BKEND_OVERRUN_ERR)
+ req->result = OPAL_I2C_BKEND_OVERRUN;
+ else if (status & I2C_STAT_BKEND_ACCESS_ERR)
+ req->result = OPAL_I2C_BKEND_ACCESS;
+ else if (status & I2C_STAT_ARBT_LOST_ERR)
+ req->result = OPAL_I2C_ARBT_LOST;
+ else if (status & I2C_STAT_STOP_ERR)
+ req->result = OPAL_I2C_STOP_ERR;
+}
+
static void p8_i2c_status_error(struct p8_i2c_master *master,
struct i2c_request *req,
uint64_t status)
{
int rc;
- uint64_t estat;
/* Display any error other than I2C_INTR_NACK_RCVD_ERR since
* getting NACK's is normal if Linux is probing the bus
*/
- if ((status & I2C_STAT_ANY_ERR) != I2C_STAT_NACK_RCVD_ERR)
- prlog(PR_ERR, "I2C: Transfer error occured, "
- "sreg=0x%016llx, state=%d\n",
- status, master->state);
+ if (!(status & I2C_STAT_NACK_RCVD_ERR)) {
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER),
+ "I2C: Transfer error occured\n");
+ p8_i2c_print_debug_info(master, req);
+ }
+
+ p8_i2c_translate_error(req, status);
rc = p8_i2c_engine_reset(master);
if (rc)
@@ -353,23 +453,11 @@ static void p8_i2c_status_error(struct p8_i2c_master *master,
if (status & (I2C_STAT_LBUS_PARITY_ERR | I2C_STAT_ARBT_LOST_ERR |
I2C_STAT_STOP_ERR)) {
/*
- * For those errors, we also grab the extended status reg
- * in order to display it
- */
- rc = xscom_read(master->chip_id,
- master->xscom_base + I2C_EXTD_STAT_REG,
- &estat);
- if (rc)
- prlog(PR_ERR, "I2C: Failed to grab extende status\n");
- else
- prlog(PR_ERR, "I2C: Extended status=%016llx\n", estat);
-
- /*
* Don't bother issuing a STOP command for those errors
* just get rid of the current request and start off with
* the fresh one in the list
*/
- p8_i2c_complete_request(master, req, OPAL_HARDWARE);
+ p8_i2c_complete_request(master, req, req->result);
} else {
/*
* Reset the bus by issuing a STOP command to slave.
@@ -377,8 +465,11 @@ static void p8_i2c_status_error(struct p8_i2c_master *master,
* Reprogram the mode register with 'enhanced bit' set
*/
rc = p8_i2c_prog_mode(master, true);
- if (rc)
+ if (rc) {
+ log_simple_error(&e_info(OPAL_RC_I2C_RESET), "I2C: "
+ "Failed to program the MODE_REG\n");
goto exit;
+ }
/* Enable the interrupt */
p8_i2c_enable_irqs(master);
@@ -388,14 +479,15 @@ static void p8_i2c_status_error(struct p8_i2c_master *master,
rc = xscom_write(master->chip_id, master->xscom_base +
I2C_CMD_REG, I2C_CMD_WITH_STOP);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to issue imm. STOP\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_RESET), "I2C: "
+ "Failed to issue immediate STOP\n");
goto exit;
}
}
return;
exit:
- p8_i2c_complete_request(master, req, rc);
+ p8_i2c_complete_request(master, req, req->result);
}
static int p8_i2c_fifo_read(struct p8_i2c_master *master,
@@ -409,7 +501,8 @@ static int p8_i2c_fifo_read(struct p8_i2c_master *master,
rc = xscom_read(master->chip_id, master->xscom_base +
I2C_FIFO_REG, &fifo);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to read the fifo\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER),
+ "I2C: Failed to read the fifo\n");
break;
}
@@ -430,7 +523,8 @@ static int p8_i2c_fifo_write(struct p8_i2c_master *master,
rc = xscom_write(master->chip_id, master->xscom_base +
I2C_FIFO_REG, fifo);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to write the fifo\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER),
+ "I2C: Failed to write the fifo\n");
break;
}
}
@@ -455,7 +549,8 @@ static void p8_i2c_status_data_request(struct p8_i2c_master *master,
case state_offset:
/* We assume the offset can always be written in one go */
if (fifo_free < req->offset_bytes) {
- prlog(PR_ERR, "I2C: Fifo too small for offset !\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER),
+ "I2C: Fifo too small for offset !\n");
rc = OPAL_HARDWARE;
} else {
rc = p8_i2c_fifo_write(master, master->obuf,
@@ -468,9 +563,10 @@ static void p8_i2c_status_data_request(struct p8_i2c_master *master,
case state_data:
/* Sanity check */
if (master->bytes_sent >= req->rw_len) {
- prlog(PR_ERR, "I2C: Data req with no data to send"
- " sent=%d req=%d\n", master->bytes_sent,
- req->rw_len);
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: "
+ "Data req with no data to send sent=%d "
+ "req=%d\n", master->bytes_sent,
+ req->rw_len);
rc = OPAL_HARDWARE;
break;
}
@@ -493,9 +589,9 @@ static void p8_i2c_status_data_request(struct p8_i2c_master *master,
master->bytes_sent += count;
break;
default:
- prlog(PR_ERR, "I2C: Invalid state %d in data req !\n",
- master->state);
- rc = OPAL_HARDWARE;
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Invalid "
+ "state %d in data req !\n", master->state);
+ rc = OPAL_WRONG_STATE;
}
if (rc)
p8_i2c_complete_request(master, req, rc);
@@ -515,7 +611,8 @@ static void p8_i2c_complete_offset(struct p8_i2c_master *master,
* write commands
*/
if (req->op == SMBUS_WRITE && req->rw_len != 0) {
- prlog(PR_ERR, "I2C: Write completion in offset state !\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Write "
+ "completion in offset state !\n");
rc = OPAL_HARDWARE;
goto complete;
}
@@ -541,8 +638,8 @@ static void p8_i2c_complete_offset(struct p8_i2c_master *master,
rc = xscom_write(master->chip_id, master->xscom_base + I2C_CMD_REG,
cmd);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to write the CMD_REG\n");
- rc = OPAL_HARDWARE;
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Failed "
+ "to write the CMD_REG\n");
goto complete;
}
@@ -574,11 +671,12 @@ static void p8_i2c_status_cmd_completion(struct p8_i2c_master *master,
* completed our data transfer properly
*/
if (master->state != state_error && master->bytes_sent != req->rw_len) {
- prlog(PR_ERR, "I2C: Request complete with residual data"
- " req=%d done=%d\n", req->rw_len, master->bytes_sent);
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Request "
+ "complete with residual data req=%d done=%d\n",
+ req->rw_len, master->bytes_sent);
/* Should we error out here ? */
}
- rc = master->state == state_error ? OPAL_HARDWARE : OPAL_SUCCESS;
+ rc = master->state == state_error ? req->result : OPAL_SUCCESS;
p8_i2c_complete_request(master, req, rc);
}
@@ -599,7 +697,8 @@ static void p8_i2c_check_status(struct p8_i2c_master *master)
rc = xscom_read(master->chip_id, master->xscom_base + I2C_STAT_REG,
&status);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to read the STAT_REG\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Failed "
+ "to read the STAT_REG\n");
return;
}
@@ -614,7 +713,8 @@ static void p8_i2c_check_status(struct p8_i2c_master *master)
rc = xscom_write(master->chip_id, master->xscom_base + I2C_INTR_REG,
~I2C_INTR_ALL_MASK);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to disable the interrupts\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Failed "
+ "to disable the interrupts\n");
return;
}
@@ -622,8 +722,8 @@ static void p8_i2c_check_status(struct p8_i2c_master *master)
* the interrupt
*/
if (req == NULL) {
- prlog(PR_ERR, "I2C: Interrupt with no request,status=%016llx\n",
- status);
+ log_simple_error(&e_info(OPAL_RC_I2C_TRANSFER), "I2C: Interrupt "
+ "with no request, status=0x%016llx\n", status);
return;
}
@@ -648,7 +748,8 @@ static int p8_i2c_check_initial_status(struct p8_i2c_master *master)
rc = xscom_read(master->chip_id, master->xscom_base + I2C_STAT_REG,
&status);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to read the STAT_REG\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: Failed "
+ "to read the STAT_REG\n");
return rc;
}
@@ -656,7 +757,8 @@ static int p8_i2c_check_initial_status(struct p8_i2c_master *master)
master->xscom_base + I2C_EXTD_STAT_REG,
&estat);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to read the EXTD_STAT_REG\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: Failed "
+ "to read the EXTD_STAT_REG\n");
return rc;
}
if (estat & (I2C_EXTD_STAT_I2C_BUSY | I2C_EXTD_STAT_SELF_BUSY)) {
@@ -666,10 +768,12 @@ static int p8_i2c_check_initial_status(struct p8_i2c_master *master)
/* Nothing happened ? Go back */
if (status & I2C_STAT_ANY_ERR) {
- prlog(PR_ERR, "I2C: Initial error status %016llx\n", status);
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: "
+ "Initial error status 0x%016llx\n", status);
if (pass > 0) {
- prlog(PR_ERR, "I2C: Error stuck, aborting\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: "
+ "Error stuck, aborting !!\n");
return OPAL_HARDWARE;
}
@@ -692,10 +796,12 @@ static int p8_i2c_check_initial_status(struct p8_i2c_master *master)
/* Still busy ? */
if (!(status & I2C_STAT_CMD_COMP)) {
- prlog(PR_ERR, "I2C: Initial commmand complete not set\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: Initial "
+ "command complete not set\n");
if (pass > 4) {
- prlog(PR_ERR, "I2C: Command stuck, aborting\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: "
+ "Command stuck, aborting !!\n");
return OPAL_HARDWARE;
}
@@ -744,8 +850,11 @@ static int p8_i2c_start_request(struct p8_i2c_master *master,
/* Program mode register */
rc = p8_i2c_prog_mode(master, false);
- if (rc)
+ if (rc) {
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: Failed "
+ "to program the MODE_REG\n");
return rc;
+ }
/* Check status */
rc = p8_i2c_check_initial_status(master);
@@ -786,8 +895,9 @@ static int p8_i2c_start_request(struct p8_i2c_master *master,
rc = xscom_write(master->chip_id, master->xscom_base + I2C_CMD_REG,
cmd);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to write the CMD_REG\n");
- return OPAL_HARDWARE;
+ log_simple_error(&e_info(OPAL_RC_I2C_START_REQ), "I2C: Failed "
+ "to write the CMD_REG\n");
+ return rc;
}
/* Enable the interrupts */
@@ -831,13 +941,12 @@ static int p8_i2c_queue_request(struct i2c_request *req)
/* Parameter check */
if (req->rw_len > I2C_MAX_TFR_LEN) {
- prlog(PR_ERR, "I2C: Too large transfer %d byes\n", req->rw_len);
+ prlog(PR_ERR, "I2C: Too large transfer %d bytes\n", req->rw_len);
return OPAL_PARAMETER;
}
if (req->offset_bytes > 4) {
- prlog(PR_ERR, "I2C: Invalid offset size %d\n",
- req->offset_bytes);
+ prlog(PR_ERR, "I2C: Invalid offset size %d\n", req->offset_bytes);
return OPAL_PARAMETER;
}
lock(&master->lock);
@@ -920,13 +1029,15 @@ static void p8_i2c_timeout(struct timer *t __unused, void *data)
}
/* Allright, we have a request and it has timed out ... */
- prlog(PR_ERR, "I2C: Request timeout !\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_TIMEOUT),
+ "I2C: Request timeout !\n");
+ p8_i2c_print_debug_info(master, req);
/* Reset the engine */
p8_i2c_engine_reset(master);
/* Should we send a stop ? For now just complete */
- p8_i2c_complete_request(master, req, OPAL_HARDWARE);
+ p8_i2c_complete_request(master, req, OPAL_I2C_TIMEOUT);
exit:
unlock(&master->lock);
@@ -992,7 +1103,8 @@ void p8_i2c_init(void)
dt_for_each_compatible(dt_root, i2cm, "ibm,power8-i2cm") {
master = zalloc(sizeof(*master));
if (!master) {
- prlog(PR_ERR,"I2C: Failed to allocate p8_i2c_master\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
+ "Failed to allocate master structure\n");
break;
}
@@ -1012,7 +1124,8 @@ void p8_i2c_init(void)
rc = xscom_read(master->chip_id, master->xscom_base +
I2C_EXTD_STAT_REG, &ex_stat);
if (rc) {
- prlog(PR_ERR, "I2C: Failed to read EXTD_STAT_REG\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
+ "Failed to read EXTD_STAT_REG\n");
free(master);
break;
}
@@ -1043,6 +1156,15 @@ void p8_i2c_init(void)
msecs_to_tb(I2C_TIMEOUT_IRQ_MS) :
msecs_to_tb(I2C_TIMEOUT_POLL_MS);
+ /* Program the watermark register */
+ rc = p8_i2c_prog_watermark(master);
+ if (rc) {
+ log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
+ "Failed to program the WATERMARK_REG\n");
+ free(master);
+ break;
+ }
+
/* Allocate ports driven by this master */
count = 0;
dt_for_each_child(i2cm, i2cm_port)
@@ -1050,7 +1172,8 @@ void p8_i2c_init(void)
port = zalloc(sizeof(*port) * count);
if (!port) {
- prlog(PR_ERR, "I2C: Insufficient memory\n");
+ log_simple_error(&e_info(OPAL_RC_I2C_INIT),
+ "I2C: Insufficient memory\n");
free(master);
break;
}
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
index df8b2f1..0610a77 100644
--- a/include/fsp-elog.h
+++ b/include/fsp-elog.h
@@ -74,6 +74,7 @@ enum elog_head_state {
#define OPAL_SENSOR 0x5345 /* SE */
#define OPAL_SLW 0x534C /* SL */
#define OPAL_FSP 0x4650 /* FP */
+#define OPAL_I2C 0x4943 /* IC */
/* SAPPHIRE SRC componenet ID*/
#define OPAL_CU 0x1000
@@ -104,6 +105,7 @@ enum elog_head_state {
#define OPAL_SE 0x2000
#define OPAL_SL 0x2100
#define OPAL_FP 0x2200
+#define OPAL_IC 0x2300
enum opal_reasoncode {
/* code update */
@@ -191,6 +193,12 @@ enum opal_reasoncode {
/* FSP */
OPAL_RC_FSP_POLL_TIMEOUT
= OPAL_FP | 0x10,
+/* I2C */
+ OPAL_RC_I2C_INIT = OPAL_IC | 0X10,
+ OPAL_RC_I2C_START_REQ = OPAL_IC | 0X11,
+ OPAL_RC_I2C_TIMEOUT = OPAL_IC | 0x12,
+ OPAL_RC_I2C_TRANSFER = OPAL_IC | 0x13,
+ OPAL_RC_I2C_RESET = OPAL_IC | 0x14,
};
#define DEFINE_LOG_ENTRY(reason, type, id, subsys, \
diff --git a/include/i2c.h b/include/i2c.h
index 1384697..dea0644 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -28,6 +28,19 @@ struct i2c_bus {
void (*free_req)(struct i2c_request *req);
};
+/*
+ * 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;
@@ -37,6 +50,7 @@ struct i2c_request {
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 */
diff --git a/include/opal.h b/include/opal.h
index 8d37d9d..effcd17 100644
--- a/include/opal.h
+++ b/include/opal.h
@@ -20,7 +20,7 @@
/****** OPAL APIs ******/
/* Return codes */
-#define OPAL_SUCCESS 0
+#define OPAL_SUCCESS 0
#define OPAL_PARAMETER -1
#define OPAL_BUSY -2
#define OPAL_PARTIAL -3
@@ -37,6 +37,14 @@
#define OPAL_WRONG_STATE -14
#define OPAL_ASYNC_COMPLETION -15
#define OPAL_EMPTY -16
+#define OPAL_I2C_TIMEOUT -17
+#define OPAL_I2C_INVALID_CMD -18
+#define OPAL_I2C_LBUS_PARITY -19
+#define OPAL_I2C_BKEND_OVERRUN -20
+#define OPAL_I2C_BKEND_ACCESS -21
+#define OPAL_I2C_ARBT_LOST -22
+#define OPAL_I2C_NACK_RCVD -23
+#define OPAL_I2C_STOP_ERR -24
/* API Tokens (in r0) */
#define OPAL_TEST 0