1 /* $NetBSD: at24cxx.c,v 1.21 2015/12/13 17:15:06 jmcneill Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Steve C. Woodford and Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: at24cxx.c,v 1.21 2015/12/13 17:15:06 jmcneill Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/device.h> 44 #include <sys/kernel.h> 45 #include <sys/fcntl.h> 46 #include <sys/uio.h> 47 #include <sys/conf.h> 48 #include <sys/proc.h> 49 #include <sys/event.h> 50 51 #include <sys/bus.h> 52 53 #include <dev/i2c/i2cvar.h> 54 #include <dev/i2c/at24cxxvar.h> 55 56 /* 57 * AT24Cxx EEPROM I2C address: 58 * 101 0xxx 59 * (and others depending on the exact model) The bigger 8-bit parts 60 * decode multiple addresses. The bigger 16-bit parts do too (those 61 * larger than 512kb). Be sure to check the datasheet of your EEPROM 62 * because there's much variation between models. 63 */ 64 #define AT24CXX_ADDRMASK 0x3f8 65 #define AT24CXX_ADDR 0x50 66 67 #define AT24CXX_WRITE_CYCLE_MS 10 68 #define AT24CXX_ADDR_HI(a) (((a) >> 8) & 0x1f) 69 #define AT24CXX_ADDR_LO(a) ((a) & 0xff) 70 71 #include "seeprom.h" 72 73 #if NSEEPROM > 0 74 75 struct seeprom_softc { 76 device_t sc_dev; 77 i2c_tag_t sc_tag; 78 int sc_address; 79 int sc_size; 80 int sc_cmdlen; 81 int sc_open; 82 }; 83 84 static int seeprom_match(device_t, cfdata_t, void *); 85 static void seeprom_attach(device_t, device_t, void *); 86 87 CFATTACH_DECL_NEW(seeprom, sizeof(struct seeprom_softc), 88 seeprom_match, seeprom_attach, NULL, NULL); 89 extern struct cfdriver seeprom_cd; 90 91 dev_type_open(seeprom_open); 92 dev_type_close(seeprom_close); 93 dev_type_read(seeprom_read); 94 dev_type_write(seeprom_write); 95 96 const struct cdevsw seeprom_cdevsw = { 97 .d_open = seeprom_open, 98 .d_close = seeprom_close, 99 .d_read = seeprom_read, 100 .d_write = seeprom_write, 101 .d_ioctl = noioctl, 102 .d_stop = nostop, 103 .d_tty = notty, 104 .d_poll = nopoll, 105 .d_mmap = nommap, 106 .d_kqfilter = nokqfilter, 107 .d_discard = nodiscard, 108 .d_flag = D_OTHER 109 }; 110 111 static int seeprom_wait_idle(struct seeprom_softc *); 112 113 static const char * seeprom_compats[] = { 114 "i2c-at24c64", 115 "i2c-at34c02", 116 "atmel,24c02", 117 NULL 118 }; 119 120 static const struct seeprom_size { 121 const char *name; 122 int size; 123 } seeprom_sizes[] = { 124 { "atmel,24c02", 256 }, 125 }; 126 127 static int 128 seeprom_match(device_t parent, cfdata_t cf, void *aux) 129 { 130 struct i2c_attach_args *ia = aux; 131 132 if (ia->ia_name) { 133 if (ia->ia_ncompat > 0) { 134 if (iic_compat_match(ia, seeprom_compats)) 135 return (1); 136 } else { 137 if (strcmp(ia->ia_name, "seeprom") == 0) 138 return (1); 139 } 140 } else { 141 if ((ia->ia_addr & AT24CXX_ADDRMASK) == AT24CXX_ADDR) 142 return (1); 143 } 144 145 return (0); 146 } 147 148 static void 149 seeprom_attach(device_t parent, device_t self, void *aux) 150 { 151 struct seeprom_softc *sc = device_private(self); 152 struct i2c_attach_args *ia = aux; 153 u_int n; 154 155 sc->sc_tag = ia->ia_tag; 156 sc->sc_address = ia->ia_addr; 157 sc->sc_dev = self; 158 159 if (ia->ia_name != NULL) { 160 aprint_naive(": %s", ia->ia_name); 161 aprint_normal(": %s", ia->ia_name); 162 } else { 163 aprint_naive(": EEPROM"); 164 aprint_normal(": AT24Cxx or compatible EEPROM"); 165 } 166 167 /* 168 * The AT24C01A/02/04/08/16 EEPROMs use a 1 byte command 169 * word to select the offset into the EEPROM page. The 170 * AT24C04/08/16 decode fewer of the i2c address bits, 171 * using the bottom 1, 2, or 3 to select the 256-byte 172 * super-page. 173 * 174 * The AT24C32/64/128/256/512 EEPROMs use a 2 byte command 175 * word and decode all of the i2c address bits. 176 * 177 * The AT24C1024 EEPROMs use a 2 byte command and also do bank 178 * switching to select the proper super-page. This isn't 179 * supported by this driver. 180 */ 181 if (device_cfdata(self)->cf_flags) 182 sc->sc_size = (device_cfdata(self)->cf_flags << 7); 183 else 184 sc->sc_size = ia->ia_size; 185 186 if (sc->sc_size == 0 && ia->ia_ncompat > 0) { 187 for (n = 0; n < __arraycount(seeprom_sizes); n++) { 188 if (!strcmp(seeprom_sizes[n].name, ia->ia_compat[n])) { 189 sc->sc_size = seeprom_sizes[n].size; 190 break; 191 } 192 } 193 } 194 195 switch (sc->sc_size) { 196 case 128: /* 1Kbit */ 197 case 256: /* 2Kbit */ 198 case 512: /* 4Kbit */ 199 case 1024: /* 8Kbit */ 200 case 2048: /* 16Kbit */ 201 sc->sc_cmdlen = 1; 202 aprint_normal(": size %d\n", sc->sc_size); 203 break; 204 205 case 4096: /* 32Kbit */ 206 case 8192: /* 64Kbit */ 207 case 16384: /* 128Kbit */ 208 case 32768: /* 256Kbit */ 209 case 65536: /* 512Kbit */ 210 sc->sc_cmdlen = 2; 211 aprint_normal(": size %d\n", sc->sc_size); 212 break; 213 214 default: 215 /* 216 * Default to 2KB. If we happen to have a 2KB 217 * EEPROM this will allow us to access it. If we 218 * have a smaller one, the worst that can happen 219 * is that we end up trying to read a different 220 * EEPROM on the bus when accessing it. 221 * 222 * Obviously this will not work for 4KB or 8KB 223 * EEPROMs, but them's the breaks. 224 */ 225 aprint_normal("\n"); 226 aprint_error_dev(self, "invalid size specified; " 227 "assuming 2KB (16Kb)\n"); 228 sc->sc_size = 2048; 229 sc->sc_cmdlen = 1; 230 } 231 232 sc->sc_open = 0; 233 } 234 235 /*ARGSUSED*/ 236 int 237 seeprom_open(dev_t dev, int flag, int fmt, struct lwp *l) 238 { 239 struct seeprom_softc *sc; 240 241 if ((sc = device_lookup_private(&seeprom_cd, minor(dev))) == NULL) 242 return (ENXIO); 243 244 /* XXX: Locking */ 245 246 if (sc->sc_open) 247 return (EBUSY); 248 249 sc->sc_open = 1; 250 return (0); 251 } 252 253 /*ARGSUSED*/ 254 int 255 seeprom_close(dev_t dev, int flag, int fmt, struct lwp *l) 256 { 257 struct seeprom_softc *sc; 258 259 if ((sc = device_lookup_private(&seeprom_cd, minor(dev))) == NULL) 260 return (ENXIO); 261 262 sc->sc_open = 0; 263 return (0); 264 } 265 266 /*ARGSUSED*/ 267 int 268 seeprom_read(dev_t dev, struct uio *uio, int flags) 269 { 270 struct seeprom_softc *sc; 271 i2c_addr_t addr; 272 u_int8_t ch, cmdbuf[2]; 273 int a, error; 274 275 if ((sc = device_lookup_private(&seeprom_cd, minor(dev))) == NULL) 276 return (ENXIO); 277 278 if (uio->uio_offset >= sc->sc_size) 279 return (EINVAL); 280 281 /* 282 * Even though the AT24Cxx EEPROMs support sequential 283 * reads within a page, some I2C controllers do not 284 * support anything other than single-byte transfers, 285 * so we're stuck with this lowest-common-denominator. 286 */ 287 288 while (uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) { 289 a = (int)uio->uio_offset; 290 if (sc->sc_cmdlen == 1) { 291 addr = sc->sc_address + (a >> 8); 292 cmdbuf[0] = a & 0xff; 293 } else { 294 addr = sc->sc_address; 295 cmdbuf[0] = AT24CXX_ADDR_HI(a); 296 cmdbuf[1] = AT24CXX_ADDR_LO(a); 297 } 298 299 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) 300 return (error); 301 if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 302 addr, cmdbuf, sc->sc_cmdlen, 303 &ch, 1, 0)) != 0) { 304 iic_release_bus(sc->sc_tag, 0); 305 aprint_error_dev(sc->sc_dev, 306 "seeprom_read: byte read failed at 0x%x\n", a); 307 return (error); 308 } 309 iic_release_bus(sc->sc_tag, 0); 310 311 if ((error = uiomove(&ch, 1, uio)) != 0) { 312 return (error); 313 } 314 } 315 316 return (0); 317 } 318 319 /*ARGSUSED*/ 320 int 321 seeprom_write(dev_t dev, struct uio *uio, int flags) 322 { 323 struct seeprom_softc *sc; 324 i2c_addr_t addr; 325 u_int8_t ch, cmdbuf[2]; 326 int a, error; 327 328 if ((sc = device_lookup_private(&seeprom_cd, minor(dev))) == NULL) 329 return (ENXIO); 330 331 if (uio->uio_offset >= sc->sc_size) 332 return (EINVAL); 333 334 /* 335 * See seeprom_read() for why we don't use sequential 336 * writes within a page. 337 */ 338 339 while (uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) { 340 a = (int)uio->uio_offset; 341 if (sc->sc_cmdlen == 1) { 342 addr = sc->sc_address + (a >> 8); 343 cmdbuf[0] = a & 0xff; 344 } else { 345 addr = sc->sc_address; 346 cmdbuf[0] = AT24CXX_ADDR_HI(a); 347 cmdbuf[1] = AT24CXX_ADDR_LO(a); 348 } 349 if ((error = uiomove(&ch, 1, uio)) != 0) { 350 iic_release_bus(sc->sc_tag, 0); 351 return (error); 352 } 353 354 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) 355 return (error); 356 if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 357 addr, cmdbuf, sc->sc_cmdlen, 358 &ch, 1, 0)) != 0) { 359 iic_release_bus(sc->sc_tag, 0); 360 aprint_error_dev(sc->sc_dev, 361 "seeprom_write: byte write failed at 0x%x\n", a); 362 return (error); 363 } 364 iic_release_bus(sc->sc_tag, 0); 365 366 /* Wait until the device commits the byte. */ 367 if ((error = seeprom_wait_idle(sc)) != 0) { 368 return (error); 369 } 370 } 371 372 return (0); 373 } 374 375 static int 376 seeprom_wait_idle(struct seeprom_softc *sc) 377 { 378 uint8_t cmdbuf[2] = { 0, 0 }; 379 int rv, timeout; 380 u_int8_t dummy; 381 int error; 382 383 timeout = (1000 / hz) / AT24CXX_WRITE_CYCLE_MS; 384 if (timeout == 0) 385 timeout = 1; 386 387 delay(10); 388 389 /* 390 * Read the byte at address 0. This is just a dummy 391 * read to wait for the EEPROM's write cycle to complete. 392 */ 393 for (;;) { 394 if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0) 395 return error; 396 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 397 sc->sc_address, cmdbuf, sc->sc_cmdlen, &dummy, 1, 0); 398 iic_release_bus(sc->sc_tag, 0); 399 if (error == 0) 400 break; 401 402 rv = tsleep(sc, PRIBIO | PCATCH, "seepromwr", timeout); 403 if (rv != EWOULDBLOCK) 404 return (rv); 405 } 406 407 return (0); 408 } 409 410 #endif /* NSEEPROM > 0 */ 411 412 int 413 seeprom_bootstrap_read(i2c_tag_t tag, int i2caddr, int offset, int devsize, 414 u_int8_t *rvp, size_t len) 415 { 416 i2c_addr_t addr; 417 int cmdlen; 418 uint8_t cmdbuf[2]; 419 420 if (len == 0) 421 return (0); 422 423 /* We are very forgiving about devsize during bootstrap. */ 424 cmdlen = (devsize >= 4096) ? 2 : 1; 425 426 if (iic_acquire_bus(tag, I2C_F_POLL) != 0) 427 return (-1); 428 429 while (len) { 430 if (cmdlen == 1) { 431 addr = i2caddr + (offset >> 8); 432 cmdbuf[0] = offset & 0xff; 433 } else { 434 addr = i2caddr; 435 cmdbuf[0] = AT24CXX_ADDR_HI(offset); 436 cmdbuf[1] = AT24CXX_ADDR_LO(offset); 437 } 438 439 /* Read a single byte. */ 440 if (iic_exec(tag, I2C_OP_READ_WITH_STOP, addr, 441 cmdbuf, cmdlen, rvp, 1, I2C_F_POLL)) { 442 iic_release_bus(tag, I2C_F_POLL); 443 return (-1); 444 } 445 446 len--; 447 rvp++; 448 offset++; 449 } 450 451 iic_release_bus(tag, I2C_F_POLL); 452 return (0); 453 } 454