1 /* This file contains device independent i2c device driver helpers. */ 2 3 #include <assert.h> 4 #include <minix/drivers.h> 5 #include <minix/endpoint.h> 6 #include <minix/i2c.h> 7 #include <minix/i2cdriver.h> 8 #include <minix/ipc.h> 9 #include <minix/ds.h> 10 11 void 12 i2cdriver_announce(uint32_t bus) 13 { 14 /* Announce we are up after a fresh start or restart. */ 15 int r; 16 char key[DS_MAX_KEYLEN]; 17 char label[DS_MAX_KEYLEN]; 18 const char *driver_prefix = "drv.i2c."; 19 20 /* Callers are allowed to use ipc_sendrec to communicate with drivers. 21 * For this reason, there may blocked callers when a driver restarts. 22 * Ask the kernel to unblock them (if any). 23 */ 24 if ((r = sys_statectl(SYS_STATE_CLEAR_IPC_REFS, 0, 0)) != OK) { 25 panic("chardriver_init: sys_statectl failed: %d", r); 26 } 27 28 /* Publish a driver up event. */ 29 r = ds_retrieve_label_name(label, sef_self()); 30 if (r != OK) { 31 panic("unable to get own label: %d\n", r); 32 } 33 /* example key: drv.i2c.1.cat24c245.0x50 */ 34 snprintf(key, DS_MAX_KEYLEN, "%s%d.%s", driver_prefix, bus, label); 35 r = ds_publish_u32(key, DS_DRIVER_UP, DSF_OVERWRITE); 36 if (r != OK) { 37 panic("unable to publish driver up event: %d\n", r); 38 } 39 } 40 41 int 42 i2cdriver_env_parse(uint32_t * bus, i2c_addr_t * address, 43 i2c_addr_t * valid_addrs) 44 { 45 /* fill in bus and address with the values passed on the command line */ 46 int r; 47 int found; 48 long int busl; 49 long int addressl; 50 51 r = env_parse("bus", "d", 0, &busl, 1, 3); 52 if (r != EP_SET) { 53 return -1; 54 } 55 *bus = (uint32_t) busl; 56 57 r = env_parse("address", "x", 0, &addressl, 0x0000, 0x03ff); 58 if (r != EP_SET) { 59 return -1; 60 } 61 *address = addressl; 62 63 found = 0; 64 while (*valid_addrs != 0x0000) { 65 66 if (*address == *valid_addrs) { 67 found = 1; 68 break; 69 } 70 71 valid_addrs++; 72 } 73 74 if (!found) { 75 return 1; 76 } 77 78 return 0; 79 } 80 81 endpoint_t 82 i2cdriver_bus_endpoint(uint32_t bus) 83 { 84 /* locate the driver for the i2c bus itself */ 85 int r; 86 const char *label_prefix = "i2c."; 87 char label[DS_MAX_KEYLEN]; 88 endpoint_t bus_endpoint; 89 90 snprintf(label, DS_MAX_KEYLEN, "%s%d", label_prefix, bus); 91 92 r = ds_retrieve_label_endpt(label, &bus_endpoint); 93 if (r != OK) { 94 return 0; 95 } 96 97 return bus_endpoint; 98 } 99 100 int 101 i2cdriver_subscribe_bus_updates(uint32_t bus) 102 { 103 int r; 104 char regex[DS_MAX_KEYLEN]; 105 106 /* only capture events for the specified bus */ 107 snprintf(regex, DS_MAX_KEYLEN, "drv\\.chr\\.i2c\\.%d", bus); 108 109 /* Subscribe to driver events from the i2c bus */ 110 r = ds_subscribe(regex, DSF_INITIAL | DSF_OVERWRITE); 111 if (r != OK) { 112 return r; 113 } 114 115 return OK; 116 } 117 118 void 119 i2cdriver_handle_bus_update(endpoint_t * bus_endpoint, uint32_t bus, 120 i2c_addr_t address) 121 { 122 char key[DS_MAX_KEYLEN]; 123 u32_t value; 124 int type; 125 endpoint_t owner_endpoint, old_endpoint; 126 int r; 127 128 /* check for pending events */ 129 while ((r = ds_check(key, &type, &owner_endpoint)) == OK) { 130 131 r = ds_retrieve_u32(key, &value); 132 if (r != OK) { 133 return; 134 } 135 136 if (value == DS_DRIVER_UP) { 137 old_endpoint = *bus_endpoint; 138 139 /* look up the bus's (potentially new) endpoint */ 140 *bus_endpoint = i2cdriver_bus_endpoint(bus); 141 142 /* was updated endpoint? */ 143 if (old_endpoint != *bus_endpoint) { 144 /* re-reserve device to allow the driver to 145 * continue working, even through a manual 146 * down/up. 147 */ 148 i2cdriver_reserve_device(*bus_endpoint, 149 address); 150 } 151 } 152 } 153 } 154 155 int 156 i2cdriver_reserve_device(endpoint_t bus_endpoint, i2c_addr_t address) 157 { 158 int r; 159 message m; 160 161 m.m_type = BUSC_I2C_RESERVE; 162 m.m_li2cdriver_i2c_busc_i2c_reserve.addr = address; 163 164 r = ipc_sendrec(bus_endpoint, &m); 165 if (r != OK) { 166 return EIO; 167 } 168 169 return m.m_type; /* return reply code OK, EBUSY, EINVAL, etc. */ 170 } 171 172 int 173 i2cdriver_exec(endpoint_t bus_endpoint, minix_i2c_ioctl_exec_t * ioctl_exec) 174 { 175 int r; 176 message m; 177 cp_grant_id_t grant_nr; 178 179 grant_nr = cpf_grant_direct(bus_endpoint, (vir_bytes) ioctl_exec, 180 sizeof(minix_i2c_ioctl_exec_t), CPF_READ | CPF_WRITE); 181 182 memset(&m, '\0', sizeof(message)); 183 184 m.m_type = BUSC_I2C_EXEC; 185 m.m_li2cdriver_i2c_busc_i2c_exec.grant = grant_nr; 186 187 r = ipc_sendrec(bus_endpoint, &m); 188 cpf_revoke(grant_nr); 189 if (r != OK) { 190 return EIO; 191 } 192 193 return m.m_type; 194 } 195 196 static int 197 __i2creg_read(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t raw, 198 uint8_t reg, uint32_t * val, size_t vallen) 199 { 200 uint32_t i; 201 int r; 202 minix_i2c_ioctl_exec_t ioctl_exec; 203 204 assert(val != NULL); 205 assert(vallen >= 1 && vallen <= 4); 206 207 memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); 208 209 /* Read from chip */ 210 ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; 211 ioctl_exec.iie_addr = address; 212 213 if (!raw) { 214 /* write the register address */ 215 ioctl_exec.iie_cmd[0] = reg; 216 ioctl_exec.iie_cmdlen = 1; 217 } 218 219 /* read vallen bytes */ 220 ioctl_exec.iie_buflen = vallen; 221 222 r = i2cdriver_exec(bus_endpoint, &ioctl_exec); 223 if (r != OK) { 224 return -1; 225 } 226 227 for (*val = 0, i = 0; i < vallen; i++) { 228 *val = ((*val) << 8) | ioctl_exec.iie_buf[i]; 229 } 230 231 return OK; 232 } 233 234 int 235 i2creg_raw_read8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t * val) 236 { 237 int r; 238 uint32_t val32; 239 240 r = __i2creg_read(bus_endpoint, address, 1, 0, &val32, 1); 241 *val = val32 & 0xff; 242 243 return r; 244 } 245 246 int 247 i2creg_read8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 248 uint8_t * val) 249 { 250 int r; 251 uint32_t val32; 252 253 r = __i2creg_read(bus_endpoint, address, 0, reg, &val32, 1); 254 *val = val32 & 0xff; 255 256 return r; 257 } 258 259 int 260 i2creg_read16(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 261 uint16_t * val) 262 { 263 int r; 264 uint32_t val32; 265 266 r = __i2creg_read(bus_endpoint, address, 0, reg, &val32, 2); 267 *val = val32 & 0xffff; 268 269 return r; 270 } 271 272 int 273 i2creg_read24(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 274 uint32_t * val) 275 { 276 return __i2creg_read(bus_endpoint, address, 0, reg, val, 3); 277 } 278 279 static int 280 __i2creg_write(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t raw, 281 uint8_t reg, uint8_t val) 282 { 283 int r; 284 minix_i2c_ioctl_exec_t ioctl_exec; 285 286 memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); 287 288 /* Write to chip */ 289 ioctl_exec.iie_op = I2C_OP_WRITE_WITH_STOP; 290 ioctl_exec.iie_addr = address; 291 292 if (raw) { 293 /* write just the value */ 294 ioctl_exec.iie_buf[0] = val; 295 ioctl_exec.iie_buflen = 1; 296 } else { 297 /* write the register address and value */ 298 ioctl_exec.iie_buf[0] = reg; 299 ioctl_exec.iie_buf[1] = val; 300 ioctl_exec.iie_buflen = 2; 301 } 302 303 r = i2cdriver_exec(bus_endpoint, &ioctl_exec); 304 if (r != OK) { 305 return -1; 306 } 307 308 return OK; 309 } 310 311 int 312 i2creg_write8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 313 uint8_t val) 314 { 315 return __i2creg_write(bus_endpoint, address, 0, reg, val); 316 } 317 318 int 319 i2creg_raw_write8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t val) 320 { 321 return __i2creg_write(bus_endpoint, address, 1, 0, val); 322 } 323 324 int 325 i2creg_set_bits8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 326 uint8_t bits) 327 { 328 int r; 329 uint8_t val; 330 331 r = i2creg_read8(bus_endpoint, address, reg, &val); 332 if (r != OK) { 333 return -1; 334 } 335 336 val |= bits; 337 338 r = i2creg_write8(bus_endpoint, address, reg, val); 339 if (r != OK) { 340 return -1; 341 } 342 343 return OK; 344 } 345 346 int 347 i2creg_clear_bits8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg, 348 uint8_t bits) 349 { 350 int r; 351 uint8_t val; 352 353 r = i2creg_read8(bus_endpoint, address, reg, &val); 354 if (r != OK) { 355 return -1; 356 } 357 358 val &= ~bits; 359 360 r = i2creg_write8(bus_endpoint, address, reg, val); 361 if (r != OK) { 362 return -1; 363 } 364 365 return OK; 366 } 367