Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 Linaro Ltd. |
| 3 | * |
| 4 | * SPDX-License-Identifier: Apache-2.0 |
| 5 | */ |
| 6 | |
| 7 | /** |
| 8 | * @file |
| 9 | * @brief Software driven 'bit-banging' library for I2C |
| 10 | * |
| 11 | * This code implements the I2C single master protocol in software by directly |
| 12 | * manipulating the levels of the SCL and SDA lines of an I2C bus. It supports |
| 13 | * the Standard-mode and Fast-mode speeds and doesn't support optional |
| 14 | * protocol feature like 10-bit addresses or clock stretching. |
| 15 | * |
| 16 | * Timings and protocol are based Rev. 6 of the I2C specification: |
| 17 | * http://www.nxp.com/documents/user_manual/UM10204.pdf |
| 18 | */ |
| 19 | |
| 20 | #include <errno.h> |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 21 | #include <kernel.h> |
Anas Nashif | 3b7dd6e | 2017-10-01 08:36:49 -0400 | [diff] [blame] | 22 | #include <i2c.h> |
| 23 | #include "i2c_bitbang.h" |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 24 | |
| 25 | /* |
| 26 | * Indexes into delay table for each part of I2C timing waveform we are |
| 27 | * interested in. In practice, for Standard and Fast modes, there are only two |
| 28 | * different numerical values (T_LOW and T_HIGH) so we alias the others to |
| 29 | * these. (Actually, we're simplifying a little, T_SU_STA could be T_HIGH on |
| 30 | * Fast mode) |
| 31 | */ |
| 32 | #define T_LOW 0 |
| 33 | #define T_HIGH 1 |
| 34 | #define T_SU_STA T_LOW |
| 35 | #define T_HD_STA T_HIGH |
| 36 | #define T_SU_STP T_HIGH |
| 37 | #define T_BUF T_LOW |
| 38 | |
| 39 | #define NS_TO_SYS_CLOCK_HW_CYCLES(ns) \ |
| 40 | ((u64_t)CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC * (ns) / NSEC_PER_SEC + 1) |
| 41 | |
| 42 | static const u32_t delays_fast[] = { |
| 43 | [T_LOW] = NS_TO_SYS_CLOCK_HW_CYCLES(1300), |
| 44 | [T_HIGH] = NS_TO_SYS_CLOCK_HW_CYCLES(600), |
| 45 | }; |
| 46 | |
| 47 | static const u32_t delays_standard[] = { |
| 48 | [T_LOW] = NS_TO_SYS_CLOCK_HW_CYCLES(4700), |
| 49 | [T_HIGH] = NS_TO_SYS_CLOCK_HW_CYCLES(4000), |
| 50 | }; |
| 51 | |
| 52 | int i2c_bitbang_configure(struct i2c_bitbang *context, u32_t dev_config) |
| 53 | { |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 54 | /* Check for features we don't support */ |
Kumar Gala | 83643a2 | 2017-09-13 11:31:00 -0500 | [diff] [blame] | 55 | if (I2C_ADDR_10_BITS & dev_config) { |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 56 | return -ENOTSUP; |
| 57 | } |
| 58 | |
| 59 | /* Setup speed to use */ |
Kumar Gala | 83643a2 | 2017-09-13 11:31:00 -0500 | [diff] [blame] | 60 | switch (I2C_SPEED_GET(dev_config)) { |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 61 | case I2C_SPEED_STANDARD: |
| 62 | context->delays = delays_standard; |
| 63 | break; |
| 64 | case I2C_SPEED_FAST: |
| 65 | context->delays = delays_fast; |
| 66 | break; |
| 67 | default: |
| 68 | return -ENOTSUP; |
| 69 | } |
| 70 | |
| 71 | return 0; |
| 72 | } |
| 73 | |
| 74 | static void i2c_set_scl(struct i2c_bitbang *context, int state) |
| 75 | { |
| 76 | context->io->set_scl(context->io_context, state); |
| 77 | } |
| 78 | |
| 79 | static void i2c_set_sda(struct i2c_bitbang *context, int state) |
| 80 | { |
| 81 | context->io->set_sda(context->io_context, state); |
| 82 | } |
| 83 | |
| 84 | static int i2c_get_sda(struct i2c_bitbang *context) |
| 85 | { |
| 86 | return context->io->get_sda(context->io_context); |
| 87 | } |
| 88 | |
| 89 | static void i2c_delay(unsigned int cycles_to_wait) |
| 90 | { |
| 91 | u32_t start = k_cycle_get_32(); |
| 92 | |
| 93 | /* Wait until the given number of cycles have passed */ |
| 94 | while (k_cycle_get_32() - start < cycles_to_wait) { |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | static void i2c_start(struct i2c_bitbang *context) |
| 99 | { |
| 100 | if (!i2c_get_sda(context)) { |
| 101 | /* |
| 102 | * SDA is already low, so we need to do something to make it |
| 103 | * high. Try pulsing clock low to get slave to release SDA. |
| 104 | */ |
| 105 | i2c_set_scl(context, 0); |
| 106 | i2c_delay(context->delays[T_LOW]); |
| 107 | i2c_set_scl(context, 1); |
| 108 | i2c_delay(context->delays[T_SU_STA]); |
| 109 | } |
| 110 | i2c_set_sda(context, 0); |
| 111 | i2c_delay(context->delays[T_HD_STA]); |
| 112 | } |
| 113 | |
| 114 | static void i2c_repeated_start(struct i2c_bitbang *context) |
| 115 | { |
| 116 | i2c_delay(context->delays[T_SU_STA]); |
| 117 | i2c_start(context); |
| 118 | } |
| 119 | |
| 120 | static void i2c_stop(struct i2c_bitbang *context) |
| 121 | { |
| 122 | if (i2c_get_sda(context)) { |
| 123 | /* |
| 124 | * SDA is already high, so we need to make it low so that |
| 125 | * we can create a rising edge. This means we're effectively |
| 126 | * doing a START. |
| 127 | */ |
| 128 | i2c_delay(context->delays[T_SU_STA]); |
| 129 | i2c_set_sda(context, 0); |
| 130 | i2c_delay(context->delays[T_HD_STA]); |
| 131 | } |
| 132 | i2c_delay(context->delays[T_SU_STP]); |
| 133 | i2c_set_sda(context, 1); |
| 134 | i2c_delay(context->delays[T_BUF]); /* In case we start again too soon */ |
| 135 | } |
| 136 | |
| 137 | static void i2c_write_bit(struct i2c_bitbang *context, int bit) |
| 138 | { |
| 139 | i2c_set_scl(context, 0); |
| 140 | /* SDA hold time is zero, so no need for a delay here */ |
| 141 | i2c_set_sda(context, bit); |
| 142 | i2c_delay(context->delays[T_LOW]); |
| 143 | i2c_set_scl(context, 1); |
| 144 | i2c_delay(context->delays[T_HIGH]); |
| 145 | } |
| 146 | |
| 147 | static bool i2c_read_bit(struct i2c_bitbang *context) |
| 148 | { |
| 149 | bool bit; |
| 150 | |
| 151 | i2c_set_scl(context, 0); |
| 152 | /* SDA hold time is zero, so no need for a delay here */ |
| 153 | i2c_set_sda(context, 1); /* Stop driving low, so slave has control */ |
| 154 | i2c_delay(context->delays[T_LOW]); |
| 155 | bit = i2c_get_sda(context); |
| 156 | i2c_set_scl(context, 1); |
| 157 | i2c_delay(context->delays[T_HIGH]); |
| 158 | return bit; |
| 159 | } |
| 160 | |
| 161 | static bool i2c_write_byte(struct i2c_bitbang *context, u8_t byte) |
| 162 | { |
| 163 | u8_t mask = 1 << 7; |
| 164 | |
| 165 | do { |
| 166 | i2c_write_bit(context, byte & mask); |
| 167 | } while (mask >>= 1); |
| 168 | |
| 169 | /* Return inverted ACK bit, i.e. 'true' for ACK, 'false' for NACK */ |
| 170 | return !i2c_read_bit(context); |
| 171 | } |
| 172 | |
| 173 | static u8_t i2c_read_byte(struct i2c_bitbang *context) |
| 174 | { |
| 175 | unsigned int byte = 1; |
| 176 | |
| 177 | do { |
| 178 | byte <<= 1; |
| 179 | byte |= i2c_read_bit(context); |
| 180 | } while (!(byte & (1 << 8))); |
| 181 | |
| 182 | return byte; |
| 183 | } |
| 184 | |
| 185 | int i2c_bitbang_transfer(struct i2c_bitbang *context, |
| 186 | struct i2c_msg *msgs, u8_t num_msgs, |
| 187 | u16_t slave_address) |
| 188 | { |
| 189 | u8_t *buf, *buf_end; |
| 190 | unsigned int flags; |
| 191 | int result = -EIO; |
| 192 | |
| 193 | if (!num_msgs) { |
| 194 | return 0; |
| 195 | } |
| 196 | |
| 197 | /* We want an initial Start condition */ |
| 198 | flags = I2C_MSG_RESTART; |
| 199 | |
| 200 | /* Make sure we're in a good state so slave recognises the Start */ |
| 201 | i2c_set_scl(context, 1); |
| 202 | flags |= I2C_MSG_STOP; |
| 203 | |
| 204 | do { |
| 205 | /* Stop flag from previous message? */ |
| 206 | if (flags & I2C_MSG_STOP) { |
| 207 | i2c_stop(context); |
| 208 | } |
| 209 | |
| 210 | /* Forget old flags except start flag */ |
| 211 | flags &= I2C_MSG_RESTART; |
| 212 | |
| 213 | /* Start condition? */ |
| 214 | if (flags & I2C_MSG_RESTART) { |
| 215 | i2c_start(context); |
| 216 | } else if (msgs->flags & I2C_MSG_RESTART) { |
| 217 | i2c_repeated_start(context); |
| 218 | } |
| 219 | |
| 220 | /* Get flags for new message */ |
| 221 | flags |= msgs->flags; |
| 222 | |
| 223 | /* Send address after any Start condition */ |
| 224 | if (flags & I2C_MSG_RESTART) { |
| 225 | unsigned int byte0 = slave_address << 1; |
| 226 | |
| 227 | byte0 |= (flags & I2C_MSG_RW_MASK) == I2C_MSG_READ; |
| 228 | if (!i2c_write_byte(context, byte0)) { |
| 229 | goto finish; /* No ACK received */ |
| 230 | } |
| 231 | flags &= ~I2C_MSG_RESTART; |
| 232 | } |
| 233 | |
| 234 | /* Transfer data */ |
| 235 | buf = msgs->buf; |
| 236 | buf_end = buf + msgs->len; |
| 237 | if ((flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { |
| 238 | /* Read */ |
| 239 | while (buf < buf_end) { |
| 240 | *buf++ = i2c_read_byte(context); |
| 241 | /* ACK the byte, except for the last one */ |
| 242 | i2c_write_bit(context, buf == buf_end); |
| 243 | } |
| 244 | } else { |
| 245 | /* Write */ |
| 246 | while (buf < buf_end) { |
| 247 | if (!i2c_write_byte(context, *buf++)) { |
| 248 | goto finish; /* No ACK received */ |
| 249 | } |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | /* Next message */ |
| 254 | msgs++; |
| 255 | num_msgs--; |
| 256 | } while (num_msgs); |
| 257 | |
| 258 | /* Complete without error */ |
| 259 | result = 0; |
| 260 | finish: |
| 261 | i2c_stop(context); |
| 262 | |
| 263 | return result; |
| 264 | } |
| 265 | |
| 266 | void i2c_bitbang_init(struct i2c_bitbang *context, |
| 267 | const struct i2c_bitbang_io *io, void *io_context) |
| 268 | { |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 269 | context->io = io; |
| 270 | context->io_context = io_context; |
Kumar Gala | 83643a2 | 2017-09-13 11:31:00 -0500 | [diff] [blame] | 271 | i2c_bitbang_configure(context, I2C_SPEED_STANDARD << I2C_SPEED_SHIFT); |
Jon Medhurst | 0818564 | 2016-08-25 14:06:32 +0100 | [diff] [blame] | 272 | } |