/* Copyright 2013 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ /* I2C port module for MEC1322 */ #include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" #include "registers.h" #include "task.h" #include "timer.h" #include "util.h" #define CPUTS(outstr) cputs(CC_I2C, outstr) #define CPRINTS(format, args...) cprints(CC_I2C, format, ## args) #define I2C_CLOCK 16000000 /* 16 MHz */ /* Status */ #define STS_NBB BIT(0) /* Bus busy */ #define STS_LAB BIT(1) /* Arbitration lost */ #define STS_LRB BIT(3) /* Last received bit */ #define STS_BER BIT(4) /* Bus error */ #define STS_PIN BIT(7) /* Pending interrupt */ /* Control */ #define CTRL_ACK BIT(0) /* Acknowledge */ #define CTRL_STO BIT(1) /* STOP */ #define CTRL_STA BIT(2) /* START */ #define CTRL_ENI BIT(3) /* Enable interrupt */ #define CTRL_ESO BIT(6) /* Enable serial output */ #define CTRL_PIN BIT(7) /* Pending interrupt not */ /* Completion */ #define COMP_IDLE BIT(29) /* i2c bus is idle */ #define COMP_RW_BITS_MASK 0x3C /* R/W bits mask */ /* Maximum transfer of a SMBUS block transfer */ #define SMBUS_MAX_BLOCK_SIZE 32 /* * Amount of time to blocking wait for i2c bus to finish. After this blocking * timeout, if the bus is still not finished, then allow other tasks to run. * Note: this is just long enough for a 400kHz bus to finish transmitting one * byte assuming the bus isn't being held. */ #define I2C_WAIT_BLOCKING_TIMEOUT_US 25 enum i2c_transaction_state { /* Stop condition was sent in previous transaction */ I2C_TRANSACTION_STOPPED, /* Stop condition was not sent in previous transaction */ I2C_TRANSACTION_OPEN, }; /* I2C controller state data */ static struct { /* Transaction timeout, or 0 to use default. */ uint32_t timeout_us; /* Task waiting on port, or TASK_ID_INVALID if none. */ volatile task_id_t task_waiting; enum i2c_transaction_state transaction_state; } cdata[I2C_CONTROLLER_COUNT]; /* Map port number to port name in datasheet, for debug prints. */ static const char *i2c_port_names[MEC1322_I2C_PORT_COUNT] = { [MEC1322_I2C0_0] = "0_0", [MEC1322_I2C0_1] = "0_1", [MEC1322_I2C1] = "1", [MEC1322_I2C2] = "2", [MEC1322_I2C3] = "3", }; static void configure_controller_speed(int controller, int kbps) { int t_low, t_high; const int period = I2C_CLOCK / 1000 / kbps; /* * Refer to NXP UM10204 for minimum timing requirement of T_Low and * T_High. * http://www.nxp.com/documents/user_manual/UM10204.pdf */ if (kbps > 400) { /* Fast mode plus */ t_low = t_high = period / 2 - 1; MEC1322_I2C_DATA_TIM(controller) = 0x06060601; MEC1322_I2C_DATA_TIM_2(controller) = 0x06; } else if (kbps > 100) { /* Fast mode */ /* By spec, clk low period is 1.3us min */ t_low = MAX((int)(I2C_CLOCK * 1.3 / 1000000), period / 2 - 1); t_high = period - t_low - 2; MEC1322_I2C_DATA_TIM(controller) = 0x040a0a01; MEC1322_I2C_DATA_TIM_2(controller) = 0x0a; } else { /* Standard mode */ t_low = t_high = period / 2 - 1; MEC1322_I2C_DATA_TIM(controller) = 0x0c4d5006; MEC1322_I2C_DATA_TIM_2(controller) = 0x4d; } /* Clock periods is one greater than the contents of these fields */ MEC1322_I2C_BUS_CLK(controller) = ((t_high & 0xff) << 8) | (t_low & 0xff); } static void configure_controller(int controller, int kbps) { MEC1322_I2C_CTRL(controller) = CTRL_PIN; MEC1322_I2C_OWN_ADDR(controller) = 0x0; configure_controller_speed(controller, kbps); MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ACK | CTRL_ENI; MEC1322_I2C_CONFIG(controller) |= BIT(10); /* ENAB */ /* Enable interrupt */ MEC1322_I2C_CONFIG(controller) |= BIT(29); /* ENIDI */ MEC1322_INT_ENABLE(12) |= BIT(controller); MEC1322_INT_BLK_EN |= BIT(12); } static void reset_controller(int controller) { int i; MEC1322_I2C_CONFIG(controller) |= BIT(9); udelay(100); MEC1322_I2C_CONFIG(controller) &= ~BIT(9); for (i = 0; i < i2c_ports_used; ++i) if (controller == i2c_port_to_controller(i2c_ports[i].port)) { configure_controller(controller, i2c_ports[i].kbps); cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; break; } } static int wait_for_interrupt(int controller, int timeout) { int event; if (timeout <= 0) return EC_ERROR_TIMEOUT; cdata[controller].task_waiting = task_get_current(); task_enable_irq(MEC1322_IRQ_I2C_0 + controller); /* Wait until I2C interrupt or timeout. */ event = task_wait_event_mask(TASK_EVENT_I2C_IDLE, timeout); task_disable_irq(MEC1322_IRQ_I2C_0 + controller); cdata[controller].task_waiting = TASK_ID_INVALID; return (event & TASK_EVENT_TIMER) ? EC_ERROR_TIMEOUT : EC_SUCCESS; } static int wait_idle(int controller) { uint8_t sts = MEC1322_I2C_STATUS(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; int rv = 0; while (!(sts & STS_NBB)) { if (rv) return rv; if (get_time().val > block_timeout) rv = wait_for_interrupt(controller, task_timeout - get_time().val); sts = MEC1322_I2C_STATUS(controller); } if (sts & (STS_BER | STS_LAB)) return EC_ERROR_UNKNOWN; return EC_SUCCESS; } static int wait_byte_done(int controller) { uint8_t sts = MEC1322_I2C_STATUS(controller); uint64_t block_timeout = get_time().val + I2C_WAIT_BLOCKING_TIMEOUT_US; uint64_t task_timeout = block_timeout + cdata[controller].timeout_us; int rv = 0; while (sts & STS_PIN) { if (rv) return rv; if (get_time().val > block_timeout) rv = wait_for_interrupt(controller, task_timeout - get_time().val); sts = MEC1322_I2C_STATUS(controller); } return sts & STS_LRB; } static void select_port(int port) { /* * I2C0_1 uses port 1 of controller 0. All other I2C pin sets * use port 0. */ uint8_t port_sel = (port == MEC1322_I2C0_1) ? 1 : 0; int controller = i2c_port_to_controller(port); MEC1322_I2C_CONFIG(controller) &= ~0xf; MEC1322_I2C_CONFIG(controller) |= port_sel; } static inline int get_line_level(int controller) { int ret, ctrl; /* * We need to enable BB (Bit Bang) mode in order to read line level * properly, othervise line levels return always idle (0x60). */ ctrl = MEC1322_I2C_BB_CTRL(controller); MEC1322_I2C_BB_CTRL(controller) |= 1; ret = (MEC1322_I2C_BB_CTRL(controller) >> 5) & 0x3; MEC1322_I2C_BB_CTRL(controller) = ctrl; return ret; } static inline void push_in_buf(uint8_t **in, uint8_t val, int skip) { if (!skip) { **in = val; (*in)++; } } int chip_i2c_xfer(const int port, const uint16_t slave_addr_flags, const uint8_t *out, int out_size, uint8_t *in, int in_size, int flags) { int i; int controller; int send_start = flags & I2C_XFER_START; int send_stop = flags & I2C_XFER_STOP; int skip = 0; int bytes_to_read; uint8_t reg; int ret_done; if (out_size == 0 && in_size == 0) return EC_SUCCESS; select_port(port); controller = i2c_port_to_controller(port); if (send_start && cdata[controller].transaction_state == I2C_TRANSACTION_STOPPED) wait_idle(controller); reg = MEC1322_I2C_STATUS(controller); if (send_start && cdata[controller].transaction_state == I2C_TRANSACTION_STOPPED && (((reg & (STS_BER | STS_LAB)) || !(reg & STS_NBB)) || (get_line_level(controller) != I2C_LINE_IDLE))) { CPRINTS("i2c%s bad status 0x%02x, SCL=%d, SDA=%d", i2c_port_names[port], reg, get_line_level(controller) & I2C_LINE_SCL_HIGH, get_line_level(controller) & I2C_LINE_SDA_HIGH); /* Attempt to unwedge the port. */ i2c_unwedge(port); /* Bus error, bus busy, or arbitration lost. Try reset. */ reset_controller(controller); select_port(port); /* * We don't know what edges the slave saw, so sleep long enough * that the slave will see the new start condition below. */ usleep(1000); } if (out_size) { if (send_start) { MEC1322_I2C_DATA(controller) = (uint8_t)(I2C_STRIP_FLAGS(slave_addr_flags) << 1); /* Clock out the slave address, sending START bit */ MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ENI | CTRL_ACK | CTRL_STA; cdata[controller].transaction_state = I2C_TRANSACTION_OPEN; } for (i = 0; i < out_size; ++i) { ret_done = wait_byte_done(controller); if (ret_done) goto err_chip_i2c_xfer; MEC1322_I2C_DATA(controller) = out[i]; } ret_done = wait_byte_done(controller); if (ret_done) goto err_chip_i2c_xfer; /* * Send STOP bit if the stop flag is on, and caller * doesn't expect to receive data. */ if (send_stop && in_size == 0) { MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; } } if (in_size) { /* Resend start bit when changing direction */ if (out_size || send_start) { /* Repeated start case */ if (cdata[controller].transaction_state == I2C_TRANSACTION_OPEN) MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_STA | CTRL_ACK | CTRL_ENI; MEC1322_I2C_DATA(controller) = (uint8_t)(I2C_STRIP_FLAGS(slave_addr_flags) << 1) | 0x01; /* New transaction case, clock out slave address. */ if (cdata[controller].transaction_state == I2C_TRANSACTION_STOPPED) MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_STA | CTRL_ACK | CTRL_ENI | CTRL_PIN; cdata[controller].transaction_state = I2C_TRANSACTION_OPEN; /* Skip over the unused byte */ skip = 1; in_size++; } /* Special flags need to be set for last two bytes */ bytes_to_read = send_stop ? in_size - 2 : in_size; for (i = 0; i < bytes_to_read; ++i) { ret_done = wait_byte_done(controller); if (ret_done) goto err_chip_i2c_xfer; push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); skip = 0; } ret_done = wait_byte_done(controller); if (ret_done) goto err_chip_i2c_xfer; if (send_stop) { /* * De-assert ACK bit before reading the next to last * byte, so that the last byte is NACK'ed. */ MEC1322_I2C_CTRL(controller) = CTRL_ESO | CTRL_ENI; push_in_buf(&in, MEC1322_I2C_DATA(controller), skip); ret_done = wait_byte_done(controller); if (ret_done) goto err_chip_i2c_xfer; /* Send STOP */ MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_ACK | CTRL_STO; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; /* * We need to know our stop point two bytes in * advance. If we don't know soon enough, we need * to do an extra read (to last_addr + 1) to * issue the stop. */ push_in_buf(&in, MEC1322_I2C_DATA(controller), in_size == 1); } } /* Check for error conditions */ if (MEC1322_I2C_STATUS(controller) & (STS_LAB | STS_BER)) return EC_ERROR_UNKNOWN; return EC_SUCCESS; err_chip_i2c_xfer: /* Send STOP and return error */ MEC1322_I2C_CTRL(controller) = CTRL_PIN | CTRL_ESO | CTRL_STO | CTRL_ACK; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; if (ret_done == STS_LRB) return EC_ERROR_BUSY; else if (ret_done == EC_ERROR_TIMEOUT) { /* * If our transaction timed out then our i2c controller * may be wedged without showing any other outward signs * of failure. Reset the controller so that future * transactions have a chance of success. */ reset_controller(controller); return EC_ERROR_TIMEOUT; } else return EC_ERROR_UNKNOWN; } int i2c_raw_get_scl(int port) { enum gpio_signal g; /* If no SCL pin defined for this port, then return 1 to appear idle. */ if (get_scl_from_i2c_port(port, &g) != EC_SUCCESS) return 1; return gpio_get_level(g); } int i2c_raw_get_sda(int port) { enum gpio_signal g; /* If no SDA pin defined for this port, then return 1 to appear idle. */ if (get_sda_from_i2c_port(port, &g) != EC_SUCCESS) return 1; return gpio_get_level(g); } int i2c_get_line_levels(int port) { int rv; i2c_lock(port, 1); select_port(port); rv = get_line_level(i2c_port_to_controller(port)); i2c_lock(port, 0); return rv; } int i2c_port_to_controller(int port) { if (port < 0 || port >= MEC1322_I2C_PORT_COUNT) return -1; return (port == MEC1322_I2C0_0) ? 0 : port - 1; } void i2c_set_timeout(int port, uint32_t timeout) { /* Param is port, but timeout is stored by-controller. */ cdata[i2c_port_to_controller(port)].timeout_us = timeout ? timeout : I2C_TIMEOUT_DEFAULT_US; } void i2c_init(void) { int i; int controller; int controller0_kbps = -1; /* Configure GPIOs */ gpio_config_module(MODULE_I2C, 1); for (i = 0; i < i2c_ports_used; ++i) { /* * If this controller has multiple ports, check if we already * configured it. If so, ensure previously configured bitrate * matches. */ controller = i2c_port_to_controller(i2c_ports[i].port); if (controller == 0) { if (controller0_kbps != -1) { ASSERT(controller0_kbps == i2c_ports[i].kbps); continue; } controller0_kbps = i2c_ports[i].kbps; } configure_controller(controller, i2c_ports[i].kbps); cdata[controller].task_waiting = TASK_ID_INVALID; cdata[controller].transaction_state = I2C_TRANSACTION_STOPPED; /* Use default timeout. */ i2c_set_timeout(i2c_ports[i].port, 0); } } static void handle_interrupt(int controller) { int id = cdata[controller].task_waiting; /* Clear the interrupt status */ MEC1322_I2C_COMPLETE(controller) &= (COMP_RW_BITS_MASK | COMP_IDLE); /* * Write to control register interferes with I2C transaction. * Instead, let's disable IRQ from the core until the next time * we want to wait for STS_PIN/STS_NBB. */ task_disable_irq(MEC1322_IRQ_I2C_0 + controller); /* Wake up the task which was waiting on the I2C interrupt, if any. */ if (id != TASK_ID_INVALID) task_set_event(id, TASK_EVENT_I2C_IDLE); } void i2c0_interrupt(void) { handle_interrupt(0); } void i2c1_interrupt(void) { handle_interrupt(1); } void i2c2_interrupt(void) { handle_interrupt(2); } void i2c3_interrupt(void) { handle_interrupt(3); } DECLARE_IRQ(MEC1322_IRQ_I2C_0, i2c0_interrupt, 2); DECLARE_IRQ(MEC1322_IRQ_I2C_1, i2c1_interrupt, 2); DECLARE_IRQ(MEC1322_IRQ_I2C_2, i2c2_interrupt, 2); DECLARE_IRQ(MEC1322_IRQ_I2C_3, i2c3_interrupt, 2);