1 /* $NetBSD: nfsmb.c,v 1.21 2010/05/08 07:41:44 pgoyette Exp $ */ 2 /* 3 * Copyright (c) 2007 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: nfsmb.c,v 1.21 2010/05/08 07:41:44 pgoyette Exp $"); 30 31 #include <sys/param.h> 32 #include <sys/device.h> 33 #include <sys/errno.h> 34 #include <sys/kernel.h> 35 #include <sys/rwlock.h> 36 #include <sys/proc.h> 37 38 #include <sys/bus.h> 39 40 #include <dev/i2c/i2cvar.h> 41 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcireg.h> 44 #include <dev/pci/pcidevs.h> 45 46 #include <dev/pci/nfsmbreg.h> 47 48 49 struct nfsmbc_attach_args { 50 int nfsmb_num; 51 bus_space_tag_t nfsmb_iot; 52 int nfsmb_addr; 53 }; 54 55 struct nfsmb_softc; 56 struct nfsmbc_softc { 57 device_t sc_dev; 58 59 pci_chipset_tag_t sc_pc; 60 pcitag_t sc_tag; 61 struct pci_attach_args *sc_pa; 62 63 bus_space_tag_t sc_iot; 64 device_t sc_nfsmb[2]; 65 }; 66 67 struct nfsmb_softc { 68 device_t sc_dev; 69 int sc_num; 70 device_t sc_nfsmbc; 71 72 bus_space_tag_t sc_iot; 73 bus_space_handle_t sc_ioh; 74 75 struct i2c_controller sc_i2c; /* i2c controller info */ 76 krwlock_t sc_rwlock; 77 }; 78 79 80 static int nfsmbc_match(device_t, cfdata_t, void *); 81 static void nfsmbc_attach(device_t, device_t, void *); 82 static int nfsmbc_print(void *, const char *); 83 84 static int nfsmb_match(device_t, cfdata_t, void *); 85 static void nfsmb_attach(device_t, device_t, void *); 86 static int nfsmb_acquire_bus(void *, int); 87 static void nfsmb_release_bus(void *, int); 88 static int nfsmb_exec( 89 void *, i2c_op_t, i2c_addr_t, const void *, size_t, void *, size_t, int); 90 static int nfsmb_check_done(struct nfsmb_softc *); 91 static int 92 nfsmb_send_1(struct nfsmb_softc *, uint8_t, i2c_addr_t, i2c_op_t, int); 93 static int nfsmb_write_1( 94 struct nfsmb_softc *, uint8_t, uint8_t, i2c_addr_t, i2c_op_t, int); 95 static int nfsmb_write_2( 96 struct nfsmb_softc *, uint8_t, uint16_t, i2c_addr_t, i2c_op_t, int); 97 static int nfsmb_receive_1(struct nfsmb_softc *, i2c_addr_t, i2c_op_t, int); 98 static int 99 nfsmb_read_1(struct nfsmb_softc *, uint8_t, i2c_addr_t, i2c_op_t, int); 100 static int 101 nfsmb_read_2(struct nfsmb_softc *, uint8_t, i2c_addr_t, i2c_op_t, int); 102 static int 103 nfsmb_quick(struct nfsmb_softc *, i2c_addr_t, i2c_op_t, int); 104 105 CFATTACH_DECL_NEW(nfsmbc, sizeof(struct nfsmbc_softc), 106 nfsmbc_match, nfsmbc_attach, NULL, NULL); 107 108 static int 109 nfsmbc_match(device_t parent, cfdata_t match, void *aux) 110 { 111 struct pci_attach_args *pa = aux; 112 113 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) { 114 switch (PCI_PRODUCT(pa->pa_id)) { 115 case PCI_PRODUCT_NVIDIA_NFORCE2_SMBUS: 116 case PCI_PRODUCT_NVIDIA_NFORCE2_400_SMBUS: 117 case PCI_PRODUCT_NVIDIA_NFORCE3_SMBUS: 118 case PCI_PRODUCT_NVIDIA_NFORCE3_250_SMBUS: 119 case PCI_PRODUCT_NVIDIA_NFORCE4_SMBUS: 120 case PCI_PRODUCT_NVIDIA_NFORCE430_SMBUS: 121 case PCI_PRODUCT_NVIDIA_MCP04_SMBUS: 122 case PCI_PRODUCT_NVIDIA_MCP55_SMB: 123 case PCI_PRODUCT_NVIDIA_MCP61_SMB: 124 case PCI_PRODUCT_NVIDIA_MCP65_SMB: 125 case PCI_PRODUCT_NVIDIA_MCP67_SMB: 126 case PCI_PRODUCT_NVIDIA_MCP73_SMB: 127 case PCI_PRODUCT_NVIDIA_MCP78S_SMB: 128 case PCI_PRODUCT_NVIDIA_MCP79_SMB: 129 return 1; 130 } 131 } 132 133 return 0; 134 } 135 136 static void 137 nfsmbc_attach(device_t parent, device_t self, void *aux) 138 { 139 struct nfsmbc_softc *sc = device_private(self); 140 struct pci_attach_args *pa = aux; 141 struct nfsmbc_attach_args nfsmbca; 142 pcireg_t reg; 143 int baseregs[2]; 144 char devinfo[256]; 145 146 aprint_naive("\n"); 147 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 148 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, 149 PCI_REVISION(pa->pa_class)); 150 151 sc->sc_dev = self; 152 sc->sc_pc = pa->pa_pc; 153 sc->sc_tag = pa->pa_tag; 154 sc->sc_pa = pa; 155 sc->sc_iot = pa->pa_iot; 156 157 nfsmbca.nfsmb_iot = sc->sc_iot; 158 159 switch (PCI_PRODUCT(pa->pa_id)) { 160 case PCI_PRODUCT_NVIDIA_NFORCE2_SMBUS: 161 case PCI_PRODUCT_NVIDIA_NFORCE2_400_SMBUS: 162 case PCI_PRODUCT_NVIDIA_NFORCE3_SMBUS: 163 case PCI_PRODUCT_NVIDIA_NFORCE3_250_SMBUS: 164 case PCI_PRODUCT_NVIDIA_NFORCE4_SMBUS: 165 baseregs[0] = NFORCE_OLD_SMB1; 166 baseregs[1] = NFORCE_OLD_SMB2; 167 break; 168 default: 169 baseregs[0] = NFORCE_SMB1; 170 baseregs[1] = NFORCE_SMB2; 171 break; 172 } 173 174 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, baseregs[0]); 175 nfsmbca.nfsmb_num = 1; 176 nfsmbca.nfsmb_addr = NFORCE_SMBBASE(reg); 177 sc->sc_nfsmb[0] = config_found(sc->sc_dev, &nfsmbca, nfsmbc_print); 178 179 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, baseregs[1]); 180 nfsmbca.nfsmb_num = 2; 181 nfsmbca.nfsmb_addr = NFORCE_SMBBASE(reg); 182 sc->sc_nfsmb[1] = config_found(sc->sc_dev, &nfsmbca, nfsmbc_print); 183 184 /* This driver is similar to an ISA bridge that doesn't 185 * need any special handling. So registering NULL handlers 186 * are sufficent. */ 187 if (!pmf_device_register(self, NULL, NULL)) 188 aprint_error_dev(self, "couldn't establish power handler\n"); 189 } 190 191 static int 192 nfsmbc_print(void *aux, const char *pnp) 193 { 194 struct nfsmbc_attach_args *nfsmbcap = aux; 195 196 if (pnp) 197 aprint_normal("nfsmb SMBus %d at %s", 198 nfsmbcap->nfsmb_num, pnp); 199 else 200 aprint_normal(" SMBus %d", nfsmbcap->nfsmb_num); 201 return UNCONF; 202 } 203 204 205 CFATTACH_DECL_NEW(nfsmb, sizeof(struct nfsmb_softc), 206 nfsmb_match, nfsmb_attach, NULL, NULL); 207 208 static int 209 nfsmb_match(device_t parent, cfdata_t match, void *aux) 210 { 211 struct nfsmbc_attach_args *nfsmbcap = aux; 212 213 if (nfsmbcap->nfsmb_num == 1 || nfsmbcap->nfsmb_num == 2) 214 return 1; 215 return 0; 216 } 217 218 static void 219 nfsmb_attach(device_t parent, device_t self, void *aux) 220 { 221 struct nfsmb_softc *sc = device_private(self); 222 struct nfsmbc_attach_args *nfsmbcap = aux; 223 struct i2cbus_attach_args iba; 224 225 aprint_naive("\n"); 226 aprint_normal("\n"); 227 228 sc->sc_dev = self; 229 sc->sc_nfsmbc = parent; 230 sc->sc_num = nfsmbcap->nfsmb_num; 231 sc->sc_iot = nfsmbcap->nfsmb_iot; 232 233 /* register with iic */ 234 sc->sc_i2c.ic_cookie = sc; 235 sc->sc_i2c.ic_acquire_bus = nfsmb_acquire_bus; 236 sc->sc_i2c.ic_release_bus = nfsmb_release_bus; 237 sc->sc_i2c.ic_send_start = NULL; 238 sc->sc_i2c.ic_send_stop = NULL; 239 sc->sc_i2c.ic_initiate_xfer = NULL; 240 sc->sc_i2c.ic_read_byte = NULL; 241 sc->sc_i2c.ic_write_byte = NULL; 242 sc->sc_i2c.ic_exec = nfsmb_exec; 243 244 rw_init(&sc->sc_rwlock); 245 246 if (bus_space_map(sc->sc_iot, nfsmbcap->nfsmb_addr, NFORCE_SMBSIZE, 0, 247 &sc->sc_ioh) != 0) { 248 aprint_error_dev(self, "failed to map SMBus space\n"); 249 return; 250 } 251 252 iba.iba_type = I2C_TYPE_SMBUS; 253 iba.iba_tag = &sc->sc_i2c; 254 (void) config_found_ia(sc->sc_dev, "i2cbus", &iba, iicbus_print); 255 256 /* This driver is similar to an ISA bridge that doesn't 257 * need any special handling. So registering NULL handlers 258 * are sufficent. */ 259 if (!pmf_device_register(self, NULL, NULL)) 260 aprint_error_dev(self, "couldn't establish power handler\n"); 261 } 262 263 static int 264 nfsmb_acquire_bus(void *cookie, int flags) 265 { 266 struct nfsmb_softc *sc = cookie; 267 268 rw_enter(&sc->sc_rwlock, RW_WRITER); 269 return 0; 270 } 271 272 static void 273 nfsmb_release_bus(void *cookie, int flags) 274 { 275 struct nfsmb_softc *sc = cookie; 276 277 rw_exit(&sc->sc_rwlock); 278 } 279 280 static int 281 nfsmb_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, 282 size_t cmdlen, void *vbuf, size_t buflen, int flags) 283 { 284 struct nfsmb_softc *sc = (struct nfsmb_softc *)cookie; 285 uint8_t *p = vbuf; 286 int rv; 287 288 if ((cmdlen == 0) && (buflen == 0)) { 289 return nfsmb_quick(sc, addr, op, flags); 290 } 291 292 if (I2C_OP_READ_P(op) && (cmdlen == 0) && (buflen == 1)) { 293 rv = nfsmb_receive_1(sc, addr, op, flags); 294 if (rv == -1) 295 return -1; 296 *p = (uint8_t)rv; 297 return 0; 298 } 299 300 if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) { 301 rv = nfsmb_read_1(sc, *(const uint8_t*)cmd, addr, op, flags); 302 if (rv == -1) 303 return -1; 304 *p = (uint8_t)rv; 305 return 0; 306 } 307 308 if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 2)) { 309 rv = nfsmb_read_2(sc, *(const uint8_t*)cmd, addr, op, flags); 310 if (rv == -1) 311 return -1; 312 *(uint16_t *)p = (uint16_t)rv; 313 return 0; 314 } 315 316 if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) 317 return nfsmb_send_1(sc, *(uint8_t*)vbuf, addr, op, flags); 318 319 if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) 320 return nfsmb_write_1(sc, *(const uint8_t*)cmd, *(uint8_t*)vbuf, 321 addr, op, flags); 322 323 if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 2)) 324 return nfsmb_write_2(sc, 325 *(const uint8_t*)cmd, *((uint16_t *)vbuf), addr, op, flags); 326 327 return -1; 328 } 329 330 static int 331 nfsmb_check_done(struct nfsmb_softc *sc) 332 { 333 int us; 334 uint8_t stat; 335 336 us = 10 * 1000; /* XXXX: wait maximum 10 msec */ 337 do { 338 delay(10); 339 us -= 10; 340 if (us <= 0) 341 return -1; 342 } while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, 343 NFORCE_SMB_PROTOCOL) != 0); 344 345 stat = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_STATUS); 346 if ((stat & NFORCE_SMB_STATUS_DONE) && 347 !(stat & NFORCE_SMB_STATUS_STATUS)) 348 return 0; 349 return -1; 350 } 351 352 /* ARGSUSED */ 353 static int 354 nfsmb_quick(struct nfsmb_softc *sc, i2c_addr_t addr, i2c_op_t op, int flags) 355 { 356 uint8_t data; 357 358 /* write smbus slave address to register */ 359 data = addr << 1; 360 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 361 362 /* write smbus protocol to register */ 363 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_QUICK; 364 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 365 366 return nfsmb_check_done(sc); 367 } 368 369 /* ARGSUSED */ 370 static int 371 nfsmb_send_1(struct nfsmb_softc *sc, uint8_t val, i2c_addr_t addr, i2c_op_t op, 372 int flags) 373 { 374 uint8_t data; 375 376 /* store cmd */ 377 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_COMMAND, val); 378 379 /* write smbus slave address to register */ 380 data = addr << 1; 381 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 382 383 /* write smbus protocol to register */ 384 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_BYTE; 385 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 386 387 return nfsmb_check_done(sc); 388 } 389 390 /* ARGSUSED */ 391 static int 392 nfsmb_write_1(struct nfsmb_softc *sc, uint8_t cmd, uint8_t val, i2c_addr_t addr, 393 i2c_op_t op, int flags) 394 { 395 uint8_t data; 396 397 /* store cmd */ 398 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_COMMAND, cmd); 399 400 /* store data */ 401 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA, val); 402 403 /* write smbus slave address to register */ 404 data = addr << 1; 405 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 406 407 /* write smbus protocol to register */ 408 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_BYTE_DATA; 409 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 410 411 return nfsmb_check_done(sc); 412 } 413 414 static int 415 nfsmb_write_2(struct nfsmb_softc *sc, uint8_t cmd, uint16_t val, 416 i2c_addr_t addr, i2c_op_t op, int flags) 417 { 418 uint8_t data, low, high; 419 420 /* store cmd */ 421 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_COMMAND, cmd); 422 423 /* store data */ 424 low = val; 425 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA, low); 426 high = val >> 8; 427 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA + 1, high); 428 429 /* write smbus slave address to register */ 430 data = addr << 1; 431 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 432 433 /* write smbus protocol to register */ 434 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_WORD_DATA; 435 if (flags & I2C_F_PEC) 436 data |= NFORCE_SMB_PROTOCOL_PEC; 437 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 438 439 return nfsmb_check_done(sc); 440 } 441 442 /* ARGSUSED */ 443 static int 444 nfsmb_receive_1(struct nfsmb_softc *sc, i2c_addr_t addr, i2c_op_t op, int flags) 445 { 446 uint8_t data; 447 448 /* write smbus slave address to register */ 449 data = addr << 1; 450 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 451 452 /* write smbus protocol to register */ 453 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_BYTE; 454 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 455 456 /* check for errors */ 457 if (nfsmb_check_done(sc) < 0) 458 return -1; 459 460 /* read data */ 461 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA); 462 } 463 464 /* ARGSUSED */ 465 static int 466 nfsmb_read_1(struct nfsmb_softc *sc, uint8_t cmd, i2c_addr_t addr, i2c_op_t op, 467 int flags) 468 { 469 uint8_t data; 470 471 /* store cmd */ 472 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_COMMAND, cmd); 473 474 /* write smbus slave address to register */ 475 data = addr << 1; 476 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 477 478 /* write smbus protocol to register */ 479 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_BYTE_DATA; 480 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 481 482 /* check for errors */ 483 if (nfsmb_check_done(sc) < 0) 484 return -1; 485 486 /* read data */ 487 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA); 488 } 489 490 static int 491 nfsmb_read_2(struct nfsmb_softc *sc, uint8_t cmd, i2c_addr_t addr, i2c_op_t op, 492 int flags) 493 { 494 uint8_t data, low, high; 495 496 /* store cmd */ 497 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_COMMAND, cmd); 498 499 /* write smbus slave address to register */ 500 data = addr << 1; 501 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_ADDRESS, data); 502 503 /* write smbus protocol to register */ 504 data = I2C_OP_READ_P(op) | NFORCE_SMB_PROTOCOL_WORD_DATA; 505 if (flags & I2C_F_PEC) 506 data |= NFORCE_SMB_PROTOCOL_PEC; 507 bus_space_write_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_PROTOCOL, data); 508 509 /* check for errors */ 510 if (nfsmb_check_done(sc) < 0) 511 return -1; 512 513 /* read data */ 514 low = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA); 515 high = bus_space_read_1(sc->sc_iot, sc->sc_ioh, NFORCE_SMB_DATA + 1); 516 return low | high << 8; 517 } 518