1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <platsupport/i2c.h> 14 15#include <string.h> 16#include <utils/util.h> 17#include <utils/zf_log_if.h> 18#include <assert.h> 19 20/** 21 * Register based I2C device 22 * We use copyin/out in order to automatically fix endianess and 23 * also because a write operation must be a contiguous stream of register 24 * address then data. 25 */ 26#define ABS(x) ( ((x) < 0)? -x : x ) 27 28#define BUFFER_SIZE 128 29 30/* Copy from data into buf while fixing endianess */ 31static void 32_fill_data(char* buf, const char* data, enum kvfmt fmt, int count) 33{ 34 int bytes = ABS(fmt); 35 int i, j; 36 for (j = 0; j < count; j++) { 37 for (i = 0; i < bytes; i++) { 38 int idx = (fmt > 0) ? i : (bytes - 1) - i; 39 buf[idx] = data[i]; 40 } 41 data += bytes; 42 buf += bytes; 43 } 44} 45 46/* Copy reg into buf with required endianess */ 47static int 48_fill_reg(char* buf, uint64_t reg, enum kvfmt fmt) 49{ 50 int i; 51 int bytes = ABS(fmt); 52 for (i = 0; i < bytes; i++, reg >>= 8) { 53 int idx = (fmt > 0) ? i : (bytes - 1) - i; 54 buf[idx] = reg & 0xff; 55 } 56 return i; 57} 58 59/* Read no more than count registers into data with correct endianess */ 60static int 61_do_kvread(i2c_kvslave_t* kvs, uint64_t reg, void* data, int count) 62{ 63 int abytes, dbytes, bytes; 64 char d[BUFFER_SIZE]; 65 assert(kvs); 66 assert(kvs->slave); 67 abytes = ABS(kvs->address_fmt); 68 dbytes = ABS(kvs->data_fmt); 69 assert(abytes < BUFFER_SIZE && dbytes < BUFFER_SIZE); 70 /* Limit the amount of data to read to fit our buffer */ 71 if (count * dbytes > BUFFER_SIZE) { 72 count = BUFFER_SIZE / dbytes; 73 } 74 /* Send the register address */ 75 ZF_LOGD("Seek register 0x%02llx", reg); 76 _fill_reg(d, reg, kvs->address_fmt); 77 bytes = i2c_slave_write(kvs->slave, d, abytes, true, NULL, NULL); 78 if (bytes != abytes) { 79 ZF_LOGE("Bus error on reg address select write."); 80 return -1; 81 } 82 /* Receive the reply */ 83 ZF_LOGD("Read register %d", dbytes * count); 84 bytes = i2c_slave_read(kvs->slave, d, dbytes * count, false, NULL, NULL); 85 if (bytes < 0) { 86 ZF_LOGE("Failed to read I2C register."); 87 return bytes; 88 } 89 if (bytes != dbytes * count) { 90 ZF_LOGW("short read %d/%d", bytes, dbytes * count); 91 } 92 /* Fix endianess */ 93 count = bytes / dbytes; 94 _fill_data(data, d, kvs->data_fmt, count); 95 return count; 96} 97 98/* Write no more than count registers from data */ 99static int 100_do_kvwrite(i2c_kvslave_t* kvs, uint64_t reg, const void* data, int count) 101{ 102 int abytes, dbytes, bytes; 103 char d[BUFFER_SIZE]; 104 assert(kvs); 105 assert(kvs->slave); 106 abytes = ABS(kvs->address_fmt); 107 dbytes = ABS(kvs->data_fmt); 108 assert(abytes < BUFFER_SIZE && dbytes < BUFFER_SIZE); 109 /* Limit the amount of data to fit our buffer */ 110 if (count * dbytes + abytes > BUFFER_SIZE) { 111 count = (BUFFER_SIZE - abytes) / dbytes; 112 } 113 /* Set up the register address */ 114 ZF_LOGD("Seek register 0x%02llx", reg); 115 _fill_reg(d, reg, kvs->address_fmt); 116 /* Load up the data */ 117 _fill_data(d + abytes, data, kvs->data_fmt, count); 118 /* Send the request */ 119 bytes = i2c_slave_write(kvs->slave, d, abytes + count * dbytes, false, NULL, NULL); 120 if (bytes <= 0) { 121 ZF_LOGE("Bus error (%d)", bytes); 122 return bytes; 123 } 124 count = (bytes - abytes) / dbytes; 125 return count; 126} 127 128int 129i2c_slave_init(i2c_bus_t* i2c_bus, int address, 130 enum i2c_slave_address_size address_size, 131 enum i2c_slave_speed max_speed, 132 uint32_t i2c_opts, 133 i2c_slave_t* i2c_slave) 134{ 135 ZF_LOGF_IF((!i2c_bus), "Handle to I2C controller not supplied!"); 136 ZF_LOGF_IF((!i2c_bus->slave_init), "Unimplemented!"); 137 138 switch (max_speed) { 139 case I2C_SLAVE_SPEED_STANDARD: 140 case I2C_SLAVE_SPEED_FAST: 141 case I2C_SLAVE_SPEED_FASTPLUS: 142 case I2C_SLAVE_SPEED_HIGHSPEED: 143 break; 144 default: 145 return -EINVAL; 146 } 147 148 if (address_size != I2C_SLAVE_ADDR_7BIT 149 && address_size != I2C_SLAVE_ADDR_10BIT) { 150 return -EINVAL; 151 } 152 153 if (!i2c_is_valid_address(i2c_extract_address(address))) { 154 return -ENODEV; 155 } 156 157 return i2c_bus->slave_init(i2c_bus, address, 158 address_size, max_speed, i2c_opts, i2c_slave); 159} 160 161int 162i2c_kvslave_init(i2c_slave_t* is, 163 enum kvfmt afmt, enum kvfmt dfmt, 164 i2c_kvslave_t* kvs) 165{ 166 ZF_LOGF_IF(!kvs, "Slave output handle not supplied!"); 167 ZF_LOGF_IF(!is, "Controller handle not supplied!"); 168 169 /* Validate address and data format arguments. */ 170 switch (afmt) { 171 case BIG64: 172 case BIG32: 173 case BIG16: 174 case BIG8: 175 case STREAM: 176 case LITTLE8: 177 case LITTLE16: 178 case LITTLE32: 179 case LITTLE64: 180 break; 181 default: 182 ZF_LOGE("Invalid address format %d.", afmt); 183 return -EINVAL; 184 } 185 186 switch (dfmt) { 187 case BIG64: 188 case BIG32: 189 case BIG16: 190 case BIG8: 191 case STREAM: 192 case LITTLE8: 193 case LITTLE16: 194 case LITTLE32: 195 case LITTLE64: 196 break; 197 default: 198 ZF_LOGE("Invalid data format %d.", dfmt); 199 return -EINVAL; 200 } 201 202 kvs->slave = is; 203 kvs->data_fmt = dfmt; 204 kvs->address_fmt = afmt; 205 return 0; 206} 207 208 209/* Loop until count registers have been read or an error occurs */ 210int 211i2c_kvslave_read(i2c_kvslave_t* kvs, uint64_t reg, void* vdata, int count) 212{ 213 assert(kvs != NULL); 214 215 int dbytes = ABS(kvs->data_fmt); 216 char* data = (char*)vdata; 217 int this = -1; 218 int remain = count; 219 220 if (kvs->slave == NULL) { 221 ZF_LOGE("KV Slave lib doesn't have underlying slave instance."); 222 return -ENODEV; 223 } 224 225 /* For large reads, copyin/out requires that they be split reads */ 226 while (remain > 0) { 227 this = _do_kvread(kvs, reg, data, remain); 228 if (this <= 0) { 229 break; 230 } 231 data += dbytes * this; 232 reg += dbytes * this; 233 remain -= this; 234 } 235 return count - remain; 236} 237 238 239/* Loop until count registers have been written or an error occurs */ 240int 241i2c_kvslave_write(i2c_kvslave_t* kvs, uint64_t reg, const void* vdata, int count) 242{ 243 assert(kvs != NULL); 244 245 int dbytes = ABS(kvs->data_fmt); 246 char* data = (char*)vdata; 247 int this = 0; 248 int remain = count; 249 250 if (kvs->slave == NULL) { 251 ZF_LOGE("KV Slave lib doesn't have underlying slave instance."); 252 return -ENODEV; 253 } 254 255 /* For large reads, copyin/out requires that they be split reads */ 256 while (remain > 0) { 257 this = _do_kvwrite(kvs, reg, data, remain); 258 if (this <= 0) { 259 break; 260 } 261 data += dbytes * this; 262 remain -= this; 263 reg += this; 264 } 265 return count - remain; 266} 267 268int 269i2c_scan(i2c_bus_t* i2c_bus, int start, int* addr, int naddr) 270{ 271 i2c_slave_t sl; 272 273 /* TODO: 274 * This should use the I2C Device-ID command. Currently it just attempts to 275 * read from each possible addressable ID on the bus. 276 * 277 * Ideally, it should still try each addressable ID in sequence, but it 278 * should first send out the Device-ID command, then follow it up with the 279 * current addressable ID, and repeat this in a loop. 280 * 281 * The Device-ID command was introduced in 2007, and is supported by devices 282 * that support the I2C protocol from version 3 upwards. 283 */ 284 int ret; 285 int i; 286 int count; 287 char dummy[10]; 288 for (count = 0, i = start & ~0x1; i < 0x100 && count < naddr; i += 2) { 289 /* Assume standard speed since we're just communicating with all the 290 * devices in sequence. 291 */ 292 memset(&sl, 0, sizeof(sl)); 293 ret = i2c_slave_init(i2c_bus, i, 294 I2C_SLAVE_ADDR_7BIT, I2C_SLAVE_SPEED_STANDARD, 295 0, &sl); 296 if (ret != 0) { 297 ZF_LOGW("Breaking out of scan early: failed to init slave " 298 "structure for slave %d.", i); 299 break; 300 } 301 302 ret = i2c_slave_read(&sl, &dummy, 10, false, NULL, NULL); 303 if (ret == 10) { 304 *addr++ = i; 305 count++; 306 } else if (ret < 0) { 307 } else { 308 ZF_LOGE("Invalid response"); 309 } 310 } 311 return count; 312} 313