1 1.7 thorpej /* $NetBSD: imcsmb.c,v 1.7 2025/09/15 13:23:02 thorpej Exp $ */ 2 1.1 pgoyette 3 1.1 pgoyette /*- 4 1.1 pgoyette * Copyright (c) 2018 The NetBSD Foundation, Inc. 5 1.1 pgoyette * All rights reserved. 6 1.1 pgoyette * 7 1.1 pgoyette * This code is derived from software contributed to The NetBSD Foundation 8 1.1 pgoyette * by Paul Goyette 9 1.1 pgoyette * 10 1.1 pgoyette * Redistribution and use in source and binary forms, with or without 11 1.1 pgoyette * modification, are permitted provided that the following conditions 12 1.1 pgoyette * are met: 13 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright 14 1.1 pgoyette * notice, this list of conditions and the following disclaimer. 15 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the 17 1.1 pgoyette * documentation and/or other materials provided with the distribution. 18 1.1 pgoyette * 19 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 pgoyette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 pgoyette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 pgoyette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 pgoyette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 pgoyette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 pgoyette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 pgoyette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 pgoyette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 pgoyette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 pgoyette * POSSIBILITY OF SUCH DAMAGE. 30 1.1 pgoyette */ 31 1.1 pgoyette 32 1.1 pgoyette /*- 33 1.1 pgoyette * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34 1.1 pgoyette * 35 1.1 pgoyette * Authors: Joe Kloss; Ravi Pokala (rpokala (at) freebsd.org) 36 1.1 pgoyette * 37 1.1 pgoyette * Copyright (c) 2017-2018 Panasas 38 1.1 pgoyette * All rights reserved. 39 1.1 pgoyette * 40 1.1 pgoyette * Redistribution and use in source and binary forms, with or without 41 1.1 pgoyette * modification, are permitted provided that the following conditions 42 1.1 pgoyette * are met: 43 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright 44 1.1 pgoyette * notice, this list of conditions and the following disclaimer. 45 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright 46 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the 47 1.1 pgoyette * documentation and/or other materials provided with the distribution. 48 1.1 pgoyette * 49 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 50 1.1 pgoyette * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 1.1 pgoyette * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 1.1 pgoyette * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 53 1.1 pgoyette * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 1.1 pgoyette * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 1.1 pgoyette * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 1.1 pgoyette * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 1.1 pgoyette * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 1.1 pgoyette * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 1.1 pgoyette * SUCH DAMAGE. 60 1.1 pgoyette */ 61 1.1 pgoyette 62 1.1 pgoyette /* 63 1.1 pgoyette * Driver for the SMBus controllers in Intel's Integrated Memory Controllers 64 1.1 pgoyette * in certain CPUs. A more detailed description of this device is present 65 1.1 pgoyette * in imc.c 66 1.1 pgoyette */ 67 1.1 pgoyette 68 1.1 pgoyette #include <sys/cdefs.h> 69 1.7 thorpej __KERNEL_RCSID(0, "$NetBSD: imcsmb.c,v 1.7 2025/09/15 13:23:02 thorpej Exp $"); 70 1.1 pgoyette 71 1.1 pgoyette #include <sys/param.h> 72 1.1 pgoyette #include <sys/kernel.h> 73 1.1 pgoyette #include <sys/module.h> 74 1.1 pgoyette #include <sys/endian.h> 75 1.1 pgoyette #include <sys/errno.h> 76 1.1 pgoyette #include <sys/mutex.h> 77 1.1 pgoyette #include <sys/bus.h> 78 1.1 pgoyette 79 1.1 pgoyette #include <dev/pci/pcidevs.h> 80 1.1 pgoyette #include <dev/pci/pcivar.h> 81 1.1 pgoyette #include <dev/pci/pcireg.h> 82 1.1 pgoyette 83 1.1 pgoyette #include <dev/i2c/i2cvar.h> 84 1.1 pgoyette 85 1.1 pgoyette #include "imcsmb_reg.h" 86 1.1 pgoyette #include "imcsmb_var.h" 87 1.1 pgoyette 88 1.1 pgoyette /* Device methods */ 89 1.1 pgoyette static int imcsmb_probe(device_t, cfdata_t, void *); 90 1.1 pgoyette static void imcsmb_attach(device_t, device_t, void *); 91 1.1 pgoyette static int imcsmb_detach(device_t, int flags); 92 1.1 pgoyette static int imcsmb_rescan(device_t, const char *, const int *); 93 1.1 pgoyette static void imcsmb_chdet(device_t, device_t); 94 1.1 pgoyette 95 1.1 pgoyette CFATTACH_DECL3_NEW(imcsmb, sizeof(struct imcsmb_softc), 96 1.1 pgoyette imcsmb_probe, imcsmb_attach, imcsmb_detach, NULL, imcsmb_rescan, 97 1.1 pgoyette imcsmb_chdet, 0); 98 1.1 pgoyette 99 1.1 pgoyette /* Bus access control methods */ 100 1.1 pgoyette static int imcsmb_acquire_bus(void *cookie, int flags); 101 1.1 pgoyette static void imcsmb_release_bus(void *cookie, int flags); 102 1.1 pgoyette 103 1.1 pgoyette /* SMBus methods */ 104 1.1 pgoyette static int imcsmb_exec(void *cookie, i2c_op_t, i2c_addr_t, const void *, 105 1.1 pgoyette size_t, void *, size_t, int); 106 1.1 pgoyette 107 1.1 pgoyette /** 108 1.1 pgoyette * device_attach() method. Set up the softc, including getting the set of the 109 1.1 pgoyette * parent imcsmb_pci's registers that we will use. Create the smbus(4) device, 110 1.1 pgoyette * which any SMBus slave device drivers will connect to. Probe and attach 111 1.1 pgoyette * anything which might be downstream. 112 1.1 pgoyette * 113 1.1 pgoyette * @author rpokala 114 1.1 pgoyette * 115 1.1 pgoyette * @param[in,out] dev 116 1.1 pgoyette * Device being attached. 117 1.1 pgoyette */ 118 1.1 pgoyette 119 1.1 pgoyette static void 120 1.1 pgoyette imcsmb_attach(device_t parent, device_t self, void *aux) 121 1.1 pgoyette { 122 1.1 pgoyette struct imcsmb_softc *sc = device_private(self); 123 1.1 pgoyette struct imc_attach_args *imca = aux; 124 1.1 pgoyette 125 1.1 pgoyette aprint_naive("\n"); 126 1.2 pgoyette aprint_normal(": SMBus controller\n"); 127 1.1 pgoyette 128 1.1 pgoyette /* Initialize private state */ 129 1.1 pgoyette sc->sc_dev = self; 130 1.1 pgoyette sc->sc_regs = imca->ia_regs; 131 1.1 pgoyette sc->sc_pci_tag = imca->ia_pci_tag; 132 1.1 pgoyette sc->sc_pci_chipset_tag = imca->ia_pci_chipset_tag; 133 1.1 pgoyette 134 1.1 pgoyette if (!pmf_device_register(self, NULL, NULL)) 135 1.1 pgoyette aprint_error_dev(self, "couldn't establish power handler\n"); 136 1.1 pgoyette 137 1.4 thorpej imcsmb_rescan(self, NULL, NULL); 138 1.1 pgoyette } 139 1.1 pgoyette 140 1.1 pgoyette static int 141 1.4 thorpej imcsmb_rescan(device_t self, const char *ifattr, const int *locs) 142 1.1 pgoyette { 143 1.1 pgoyette struct imcsmb_softc *sc = device_private(self); 144 1.1 pgoyette 145 1.1 pgoyette /* Create the i2cbus child */ 146 1.1 pgoyette if (sc->sc_smbus != NULL) 147 1.1 pgoyette return 0; 148 1.1 pgoyette 149 1.3 thorpej iic_tag_init(&sc->sc_i2c_tag); 150 1.1 pgoyette sc->sc_i2c_tag.ic_cookie = sc; 151 1.1 pgoyette sc->sc_i2c_tag.ic_acquire_bus = imcsmb_acquire_bus; 152 1.1 pgoyette sc->sc_i2c_tag.ic_release_bus = imcsmb_release_bus; 153 1.1 pgoyette sc->sc_i2c_tag.ic_exec = imcsmb_exec; 154 1.1 pgoyette 155 1.7 thorpej sc->sc_smbus = iicbus_attach(self, &sc->sc_i2c_tag); 156 1.1 pgoyette 157 1.1 pgoyette if (sc->sc_smbus == NULL) { 158 1.1 pgoyette aprint_normal_dev(self, "no child found\n"); 159 1.1 pgoyette return ENXIO; 160 1.1 pgoyette } 161 1.1 pgoyette 162 1.1 pgoyette return 0; 163 1.1 pgoyette } 164 1.1 pgoyette 165 1.1 pgoyette static void 166 1.1 pgoyette imcsmb_chdet(device_t self, device_t child) 167 1.1 pgoyette { 168 1.1 pgoyette struct imcsmb_softc *sc = device_private(self); 169 1.1 pgoyette 170 1.1 pgoyette if (child == sc->sc_smbus) 171 1.1 pgoyette sc->sc_smbus = NULL; 172 1.1 pgoyette else KASSERT(child == NULL); 173 1.1 pgoyette } 174 1.1 pgoyette 175 1.1 pgoyette /** 176 1.1 pgoyette * device_detach() method. attach() didn't do any allocations, so there's 177 1.1 pgoyette * nothing special needed 178 1.1 pgoyette */ 179 1.1 pgoyette static int 180 1.1 pgoyette imcsmb_detach(device_t self, int flags) 181 1.1 pgoyette { 182 1.6 riastrad struct imcsmb_softc *sc = device_private(self); 183 1.1 pgoyette int error; 184 1.1 pgoyette 185 1.6 riastrad error = config_detach_children(self, flags); 186 1.6 riastrad if (error) 187 1.6 riastrad return error; 188 1.1 pgoyette 189 1.1 pgoyette pmf_device_deregister(self); 190 1.3 thorpej iic_tag_fini(&sc->sc_i2c_tag); 191 1.1 pgoyette return 0; 192 1.1 pgoyette } 193 1.1 pgoyette 194 1.1 pgoyette /** 195 1.1 pgoyette * device_probe() method. All the actual probing was done by the imc 196 1.1 pgoyette * parent, so just report success. 197 1.1 pgoyette * 198 1.1 pgoyette * @author Joe Kloss 199 1.1 pgoyette * 200 1.1 pgoyette * @param[in,out] dev 201 1.1 pgoyette * Device being probed. 202 1.1 pgoyette */ 203 1.1 pgoyette static int 204 1.1 pgoyette imcsmb_probe(device_t parent, cfdata_t match, void *aux) 205 1.1 pgoyette { 206 1.1 pgoyette 207 1.1 pgoyette return 1; 208 1.1 pgoyette } 209 1.1 pgoyette 210 1.1 pgoyette static int 211 1.1 pgoyette imcsmb_acquire_bus(void *cookie, int flags) 212 1.1 pgoyette { 213 1.1 pgoyette struct imcsmb_softc *sc = cookie; 214 1.1 pgoyette 215 1.1 pgoyette if (cold) 216 1.1 pgoyette return 0; 217 1.1 pgoyette 218 1.1 pgoyette imc_callback(sc, IMC_BIOS_DISABLE); 219 1.1 pgoyette 220 1.1 pgoyette return 0; 221 1.1 pgoyette } 222 1.1 pgoyette 223 1.1 pgoyette static void 224 1.1 pgoyette imcsmb_release_bus(void *cookie, int flags) 225 1.1 pgoyette { 226 1.1 pgoyette struct imcsmb_softc *sc = cookie; 227 1.1 pgoyette 228 1.1 pgoyette if (cold) 229 1.1 pgoyette return; 230 1.1 pgoyette 231 1.1 pgoyette imc_callback(sc, IMC_BIOS_ENABLE); 232 1.1 pgoyette } 233 1.1 pgoyette 234 1.1 pgoyette static int 235 1.1 pgoyette imcsmb_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmdbuf, 236 1.1 pgoyette size_t cmdlen, void *buf, size_t len, int flags) 237 1.1 pgoyette { 238 1.1 pgoyette struct imcsmb_softc *sc = cookie; 239 1.1 pgoyette int i; 240 1.1 pgoyette int rc = 0; 241 1.1 pgoyette uint32_t cmd_val; 242 1.1 pgoyette uint32_t cntl_val; 243 1.1 pgoyette uint32_t orig_cntl_val; 244 1.1 pgoyette uint32_t stat_val; 245 1.1 pgoyette uint16_t *word; 246 1.1 pgoyette uint16_t lword; 247 1.1 pgoyette uint8_t *byte; 248 1.1 pgoyette uint8_t lbyte; 249 1.1 pgoyette uint8_t cmd; 250 1.1 pgoyette 251 1.1 pgoyette if ((cmdlen != 1) || (len > 2) || (len < 1)) 252 1.1 pgoyette return EINVAL; 253 1.1 pgoyette 254 1.1 pgoyette byte = (uint8_t *) buf; 255 1.1 pgoyette word = (uint16_t *) buf; 256 1.1 pgoyette lbyte = *byte; 257 1.1 pgoyette lword = *word; 258 1.1 pgoyette 259 1.1 pgoyette /* We modify the value of the control register; save the original, so 260 1.1 pgoyette * we can restore it later 261 1.1 pgoyette */ 262 1.1 pgoyette orig_cntl_val = pci_conf_read(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 263 1.1 pgoyette sc->sc_regs->smb_cntl); 264 1.1 pgoyette 265 1.1 pgoyette cntl_val = orig_cntl_val; 266 1.1 pgoyette 267 1.1 pgoyette /* 268 1.1 pgoyette * Set up the SMBCNTL register 269 1.1 pgoyette */ 270 1.1 pgoyette 271 1.1 pgoyette /* [31:28] Clear the existing value of the DTI bits, then set them to 272 1.1 pgoyette * the four high bits of the slave address. 273 1.1 pgoyette */ 274 1.1 pgoyette cntl_val &= ~IMCSMB_CNTL_DTI_MASK; 275 1.1 pgoyette cntl_val |= ((uint32_t) addr & 0x78) << 25; 276 1.1 pgoyette 277 1.1 pgoyette /* [27:27] Set the CLK_OVERRIDE bit, to enable normal operation */ 278 1.1 pgoyette cntl_val |= IMCSMB_CNTL_CLK_OVERRIDE; 279 1.1 pgoyette 280 1.1 pgoyette /* [26:26] Clear the WRITE_DISABLE bit; the datasheet says this isn't 281 1.1 pgoyette * necessary, but empirically, it is. 282 1.1 pgoyette */ 283 1.1 pgoyette cntl_val &= ~IMCSMB_CNTL_WRITE_DISABLE_BIT; 284 1.1 pgoyette 285 1.1 pgoyette /* [9:9] Clear the POLL_EN bit, to stop the hardware TSOD polling. */ 286 1.1 pgoyette cntl_val &= ~IMCSMB_CNTL_POLL_EN; 287 1.1 pgoyette 288 1.1 pgoyette /* 289 1.1 pgoyette * Set up the SMBCMD register 290 1.1 pgoyette */ 291 1.1 pgoyette 292 1.1 pgoyette /* [31:31] Set the TRIGGER bit; when this gets written, the controller 293 1.1 pgoyette * will issue the command. 294 1.1 pgoyette */ 295 1.1 pgoyette cmd_val = IMCSMB_CMD_TRIGGER_BIT; 296 1.1 pgoyette 297 1.1 pgoyette /* [29:29] For word operations, set the WORD_ACCESS bit. */ 298 1.1 pgoyette if (len == 2) { 299 1.1 pgoyette cmd_val |= IMCSMB_CMD_WORD_ACCESS; 300 1.1 pgoyette } 301 1.1 pgoyette 302 1.1 pgoyette /* [27:27] For write operations, set the WRITE bit. */ 303 1.1 pgoyette if (I2C_OP_WRITE_P(op)) { 304 1.1 pgoyette cmd_val |= IMCSMB_CMD_WRITE_BIT; 305 1.1 pgoyette } 306 1.1 pgoyette 307 1.1 pgoyette /* [26:24] The three non-DTI, non-R/W bits of the slave address. */ 308 1.1 pgoyette cmd_val |= (uint32_t) ((addr & 0x7) << 24); 309 1.1 pgoyette 310 1.1 pgoyette /* [23:16] The command (offset in the case of an EEPROM, or register in 311 1.1 pgoyette * the case of TSOD or NVDIMM controller). 312 1.1 pgoyette */ 313 1.1 pgoyette cmd = *((const uint8_t *) cmdbuf); 314 1.1 pgoyette cmd_val |= (uint32_t) (cmd << 16); 315 1.1 pgoyette 316 1.1 pgoyette /* [15:0] The data to be written for a write operation. */ 317 1.1 pgoyette if (I2C_OP_WRITE_P(op)) { 318 1.1 pgoyette if (len == 2) { 319 1.1 pgoyette /* The datasheet says the controller uses different 320 1.1 pgoyette * endianness for word operations on I2C vs SMBus! 321 1.1 pgoyette * I2C: [15:8] = MSB; [7:0] = LSB 322 1.1 pgoyette * SMB: [15:8] = LSB; [7:0] = MSB 323 1.1 pgoyette * As a practical matter, this controller is very 324 1.1 pgoyette * specifically for use with DIMMs, the SPD (and 325 1.1 pgoyette * NVDIMM controllers) are only accessed as bytes, 326 1.1 pgoyette * the temperature sensor is only accessed as words, and 327 1.1 pgoyette * the temperature sensors are I2C. Thus, byte-swap the 328 1.1 pgoyette * word. 329 1.1 pgoyette */ 330 1.1 pgoyette lword = htobe16(*(uint16_t *)buf); 331 1.1 pgoyette } else { 332 1.1 pgoyette /* For byte operations, the data goes in the LSB, and 333 1.1 pgoyette * the MSB is a don't care. 334 1.1 pgoyette */ 335 1.1 pgoyette lword = *(uint8_t *)buf; 336 1.1 pgoyette } 337 1.1 pgoyette cmd_val |= lword; 338 1.1 pgoyette } 339 1.1 pgoyette 340 1.1 pgoyette /* Write the updated value to the control register first, to disable 341 1.1 pgoyette * the hardware TSOD polling. 342 1.1 pgoyette */ 343 1.1 pgoyette pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 344 1.1 pgoyette sc->sc_regs->smb_cntl, cntl_val); 345 1.1 pgoyette 346 1.1 pgoyette /* Poll on the BUSY bit in the status register until clear, or timeout. 347 1.1 pgoyette * We just cleared the auto-poll bit, so we need to make sure the device 348 1.1 pgoyette * is idle before issuing a command. We can safely timeout after 35 ms, 349 1.1 pgoyette * as this is the maximum time the SMBus spec allows for a transaction. 350 1.1 pgoyette */ 351 1.1 pgoyette for (i = 4; i != 0; i--) { 352 1.1 pgoyette stat_val = pci_conf_read(sc->sc_pci_chipset_tag, 353 1.1 pgoyette sc->sc_pci_tag, sc->sc_regs->smb_stat); 354 1.1 pgoyette if (! (stat_val & IMCSMB_STATUS_BUSY_BIT)) { 355 1.1 pgoyette break; 356 1.1 pgoyette } 357 1.1 pgoyette delay(100); /* wait 10ms */ 358 1.1 pgoyette } 359 1.1 pgoyette 360 1.1 pgoyette if (i == 0) { 361 1.1 pgoyette aprint_debug_dev(sc->sc_dev, 362 1.1 pgoyette "transfer: timeout waiting for device to settle\n"); 363 1.1 pgoyette } 364 1.1 pgoyette 365 1.1 pgoyette /* Now that polling has stopped, we can write the command register. This 366 1.1 pgoyette * starts the SMBus command. 367 1.1 pgoyette */ 368 1.1 pgoyette pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 369 1.1 pgoyette sc->sc_regs->smb_cmd, cmd_val); 370 1.1 pgoyette 371 1.1 pgoyette /* Wait for WRITE_DATA_DONE/READ_DATA_VALID to be set, or timeout and 372 1.1 pgoyette * fail. We wait up to 35ms. 373 1.1 pgoyette */ 374 1.1 pgoyette for (i = 35000; i != 0; i -= 10) 375 1.1 pgoyette { 376 1.1 pgoyette delay(10); 377 1.1 pgoyette stat_val = pci_conf_read(sc->sc_pci_chipset_tag, 378 1.1 pgoyette sc->sc_pci_tag, sc->sc_regs->smb_stat); 379 1.1 pgoyette /* 380 1.1 pgoyette * For a write, the bits holding the data contain the data 381 1.1 pgoyette * being written. You would think that would cause the 382 1.1 pgoyette * READ_DATA_VALID bit to be cleared, because the data bits 383 1.1 pgoyette * no longer contain valid data from the most recent read 384 1.1 pgoyette * operation. While that would be logical, that's not the 385 1.1 pgoyette * case here: READ_DATA_VALID is only cleared when starting 386 1.1 pgoyette * a read operation, and WRITE_DATA_DONE is only cleared 387 1.1 pgoyette * when starting a write operation. 388 1.1 pgoyette */ 389 1.1 pgoyette if (I2C_OP_WRITE_P(op)) { 390 1.1 pgoyette if (stat_val & IMCSMB_STATUS_WRITE_DATA_DONE) { 391 1.1 pgoyette break; 392 1.1 pgoyette } 393 1.1 pgoyette } else { 394 1.1 pgoyette if (stat_val & IMCSMB_STATUS_READ_DATA_VALID) { 395 1.1 pgoyette break; 396 1.1 pgoyette } 397 1.1 pgoyette } 398 1.1 pgoyette } 399 1.1 pgoyette if (i == 0) { 400 1.1 pgoyette rc = ETIMEDOUT; 401 1.1 pgoyette aprint_debug_dev(sc->sc_dev, "transfer timeout\n"); 402 1.1 pgoyette goto out; 403 1.1 pgoyette } 404 1.1 pgoyette 405 1.1 pgoyette /* It is generally the case that this bit indicates non-ACK, but it 406 1.1 pgoyette * could also indicate other bus errors. There's no way to tell the 407 1.1 pgoyette * difference. 408 1.1 pgoyette */ 409 1.1 pgoyette if (stat_val & IMCSMB_STATUS_BUS_ERROR_BIT) { 410 1.1 pgoyette /* While it is not documented, empirically, SPD page-change 411 1.1 pgoyette * commands (writes with DTI = 0x30) always complete with the 412 1.1 pgoyette * error bit set. So, ignore it in those cases. 413 1.1 pgoyette */ 414 1.1 pgoyette if ((addr & 0x78) != 0x30) { 415 1.1 pgoyette rc = ENODEV; 416 1.1 pgoyette goto out; 417 1.1 pgoyette } 418 1.1 pgoyette } 419 1.1 pgoyette 420 1.1 pgoyette /* For a read operation, copy the data out */ 421 1.1 pgoyette if (I2C_OP_READ_P(op)) { 422 1.1 pgoyette if (len == 2) { 423 1.1 pgoyette /* The data is returned in bits [15:0]; as discussed 424 1.1 pgoyette * above, byte-swap. 425 1.1 pgoyette */ 426 1.1 pgoyette lword = (uint16_t) (stat_val & 0xffff); 427 1.1 pgoyette lword = htobe16(lword); 428 1.1 pgoyette *(uint16_t *)buf = lword; 429 1.1 pgoyette } else { 430 1.1 pgoyette /* The data is returned in bits [7:0] */ 431 1.1 pgoyette lbyte = (uint8_t) (stat_val & 0xff); 432 1.1 pgoyette *(uint8_t *)buf = lbyte; 433 1.1 pgoyette } 434 1.1 pgoyette } 435 1.1 pgoyette 436 1.1 pgoyette out: 437 1.1 pgoyette /* Restore the original value of the control register. */ 438 1.1 pgoyette pci_conf_write(sc->sc_pci_chipset_tag, sc->sc_pci_tag, 439 1.1 pgoyette sc->sc_regs->smb_cntl, orig_cntl_val); 440 1.1 pgoyette return rc; 441 1.1 pgoyette }; 442 1.1 pgoyette 443 1.1 pgoyette MODULE(MODULE_CLASS_DRIVER, imcsmb, "imc,iic"); 444 1.1 pgoyette 445 1.1 pgoyette #ifdef _MODULE 446 1.1 pgoyette #include "ioconf.c" 447 1.1 pgoyette #endif 448 1.1 pgoyette 449 1.1 pgoyette static int 450 1.1 pgoyette imcsmb_modcmd(modcmd_t cmd, void *opaque) 451 1.1 pgoyette { 452 1.1 pgoyette int error = 0; 453 1.1 pgoyette 454 1.1 pgoyette #ifdef _MODULE 455 1.1 pgoyette switch (cmd) { 456 1.1 pgoyette case MODULE_CMD_INIT: 457 1.1 pgoyette error = config_init_component(cfdriver_ioconf_imcsmb, 458 1.1 pgoyette cfattach_ioconf_imcsmb, cfdata_ioconf_imcsmb); 459 1.1 pgoyette break; 460 1.1 pgoyette case MODULE_CMD_FINI: 461 1.1 pgoyette error = config_fini_component(cfdriver_ioconf_imcsmb, 462 1.1 pgoyette cfattach_ioconf_imcsmb, cfdata_ioconf_imcsmb); 463 1.1 pgoyette break; 464 1.1 pgoyette default: 465 1.1 pgoyette error = ENOTTY; 466 1.1 pgoyette break; 467 1.1 pgoyette } 468 1.1 pgoyette #endif 469 1.1 pgoyette 470 1.1 pgoyette return error; 471 1.1 pgoyette } 472