| @@ -1,38 +1,38 @@ | | | @@ -1,38 +1,38 @@ |
1 | /* $NetBSD: ichsmb.c,v 1.50.6.4 2020/08/05 15:54:30 martin Exp $ */ | | 1 | /* $NetBSD: ichsmb.c,v 1.50.6.5 2021/12/03 17:54:30 martin Exp $ */ |
2 | /* $OpenBSD: ichiic.c,v 1.18 2007/05/03 09:36:26 dlg Exp $ */ | | 2 | /* $OpenBSD: ichiic.c,v 1.44 2020/10/07 11:23:05 jsg Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org> | | 5 | * Copyright (c) 2005, 2006 Alexander Yurchenko <grange@openbsd.org> |
6 | * | | 6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | | 7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above | | 8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. | | 9 | * copyright notice and this permission notice appear in all copies. |
10 | * | | 10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | */ | | 18 | */ |
19 | | | 19 | |
20 | /* | | 20 | /* |
21 | * Intel ICH SMBus controller driver. | | 21 | * Intel ICH SMBus controller driver. |
22 | */ | | 22 | */ |
23 | | | 23 | |
24 | #include <sys/cdefs.h> | | 24 | #include <sys/cdefs.h> |
25 | __KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.50.6.4 2020/08/05 15:54:30 martin Exp $"); | | 25 | __KERNEL_RCSID(0, "$NetBSD: ichsmb.c,v 1.50.6.5 2021/12/03 17:54:30 martin Exp $"); |
26 | | | 26 | |
27 | #include <sys/param.h> | | 27 | #include <sys/param.h> |
28 | #include <sys/device.h> | | 28 | #include <sys/device.h> |
29 | #include <sys/errno.h> | | 29 | #include <sys/errno.h> |
30 | #include <sys/kernel.h> | | 30 | #include <sys/kernel.h> |
31 | #include <sys/mutex.h> | | 31 | #include <sys/mutex.h> |
32 | #include <sys/proc.h> | | 32 | #include <sys/proc.h> |
33 | | | 33 | |
34 | #include <sys/bus.h> | | 34 | #include <sys/bus.h> |
35 | | | 35 | |
36 | #include <dev/pci/pcidevs.h> | | 36 | #include <dev/pci/pcidevs.h> |
37 | #include <dev/pci/pcireg.h> | | 37 | #include <dev/pci/pcireg.h> |
38 | #include <dev/pci/pcivar.h> | | 38 | #include <dev/pci/pcivar.h> |
| @@ -109,45 +109,52 @@ ichsmb_match(device_t parent, cfdata_t m | | | @@ -109,45 +109,52 @@ ichsmb_match(device_t parent, cfdata_t m |
109 | case PCI_PRODUCT_INTEL_82801I_SMB: | | 109 | case PCI_PRODUCT_INTEL_82801I_SMB: |
110 | case PCI_PRODUCT_INTEL_82801JD_SMB: | | 110 | case PCI_PRODUCT_INTEL_82801JD_SMB: |
111 | case PCI_PRODUCT_INTEL_82801JI_SMB: | | 111 | case PCI_PRODUCT_INTEL_82801JI_SMB: |
112 | case PCI_PRODUCT_INTEL_3400_SMB: | | 112 | case PCI_PRODUCT_INTEL_3400_SMB: |
113 | case PCI_PRODUCT_INTEL_6SERIES_SMB: | | 113 | case PCI_PRODUCT_INTEL_6SERIES_SMB: |
114 | case PCI_PRODUCT_INTEL_7SERIES_SMB: | | 114 | case PCI_PRODUCT_INTEL_7SERIES_SMB: |
115 | case PCI_PRODUCT_INTEL_8SERIES_SMB: | | 115 | case PCI_PRODUCT_INTEL_8SERIES_SMB: |
116 | case PCI_PRODUCT_INTEL_9SERIES_SMB: | | 116 | case PCI_PRODUCT_INTEL_9SERIES_SMB: |
117 | case PCI_PRODUCT_INTEL_100SERIES_SMB: | | 117 | case PCI_PRODUCT_INTEL_100SERIES_SMB: |
118 | case PCI_PRODUCT_INTEL_100SERIES_LP_SMB: | | 118 | case PCI_PRODUCT_INTEL_100SERIES_LP_SMB: |
119 | case PCI_PRODUCT_INTEL_2HS_SMB: | | 119 | case PCI_PRODUCT_INTEL_2HS_SMB: |
120 | case PCI_PRODUCT_INTEL_3HS_SMB: | | 120 | case PCI_PRODUCT_INTEL_3HS_SMB: |
121 | case PCI_PRODUCT_INTEL_3HS_U_SMB: | | 121 | case PCI_PRODUCT_INTEL_3HS_U_SMB: |
| | | 122 | case PCI_PRODUCT_INTEL_4HS_H_SMB: |
| | | 123 | case PCI_PRODUCT_INTEL_4HS_V_SMB: |
122 | case PCI_PRODUCT_INTEL_CORE4G_M_SMB: | | 124 | case PCI_PRODUCT_INTEL_CORE4G_M_SMB: |
123 | case PCI_PRODUCT_INTEL_CORE5G_M_SMB: | | 125 | case PCI_PRODUCT_INTEL_CORE5G_M_SMB: |
124 | case PCI_PRODUCT_INTEL_CMTLK_SMB: | | 126 | case PCI_PRODUCT_INTEL_CMTLK_SMB: |
125 | case PCI_PRODUCT_INTEL_BAYTRAIL_PCU_SMB: | | 127 | case PCI_PRODUCT_INTEL_BAYTRAIL_PCU_SMB: |
126 | case PCI_PRODUCT_INTEL_BSW_PCU_SMB: | | 128 | case PCI_PRODUCT_INTEL_BSW_PCU_SMB: |
127 | case PCI_PRODUCT_INTEL_APL_SMB: | | 129 | case PCI_PRODUCT_INTEL_APL_SMB: |
128 | case PCI_PRODUCT_INTEL_GLK_SMB: | | 130 | case PCI_PRODUCT_INTEL_GLK_SMB: |
| | | 131 | case PCI_PRODUCT_INTEL_EHL_SMB: |
| | | 132 | case PCI_PRODUCT_INTEL_JSL_SMB: |
129 | case PCI_PRODUCT_INTEL_C600_SMBUS: | | 133 | case PCI_PRODUCT_INTEL_C600_SMBUS: |
130 | case PCI_PRODUCT_INTEL_C600_SMB_0: | | 134 | case PCI_PRODUCT_INTEL_C600_SMB_0: |
131 | case PCI_PRODUCT_INTEL_C600_SMB_1: | | 135 | case PCI_PRODUCT_INTEL_C600_SMB_1: |
132 | case PCI_PRODUCT_INTEL_C600_SMB_2: | | 136 | case PCI_PRODUCT_INTEL_C600_SMB_2: |
133 | case PCI_PRODUCT_INTEL_C610_SMB: | | 137 | case PCI_PRODUCT_INTEL_C610_SMB: |
134 | case PCI_PRODUCT_INTEL_C620_SMB: | | 138 | case PCI_PRODUCT_INTEL_C620_SMB: |
135 | case PCI_PRODUCT_INTEL_C620_SMB_S: | | 139 | case PCI_PRODUCT_INTEL_C620_SMB_S: |
136 | case PCI_PRODUCT_INTEL_EP80579_SMB: | | 140 | case PCI_PRODUCT_INTEL_EP80579_SMB: |
137 | case PCI_PRODUCT_INTEL_DH89XXCC_SMB: | | 141 | case PCI_PRODUCT_INTEL_DH89XXCC_SMB: |
138 | case PCI_PRODUCT_INTEL_DH89XXCL_SMB: | | 142 | case PCI_PRODUCT_INTEL_DH89XXCL_SMB: |
139 | case PCI_PRODUCT_INTEL_C2000_PCU_SMBUS: | | 143 | case PCI_PRODUCT_INTEL_C2000_PCU_SMBUS: |
140 | case PCI_PRODUCT_INTEL_C3K_SMBUS_LEGACY: | | 144 | case PCI_PRODUCT_INTEL_C3K_SMBUS_LEGACY: |
| | | 145 | case PCI_PRODUCT_INTEL_495_YU_SMB: |
| | | 146 | case PCI_PRODUCT_INTEL_5HS_H_SMB: |
| | | 147 | case PCI_PRODUCT_INTEL_5HS_LP_SMB: |
141 | return 1; | | 148 | return 1; |
142 | } | | 149 | } |
143 | } | | 150 | } |
144 | return 0; | | 151 | return 0; |
145 | } | | 152 | } |
146 | | | 153 | |
147 | static void | | 154 | static void |
148 | ichsmb_attach(device_t parent, device_t self, void *aux) | | 155 | ichsmb_attach(device_t parent, device_t self, void *aux) |
149 | { | | 156 | { |
150 | struct ichsmb_softc *sc = device_private(self); | | 157 | struct ichsmb_softc *sc = device_private(self); |
151 | struct pci_attach_args *pa = aux; | | 158 | struct pci_attach_args *pa = aux; |
152 | pcireg_t conf; | | 159 | pcireg_t conf; |
153 | bus_size_t iosize; | | 160 | bus_size_t iosize; |
| @@ -373,71 +380,68 @@ ichsmb_i2c_exec(void *cookie, i2c_op_t o | | | @@ -373,71 +380,68 @@ ichsmb_i2c_exec(void *cookie, i2c_op_t o |
373 | if (tsleep(sc, PRIBIO, "iicexec", ICHIIC_TIMEOUT * hz)) | | 380 | if (tsleep(sc, PRIBIO, "iicexec", ICHIIC_TIMEOUT * hz)) |
374 | goto timeout; | | 381 | goto timeout; |
375 | } | | 382 | } |
376 | | | 383 | |
377 | if (sc->sc_i2c_xfer.error) | | 384 | if (sc->sc_i2c_xfer.error) |
378 | return (1); | | 385 | return (1); |
379 | | | 386 | |
380 | return (0); | | 387 | return (0); |
381 | | | 388 | |
382 | timeout: | | 389 | timeout: |
383 | /* | | 390 | /* |
384 | * Transfer timeout. Kill the transaction and clear status bits. | | 391 | * Transfer timeout. Kill the transaction and clear status bits. |
385 | */ | | 392 | */ |
386 | snprintb(fbuf, sizeof(fbuf), LPCIB_SMB_HS_BITS, st); | | | |
387 | aprint_error_dev(sc->sc_dev, | | | |
388 | "exec: op %d, addr 0x%02x, cmdlen %zd, len %zd, " | | | |
389 | "flags 0x%02x: timeout, status %s\n", | | | |
390 | op, addr, cmdlen, len, flags, fbuf); | | | |
391 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HC, | | 393 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HC, |
392 | LPCIB_SMB_HC_KILL); | | 394 | LPCIB_SMB_HC_KILL); |
393 | DELAY(ICHIIC_DELAY); | | 395 | DELAY(ICHIIC_DELAY); |
394 | st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS); | | 396 | st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS); |
395 | if ((st & LPCIB_SMB_HS_FAILED) == 0) { | | 397 | if ((st & LPCIB_SMB_HS_FAILED) == 0) { |
396 | snprintb(fbuf, sizeof(fbuf), LPCIB_SMB_HS_BITS, st); | | 398 | snprintb(fbuf, sizeof(fbuf), LPCIB_SMB_HS_BITS, st); |
397 | aprint_error_dev(sc->sc_dev, "abort failed, status %s\n", | | 399 | aprint_error_dev(sc->sc_dev, "abort failed, status %s\n", |
398 | fbuf); | | 400 | fbuf); |
399 | } | | 401 | } |
400 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS, st); | | 402 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS, st); |
401 | return (1); | | 403 | return (1); |
402 | } | | 404 | } |
403 | | | 405 | |
404 | static int | | 406 | static int |
405 | ichsmb_intr(void *arg) | | 407 | ichsmb_intr(void *arg) |
406 | { | | 408 | { |
407 | struct ichsmb_softc *sc = arg; | | 409 | struct ichsmb_softc *sc = arg; |
408 | uint8_t st; | | 410 | uint8_t st; |
409 | uint8_t *b; | | 411 | uint8_t *b; |
410 | size_t len; | | 412 | size_t len; |
411 | #ifdef ICHIIC_DEBUG | | 413 | #ifdef ICHIIC_DEBUG |
412 | char fbuf[64]; | | 414 | char fbuf[64]; |
413 | #endif | | 415 | #endif |
414 | | | 416 | |
415 | /* Read status */ | | 417 | /* Read status */ |
416 | st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS); | | 418 | st = bus_space_read_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS); |
| | | 419 | |
| | | 420 | /* Clear status bits */ |
| | | 421 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS, st); |
| | | 422 | |
| | | 423 | /* XXX Ignore SMBALERT# for now */ |
417 | if ((st & LPCIB_SMB_HS_BUSY) != 0 || (st & (LPCIB_SMB_HS_INTR | | | 424 | if ((st & LPCIB_SMB_HS_BUSY) != 0 || (st & (LPCIB_SMB_HS_INTR | |
418 | LPCIB_SMB_HS_DEVERR | LPCIB_SMB_HS_BUSERR | LPCIB_SMB_HS_FAILED | | | 425 | LPCIB_SMB_HS_DEVERR | LPCIB_SMB_HS_BUSERR | LPCIB_SMB_HS_FAILED | |
419 | LPCIB_SMB_HS_SMBAL | LPCIB_SMB_HS_BDONE)) == 0) | | 426 | LPCIB_SMB_HS_BDONE)) == 0) |
420 | /* Interrupt was not for us */ | | 427 | /* Interrupt was not for us */ |
421 | return (0); | | 428 | return (0); |
422 | | | 429 | |
423 | #ifdef ICHIIC_DEBUG | | 430 | #ifdef ICHIIC_DEBUG |
424 | snprintb(fbuf, sizeof(fbuf), LPCIB_SMB_HS_BITS, st); | | 431 | snprintb(fbuf, sizeof(fbuf), LPCIB_SMB_HS_BITS, st); |
425 | printf("%s: intr st %s\n", device_xname(sc->sc_dev), fbuf); | | 432 | printf("%s: intr st %s\n", device_xname(sc->sc_dev), fbuf); |
426 | #endif | | 433 | #endif |
427 | | | 434 | |
428 | /* Clear status bits */ | | | |
429 | bus_space_write_1(sc->sc_iot, sc->sc_ioh, LPCIB_SMB_HS, st); | | | |
430 | | | | |
431 | /* Check for errors */ | | 435 | /* Check for errors */ |
432 | if (st & (LPCIB_SMB_HS_DEVERR | LPCIB_SMB_HS_BUSERR | LPCIB_SMB_HS_FAILED)) { | | 436 | if (st & (LPCIB_SMB_HS_DEVERR | LPCIB_SMB_HS_BUSERR | LPCIB_SMB_HS_FAILED)) { |
433 | sc->sc_i2c_xfer.error = 1; | | 437 | sc->sc_i2c_xfer.error = 1; |
434 | goto done; | | 438 | goto done; |
435 | } | | 439 | } |
436 | | | 440 | |
437 | if (st & LPCIB_SMB_HS_INTR) { | | 441 | if (st & LPCIB_SMB_HS_INTR) { |
438 | if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op)) | | 442 | if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op)) |
439 | goto done; | | 443 | goto done; |
440 | | | 444 | |
441 | /* Read data */ | | 445 | /* Read data */ |
442 | b = sc->sc_i2c_xfer.buf; | | 446 | b = sc->sc_i2c_xfer.buf; |
443 | len = sc->sc_i2c_xfer.len; | | 447 | len = sc->sc_i2c_xfer.len; |