Commit | Line | Data |
---|---|---|
c942fddf | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 | 2 | /* |
1da177e4 LT |
3 | Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, |
4 | Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker | |
5 | <mdsxyz123@yahoo.com> | |
b3b8df97 | 6 | Copyright (C) 2007 - 2014 Jean Delvare <jdelvare@suse.de> |
0cd96eb0 DW |
7 | Copyright (C) 2010 Intel Corporation, |
8 | David Woodhouse <dwmw2@infradead.org> | |
1da177e4 | 9 | |
1da177e4 LT |
10 | */ |
11 | ||
12 | /* | |
ce316110 JD |
13 | * Supports the following Intel I/O Controller Hubs (ICH): |
14 | * | |
15 | * I/O Block I2C | |
16 | * region SMBus Block proc. block | |
17 | * Chip name PCI ID size PEC buffer call read | |
18 | * --------------------------------------------------------------------------- | |
19 | * 82801AA (ICH) 0x2413 16 no no no no | |
20 | * 82801AB (ICH0) 0x2423 16 no no no no | |
21 | * 82801BA (ICH2) 0x2443 16 no no no no | |
22 | * 82801CA (ICH3) 0x2483 32 soft no no no | |
23 | * 82801DB (ICH4) 0x24c3 32 hard yes no no | |
24 | * 82801E (ICH5) 0x24d3 32 hard yes yes yes | |
25 | * 6300ESB 0x25a4 32 hard yes yes yes | |
26 | * 82801F (ICH6) 0x266a 32 hard yes yes yes | |
27 | * 6310ESB/6320ESB 0x269b 32 hard yes yes yes | |
28 | * 82801G (ICH7) 0x27da 32 hard yes yes yes | |
29 | * 82801H (ICH8) 0x283e 32 hard yes yes yes | |
30 | * 82801I (ICH9) 0x2930 32 hard yes yes yes | |
31 | * EP80579 (Tolapai) 0x5032 32 hard yes yes yes | |
32 | * ICH10 0x3a30 32 hard yes yes yes | |
33 | * ICH10 0x3a60 32 hard yes yes yes | |
34 | * 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes | |
35 | * 6 Series (PCH) 0x1c22 32 hard yes yes yes | |
36 | * Patsburg (PCH) 0x1d22 32 hard yes yes yes | |
37 | * Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes | |
38 | * Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes | |
39 | * Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes | |
40 | * DH89xxCC (PCH) 0x2330 32 hard yes yes yes | |
41 | * Panther Point (PCH) 0x1e22 32 hard yes yes yes | |
42 | * Lynx Point (PCH) 0x8c22 32 hard yes yes yes | |
43 | * Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes | |
44 | * Avoton (SOC) 0x1f3c 32 hard yes yes yes | |
45 | * Wellsburg (PCH) 0x8d22 32 hard yes yes yes | |
46 | * Wellsburg (PCH) MS 0x8d7d 32 hard yes yes yes | |
47 | * Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes | |
48 | * Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes | |
49 | * Coleto Creek (PCH) 0x23b0 32 hard yes yes yes | |
b299de83 | 50 | * Wildcat Point (PCH) 0x8ca2 32 hard yes yes yes |
ce316110 JD |
51 | * Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes |
52 | * BayTrail (SOC) 0x0f12 32 hard yes yes yes | |
15407798 | 53 | * Braswell (SOC) 0x2292 32 hard yes yes yes |
3e27a844 | 54 | * Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes |
3eee1799 | 55 | * Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes |
84d7f2eb | 56 | * DNV (SOC) 0x19df 32 hard yes yes yes |
12745b07 | 57 | * Emmitsburg (PCH) 0x1bc9 32 hard yes yes yes |
dd77f423 | 58 | * Broxton (SOC) 0x5ad4 32 hard yes yes yes |
cdc5a311 AY |
59 | * Lewisburg (PCH) 0xa1a3 32 hard yes yes yes |
60 | * Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes | |
31158763 | 61 | * Kaby Lake PCH-H (PCH) 0xa2a3 32 hard yes yes yes |
9827f9eb | 62 | * Gemini Lake (SOC) 0x31d4 32 hard yes yes yes |
09a1de04 SP |
63 | * Cannon Lake-H (PCH) 0xa323 32 hard yes yes yes |
64 | * Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes | |
cb09d943 | 65 | * Cedar Fork (PCH) 0x18df 32 hard yes yes yes |
0bff2a86 | 66 | * Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes |
76eb4db6 | 67 | * Ice Lake-N (PCH) 0x38a3 32 hard yes yes yes |
5cd1c56c | 68 | * Comet Lake (PCH) 0x02a3 32 hard yes yes yes |
07f047e3 | 69 | * Comet Lake-H (PCH) 0x06a3 32 hard yes yes yes |
9be1485a | 70 | * Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes |
051d769f | 71 | * Tiger Lake-LP (PCH) 0xa0a3 32 hard yes yes yes |
f46efbca | 72 | * Tiger Lake-H (PCH) 0x43a3 32 hard yes yes yes |
790591f4 | 73 | * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes |
f53938d2 | 74 | * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes |
332fdaeb | 75 | * Alder Lake-S (PCH) 0x7aa3 32 hard yes yes yes |
d1f50bcf | 76 | * Alder Lake-P (PCH) 0x51a3 32 hard yes yes yes |
8f51c176 | 77 | * Alder Lake-M (PCH) 0x54a3 32 hard yes yes yes |
9c02d401 | 78 | * Raptor Lake-S (PCH) 0x7a23 32 hard yes yes yes |
24fff66f | 79 | * Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes |
e755ef00 | 80 | * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes |
bcfc2ab7 | 81 | * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes |
8c56f9ef | 82 | * Birch Stream (SOC) 0x5796 32 hard yes yes yes |
f0eda4dd | 83 | * Arrow Lake-H (SOC) 0x7722 32 hard yes yes yes |
bd492b58 JN |
84 | * Panther Lake-H (SOC) 0xe322 32 hard yes yes yes |
85 | * Panther Lake-P (SOC) 0xe422 32 hard yes yes yes | |
ce316110 JD |
86 | * |
87 | * Features supported by this driver: | |
88 | * Software PEC no | |
89 | * Hardware PEC yes | |
90 | * Block buffer yes | |
315cd67c | 91 | * Block process call transaction yes |
ce316110 | 92 | * I2C block read transaction yes (doesn't use the block buffer) |
d08cac0a | 93 | * Target mode no |
7b0ed334 | 94 | * SMBus Host Notify yes |
ce316110 JD |
95 | * Interrupt processing yes |
96 | * | |
ccf988b6 | 97 | * See the file Documentation/i2c/busses/i2c-i801.rst for details. |
ce316110 | 98 | */ |
1da177e4 | 99 | |
d4a994f6 HK |
100 | #define DRV_NAME "i801_smbus" |
101 | ||
636752bc | 102 | #include <linux/interrupt.h> |
1da177e4 LT |
103 | #include <linux/module.h> |
104 | #include <linux/pci.h> | |
105 | #include <linux/kernel.h> | |
106 | #include <linux/stddef.h> | |
107 | #include <linux/delay.h> | |
1da177e4 LT |
108 | #include <linux/ioport.h> |
109 | #include <linux/init.h> | |
110 | #include <linux/i2c.h> | |
893fef0b | 111 | #include <linux/i2c-mux.h> |
7b0ed334 | 112 | #include <linux/i2c-smbus.h> |
54fb4a05 | 113 | #include <linux/acpi.h> |
1561bfe5 | 114 | #include <linux/io.h> |
fa5bfab7 | 115 | #include <linux/dmi.h> |
665a96b7 | 116 | #include <linux/slab.h> |
af668d65 | 117 | #include <linux/string.h> |
1de93d5d | 118 | #include <linux/completion.h> |
3ad7ea18 | 119 | #include <linux/err.h> |
94246930 MW |
120 | #include <linux/platform_device.h> |
121 | #include <linux/platform_data/itco_wdt.h> | |
5c7b9167 | 122 | #include <linux/platform_data/x86/p2sb.h> |
a7401ca5 | 123 | #include <linux/pm_runtime.h> |
1a987c69 | 124 | #include <linux/mutex.h> |
3ad7ea18 | 125 | |
9c535237 | 126 | #ifdef CONFIG_I2C_I801_MUX |
d308dfbf | 127 | #include <linux/gpio/machine.h> |
62ea22c4 | 128 | #include <linux/platform_data/i2c-mux-gpio.h> |
3ad7ea18 | 129 | #endif |
1da177e4 | 130 | |
1da177e4 | 131 | /* I801 SMBus address offsets */ |
0cd96eb0 DW |
132 | #define SMBHSTSTS(p) (0 + (p)->smba) |
133 | #define SMBHSTCNT(p) (2 + (p)->smba) | |
134 | #define SMBHSTCMD(p) (3 + (p)->smba) | |
135 | #define SMBHSTADD(p) (4 + (p)->smba) | |
136 | #define SMBHSTDAT0(p) (5 + (p)->smba) | |
137 | #define SMBHSTDAT1(p) (6 + (p)->smba) | |
138 | #define SMBBLKDAT(p) (7 + (p)->smba) | |
139 | #define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */ | |
140 | #define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */ | |
141 | #define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */ | |
7b0ed334 BT |
142 | #define SMBSLVSTS(p) (16 + (p)->smba) /* ICH3 and later */ |
143 | #define SMBSLVCMD(p) (17 + (p)->smba) /* ICH3 and later */ | |
144 | #define SMBNTFDADD(p) (20 + (p)->smba) /* ICH3 and later */ | |
1da177e4 LT |
145 | |
146 | /* PCI Address Constants */ | |
d50f2f5d | 147 | #define SMBBAR_MMIO 0 |
6dcc19df | 148 | #define SMBBAR 4 |
1da177e4 | 149 | #define SMBHSTCFG 0x040 |
94246930 MW |
150 | #define TCOBASE 0x050 |
151 | #define TCOCTL 0x054 | |
152 | ||
94246930 | 153 | #define SBREG_SMBCTRL 0xc6000c |
851a1511 | 154 | #define SBREG_SMBCTRL_DNV 0xcf000c |
1da177e4 LT |
155 | |
156 | /* Host configuration bits for SMBHSTCFG */ | |
fe9ba3ec BT |
157 | #define SMBHSTCFG_HST_EN BIT(0) |
158 | #define SMBHSTCFG_SMB_SMI_EN BIT(1) | |
159 | #define SMBHSTCFG_I2C_EN BIT(2) | |
160 | #define SMBHSTCFG_SPD_WD BIT(4) | |
1da177e4 | 161 | |
94246930 | 162 | /* TCO configuration bits for TCOCTL */ |
fe9ba3ec | 163 | #define TCOCTL_EN BIT(8) |
94246930 | 164 | |
97d34ec1 | 165 | /* Auxiliary status register bits, ICH4+ only */ |
fe9ba3ec BT |
166 | #define SMBAUXSTS_CRCE BIT(0) |
167 | #define SMBAUXSTS_STCO BIT(1) | |
97d34ec1 | 168 | |
25985edc | 169 | /* Auxiliary control register bits, ICH4+ only */ |
fe9ba3ec BT |
170 | #define SMBAUXCTL_CRC BIT(0) |
171 | #define SMBAUXCTL_E32B BIT(1) | |
ca8b9e32 | 172 | |
1da177e4 LT |
173 | /* I801 command constants */ |
174 | #define I801_QUICK 0x00 | |
175 | #define I801_BYTE 0x04 | |
176 | #define I801_BYTE_DATA 0x08 | |
177 | #define I801_WORD_DATA 0x0C | |
55b6f82e | 178 | #define I801_PROC_CALL 0x10 |
1da177e4 | 179 | #define I801_BLOCK_DATA 0x14 |
6342064c | 180 | #define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ |
315cd67c | 181 | #define I801_BLOCK_PROC_CALL 0x1C |
edbeea63 DK |
182 | |
183 | /* I801 Host Control register bits */ | |
fe9ba3ec BT |
184 | #define SMBHSTCNT_INTREN BIT(0) |
185 | #define SMBHSTCNT_KILL BIT(1) | |
186 | #define SMBHSTCNT_LAST_BYTE BIT(5) | |
187 | #define SMBHSTCNT_START BIT(6) | |
188 | #define SMBHSTCNT_PEC_EN BIT(7) /* ICH3 and later */ | |
1da177e4 | 189 | |
ca8b9e32 | 190 | /* I801 Hosts Status register bits */ |
fe9ba3ec BT |
191 | #define SMBHSTSTS_BYTE_DONE BIT(7) |
192 | #define SMBHSTSTS_INUSE_STS BIT(6) | |
193 | #define SMBHSTSTS_SMBALERT_STS BIT(5) | |
194 | #define SMBHSTSTS_FAILED BIT(4) | |
195 | #define SMBHSTSTS_BUS_ERR BIT(3) | |
196 | #define SMBHSTSTS_DEV_ERR BIT(2) | |
197 | #define SMBHSTSTS_INTR BIT(1) | |
198 | #define SMBHSTSTS_HOST_BUSY BIT(0) | |
1da177e4 | 199 | |
9786b1f1 | 200 | /* Host Notify Status register bits */ |
fe9ba3ec | 201 | #define SMBSLVSTS_HST_NTFY_STS BIT(0) |
7b0ed334 | 202 | |
9786b1f1 | 203 | /* Host Notify Command register bits */ |
03a976c9 | 204 | #define SMBSLVCMD_SMBALERT_DISABLE BIT(2) |
fe9ba3ec | 205 | #define SMBSLVCMD_HST_NTFY_INTREN BIT(0) |
7b0ed334 | 206 | |
70a1cc19 DK |
207 | #define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \ |
208 | SMBHSTSTS_DEV_ERR) | |
209 | ||
210 | #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \ | |
211 | STATUS_ERROR_FLAGS) | |
cf898dc5 | 212 | |
29dae457 HK |
213 | #define SMBUS_LEN_SENTINEL (I2C_SMBUS_BLOCK_MAX + 1) |
214 | ||
a6e5e2be | 215 | /* Older devices have their ID defined in <linux/pci_ids.h> */ |
856078bf | 216 | #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3 |
07f047e3 | 217 | #define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3 |
ce316110 | 218 | #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 |
cb09d943 | 219 | #define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df |
34b57f40 | 220 | #define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df |
12745b07 | 221 | #define PCI_DEVICE_ID_INTEL_EBG_SMBUS 0x1bc9 |
ce316110 JD |
222 | #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 |
223 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 | |
55fee8d7 | 224 | /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ |
ce316110 JD |
225 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 |
226 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 | |
227 | #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 | |
228 | #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 | |
229 | #define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c | |
34b57f40 | 230 | #define PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS 0x2292 |
ce316110 JD |
231 | #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 |
232 | #define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS 0x23b0 | |
9827f9eb | 233 | #define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4 |
0bff2a86 | 234 | #define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3 |
76eb4db6 | 235 | #define PCI_DEVICE_ID_INTEL_ICELAKE_N_SMBUS 0x38a3 |
ce316110 | 236 | #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 |
f46efbca | 237 | #define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3 |
856078bf | 238 | #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 |
790591f4 | 239 | #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 |
d1f50bcf | 240 | #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3 |
8f51c176 | 241 | #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 |
8c56f9ef | 242 | #define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796 |
34b57f40 | 243 | #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 |
f0eda4dd | 244 | #define PCI_DEVICE_ID_INTEL_ARROW_LAKE_H_SMBUS 0x7722 |
9c02d401 | 245 | #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 |
332fdaeb | 246 | #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 |
24fff66f | 247 | #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_P_SMBUS 0x7e22 |
bcfc2ab7 | 248 | #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_PCH_S_SMBUS 0x7f23 |
ce316110 | 249 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 |
b299de83 | 250 | #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS 0x8ca2 |
ce316110 JD |
251 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS 0x8d22 |
252 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0 0x8d7d | |
253 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e | |
254 | #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f | |
255 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 | |
afc65924 | 256 | #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2 |
3eee1799 | 257 | #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS 0x9d23 |
09a1de04 | 258 | #define PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS 0x9da3 |
051d769f | 259 | #define PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS 0xa0a3 |
34b57f40 | 260 | #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS 0xa123 |
cdc5a311 AY |
261 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS 0xa1a3 |
262 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223 | |
31158763 | 263 | #define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3 |
09a1de04 | 264 | #define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323 |
f53938d2 | 265 | #define PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS 0xa3a3 |
e755ef00 | 266 | #define PCI_DEVICE_ID_INTEL_METEOR_LAKE_SOC_S_SMBUS 0xae22 |
bd492b58 JN |
267 | #define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_H_SMBUS 0xe322 |
268 | #define PCI_DEVICE_ID_INTEL_PANTHER_LAKE_P_SMBUS 0xe422 | |
55fee8d7 | 269 | |
3ad7ea18 JD |
270 | struct i801_mux_config { |
271 | char *gpio_chip; | |
272 | unsigned values[3]; | |
273 | int n_values; | |
3ad7ea18 JD |
274 | unsigned gpios[2]; /* Relative to gpio_chip->base */ |
275 | int n_gpios; | |
276 | }; | |
277 | ||
0cd96eb0 DW |
278 | struct i801_priv { |
279 | struct i2c_adapter adapter; | |
4a3f77ea | 280 | void __iomem *smba; |
0cd96eb0 | 281 | unsigned char original_hstcfg; |
9b5bf587 | 282 | unsigned char original_hstcnt; |
22e94bd6 | 283 | unsigned char original_slvcmd; |
0cd96eb0 DW |
284 | struct pci_dev *pci_dev; |
285 | unsigned int features; | |
636752bc DK |
286 | |
287 | /* isr processing */ | |
1de93d5d | 288 | struct completion done; |
636752bc | 289 | u8 status; |
d3ff6ce4 DK |
290 | |
291 | /* Command state used by isr for byte-by-byte block transactions */ | |
292 | u8 cmd; | |
293 | bool is_read; | |
294 | int count; | |
295 | int len; | |
296 | u8 *data; | |
3ad7ea18 | 297 | |
9c535237 | 298 | #ifdef CONFIG_I2C_I801_MUX |
3ad7ea18 | 299 | struct platform_device *mux_pdev; |
d308dfbf | 300 | struct gpiod_lookup_table *lookup; |
893fef0b | 301 | struct notifier_block mux_notifier_block; |
3ad7ea18 | 302 | #endif |
94246930 | 303 | struct platform_device *tco_pdev; |
a7ae8195 MW |
304 | |
305 | /* | |
306 | * If set to true the host controller registers are reserved for | |
f707d6b9 | 307 | * ACPI AML use. |
a7ae8195 MW |
308 | */ |
309 | bool acpi_reserved; | |
0cd96eb0 DW |
310 | }; |
311 | ||
f91fba62 BT |
312 | #define FEATURE_SMBUS_PEC BIT(0) |
313 | #define FEATURE_BLOCK_BUFFER BIT(1) | |
314 | #define FEATURE_BLOCK_PROC BIT(2) | |
315 | #define FEATURE_I2C_BLOCK_READ BIT(3) | |
316 | #define FEATURE_IRQ BIT(4) | |
317 | #define FEATURE_HOST_NOTIFY BIT(5) | |
e7198fbf | 318 | /* Not really a feature, but it's convenient to handle it as such */ |
f91fba62 | 319 | #define FEATURE_IDF BIT(15) |
b84398d6 MW |
320 | #define FEATURE_TCO_SPT BIT(16) |
321 | #define FEATURE_TCO_CNL BIT(17) | |
1da177e4 | 322 | |
adff687d JD |
323 | static const char *i801_feature_names[] = { |
324 | "SMBus PEC", | |
325 | "Block buffer", | |
326 | "Block process call", | |
327 | "I2C block read", | |
636752bc | 328 | "Interrupt", |
7b0ed334 | 329 | "SMBus Host Notify", |
adff687d JD |
330 | }; |
331 | ||
332 | static unsigned int disable_features; | |
333 | module_param(disable_features, uint, S_IRUGO | S_IWUSR); | |
53229345 JD |
334 | MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" |
335 | "\t\t 0x01 disable SMBus PEC\n" | |
336 | "\t\t 0x02 disable the block buffer\n" | |
337 | "\t\t 0x08 disable the I2C block read functionality\n" | |
7b0ed334 BT |
338 | "\t\t 0x10 don't use interrupts\n" |
339 | "\t\t 0x20 disable SMBus Host Notify "); | |
adff687d | 340 | |
e5befb5b HK |
341 | /* Wait for BUSY being cleared and either INTR or an error flag being set */ |
342 | static int i801_wait_intr(struct i801_priv *priv) | |
343 | { | |
344 | unsigned long timeout = jiffies + priv->adapter.timeout; | |
345 | int status, busy; | |
346 | ||
347 | do { | |
348 | usleep_range(250, 500); | |
4a3f77ea | 349 | status = ioread8(SMBHSTSTS(priv)); |
e5befb5b HK |
350 | busy = status & SMBHSTSTS_HOST_BUSY; |
351 | status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; | |
352 | if (!busy && status) | |
353 | return status & STATUS_ERROR_FLAGS; | |
354 | } while (time_is_after_eq_jiffies(timeout)); | |
355 | ||
356 | return -ETIMEDOUT; | |
357 | } | |
358 | ||
359 | /* Wait for either BYTE_DONE or an error flag being set */ | |
360 | static int i801_wait_byte_done(struct i801_priv *priv) | |
361 | { | |
362 | unsigned long timeout = jiffies + priv->adapter.timeout; | |
363 | int status; | |
364 | ||
365 | do { | |
366 | usleep_range(250, 500); | |
4a3f77ea | 367 | status = ioread8(SMBHSTSTS(priv)); |
e5befb5b HK |
368 | if (status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) |
369 | return status & STATUS_ERROR_FLAGS; | |
370 | } while (time_is_after_eq_jiffies(timeout)); | |
371 | ||
372 | return -ETIMEDOUT; | |
373 | } | |
374 | ||
857cc04c HK |
375 | static int i801_get_block_len(struct i801_priv *priv) |
376 | { | |
4a3f77ea | 377 | u8 len = ioread8(SMBHSTDAT0(priv)); |
857cc04c HK |
378 | |
379 | if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { | |
380 | pci_err(priv->pci_dev, "Illegal SMBus block read size %u\n", len); | |
381 | return -EPROTO; | |
382 | } | |
383 | ||
384 | return len; | |
385 | } | |
386 | ||
03f9863b HK |
387 | static int i801_check_and_clear_pec_error(struct i801_priv *priv) |
388 | { | |
389 | u8 status; | |
390 | ||
391 | if (!(priv->features & FEATURE_SMBUS_PEC)) | |
392 | return 0; | |
393 | ||
4a3f77ea | 394 | status = ioread8(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; |
03f9863b | 395 | if (status) { |
4a3f77ea | 396 | iowrite8(status, SMBAUXSTS(priv)); |
03f9863b HK |
397 | return -EBADMSG; |
398 | } | |
399 | ||
400 | return 0; | |
401 | } | |
402 | ||
cf898dc5 JD |
403 | /* Make sure the SMBus host is ready to start transmitting. |
404 | Return 0 if it is, -EBUSY if it is not. */ | |
0cd96eb0 | 405 | static int i801_check_pre(struct i801_priv *priv) |
1da177e4 | 406 | { |
03f9863b | 407 | int status, result; |
1da177e4 | 408 | |
4a3f77ea | 409 | status = ioread8(SMBHSTSTS(priv)); |
cf898dc5 | 410 | if (status & SMBHSTSTS_HOST_BUSY) { |
8c7a8967 | 411 | pci_err(priv->pci_dev, "SMBus is busy, can't use it!\n"); |
cf898dc5 JD |
412 | return -EBUSY; |
413 | } | |
414 | ||
415 | status &= STATUS_FLAGS; | |
416 | if (status) { | |
8c7a8967 | 417 | pci_dbg(priv->pci_dev, "Clearing status flags (%02x)\n", status); |
4a3f77ea | 418 | iowrite8(status, SMBHSTSTS(priv)); |
1da177e4 LT |
419 | } |
420 | ||
97d34ec1 EW |
421 | /* |
422 | * Clear CRC status if needed. | |
423 | * During normal operation, i801_check_post() takes care | |
424 | * of it after every operation. We do it here only in case | |
425 | * the hardware was already in this state when the driver | |
426 | * started. | |
427 | */ | |
03f9863b HK |
428 | result = i801_check_and_clear_pec_error(priv); |
429 | if (result) | |
430 | pci_dbg(priv->pci_dev, "Clearing aux status flag CRCE\n"); | |
97d34ec1 | 431 | |
cf898dc5 JD |
432 | return 0; |
433 | } | |
1da177e4 | 434 | |
6cad93c4 | 435 | static int i801_check_post(struct i801_priv *priv, int status) |
cf898dc5 JD |
436 | { |
437 | int result = 0; | |
1da177e4 | 438 | |
636752bc DK |
439 | /* |
440 | * If the SMBus is still busy, we give up | |
636752bc | 441 | */ |
6cad93c4 | 442 | if (unlikely(status < 0)) { |
ca8b9e32 | 443 | /* try to stop the current command */ |
4a3f77ea | 444 | iowrite8(SMBHSTCNT_KILL, SMBHSTCNT(priv)); |
3a3c6b7b | 445 | status = i801_wait_intr(priv); |
4a3f77ea | 446 | iowrite8(0, SMBHSTCNT(priv)); |
cf898dc5 JD |
447 | |
448 | /* Check if it worked */ | |
3a3c6b7b | 449 | if (status < 0 || !(status & SMBHSTSTS_FAILED)) |
9d515bf7 | 450 | pci_dbg(priv->pci_dev, "Failed terminating the transaction\n"); |
cf898dc5 | 451 | return -ETIMEDOUT; |
1da177e4 LT |
452 | } |
453 | ||
2b73809d | 454 | if (status & SMBHSTSTS_FAILED) { |
97140342 | 455 | result = -EIO; |
9d515bf7 | 456 | pci_err(priv->pci_dev, "Transaction failed\n"); |
cf898dc5 JD |
457 | } |
458 | if (status & SMBHSTSTS_DEV_ERR) { | |
97d34ec1 EW |
459 | /* |
460 | * This may be a PEC error, check and clear it. | |
461 | * | |
462 | * AUXSTS is handled differently from HSTSTS. | |
463 | * For HSTSTS, i801_isr() or i801_wait_intr() | |
464 | * has already cleared the error bits in hardware, | |
465 | * and we are passed a copy of the original value | |
466 | * in "status". | |
467 | * For AUXSTS, the hardware register is left | |
468 | * for us to handle here. | |
469 | * This is asymmetric, slightly iffy, but safe, | |
470 | * since all this code is serialized and the CRCE | |
471 | * bit is harmless as long as it's cleared before | |
472 | * the next operation. | |
473 | */ | |
03f9863b HK |
474 | result = i801_check_and_clear_pec_error(priv); |
475 | if (result) { | |
476 | pci_dbg(priv->pci_dev, "PEC error\n"); | |
97d34ec1 EW |
477 | } else { |
478 | result = -ENXIO; | |
03f9863b | 479 | pci_dbg(priv->pci_dev, "No response\n"); |
97d34ec1 | 480 | } |
1da177e4 | 481 | } |
2b73809d | 482 | if (status & SMBHSTSTS_BUS_ERR) { |
dcb5c923 | 483 | result = -EAGAIN; |
9d515bf7 | 484 | pci_dbg(priv->pci_dev, "Lost arbitration\n"); |
1da177e4 LT |
485 | } |
486 | ||
1da177e4 LT |
487 | return result; |
488 | } | |
489 | ||
6cad93c4 JD |
490 | static int i801_transaction(struct i801_priv *priv, int xact) |
491 | { | |
1de93d5d | 492 | unsigned long result; |
b3b8df97 | 493 | const struct i2c_adapter *adap = &priv->adapter; |
ca8b9e32 | 494 | |
636752bc | 495 | if (priv->features & FEATURE_IRQ) { |
1de93d5d | 496 | reinit_completion(&priv->done); |
4a3f77ea | 497 | iowrite8(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, |
636752bc | 498 | SMBHSTCNT(priv)); |
1de93d5d | 499 | result = wait_for_completion_timeout(&priv->done, adap->timeout); |
de461a26 | 500 | return result ? priv->status : -ETIMEDOUT; |
636752bc DK |
501 | } |
502 | ||
4a3f77ea | 503 | iowrite8(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); |
6cad93c4 | 504 | |
de461a26 | 505 | return i801_wait_intr(priv); |
ca8b9e32 OR |
506 | } |
507 | ||
0cd96eb0 DW |
508 | static int i801_block_transaction_by_block(struct i801_priv *priv, |
509 | union i2c_smbus_data *data, | |
a6b8bb6a | 510 | char read_write, int command) |
7edcb9ab | 511 | { |
4a3f77ea | 512 | int len, status, xact; |
315cd67c AS |
513 | |
514 | switch (command) { | |
515 | case I2C_SMBUS_BLOCK_PROC_CALL: | |
a6b8bb6a | 516 | xact = I801_BLOCK_PROC_CALL; |
315cd67c AS |
517 | break; |
518 | case I2C_SMBUS_BLOCK_DATA: | |
a6b8bb6a | 519 | xact = I801_BLOCK_DATA; |
315cd67c AS |
520 | break; |
521 | default: | |
522 | return -EOPNOTSUPP; | |
523 | } | |
7edcb9ab | 524 | |
1e1d6582 | 525 | /* Set block buffer mode */ |
4a3f77ea | 526 | iowrite8(ioread8(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); |
1e1d6582 | 527 | |
7edcb9ab OR |
528 | if (read_write == I2C_SMBUS_WRITE) { |
529 | len = data->block[0]; | |
4a3f77ea HK |
530 | iowrite8(len, SMBHSTDAT0(priv)); |
531 | ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */ | |
532 | iowrite8_rep(SMBBLKDAT(priv), data->block + 1, len); | |
7edcb9ab OR |
533 | } |
534 | ||
315cd67c | 535 | status = i801_transaction(priv, xact); |
97140342 | 536 | if (status) |
63fd342f | 537 | goto out; |
7edcb9ab | 538 | |
315cd67c AS |
539 | if (read_write == I2C_SMBUS_READ || |
540 | command == I2C_SMBUS_BLOCK_PROC_CALL) { | |
d1ef7a9c ML |
541 | len = i801_get_block_len(priv); |
542 | if (len < 0) { | |
543 | status = len; | |
63fd342f | 544 | goto out; |
d1ef7a9c | 545 | } |
7edcb9ab OR |
546 | |
547 | data->block[0] = len; | |
4a3f77ea HK |
548 | ioread8(SMBHSTCNT(priv)); /* reset the data buffer index */ |
549 | ioread8_rep(SMBBLKDAT(priv), data->block + 1, len); | |
7edcb9ab | 550 | } |
63fd342f | 551 | out: |
4a3f77ea | 552 | iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_E32B, SMBAUXCTL(priv)); |
63fd342f | 553 | return status; |
7edcb9ab OR |
554 | } |
555 | ||
d3ff6ce4 DK |
556 | static void i801_isr_byte_done(struct i801_priv *priv) |
557 | { | |
558 | if (priv->is_read) { | |
29dae457 HK |
559 | /* |
560 | * At transfer start i801_smbus_block_transaction() marks | |
561 | * the block length as invalid. Check for this sentinel value | |
562 | * and read the block length from SMBHSTDAT0. | |
563 | */ | |
564 | if (priv->len == SMBUS_LEN_SENTINEL) { | |
857cc04c HK |
565 | priv->len = i801_get_block_len(priv); |
566 | if (priv->len < 0) | |
d3ff6ce4 DK |
567 | /* FIXME: Recover */ |
568 | priv->len = I2C_SMBUS_BLOCK_MAX; | |
857cc04c | 569 | |
d3ff6ce4 DK |
570 | priv->data[-1] = priv->len; |
571 | } | |
572 | ||
573 | /* Read next byte */ | |
574 | if (priv->count < priv->len) | |
4a3f77ea | 575 | priv->data[priv->count++] = ioread8(SMBBLKDAT(priv)); |
d3ff6ce4 | 576 | else |
9d515bf7 | 577 | pci_dbg(priv->pci_dev, "Discarding extra byte on block read\n"); |
d3ff6ce4 DK |
578 | |
579 | /* Set LAST_BYTE for last byte of read transaction */ | |
580 | if (priv->count == priv->len - 1) | |
4a3f77ea | 581 | iowrite8(priv->cmd | SMBHSTCNT_LAST_BYTE, |
d3ff6ce4 DK |
582 | SMBHSTCNT(priv)); |
583 | } else if (priv->count < priv->len - 1) { | |
584 | /* Write next byte, except for IRQ after last byte */ | |
4a3f77ea | 585 | iowrite8(priv->data[++priv->count], SMBBLKDAT(priv)); |
d3ff6ce4 | 586 | } |
d3ff6ce4 DK |
587 | } |
588 | ||
7b0ed334 BT |
589 | static irqreturn_t i801_host_notify_isr(struct i801_priv *priv) |
590 | { | |
591 | unsigned short addr; | |
7b0ed334 | 592 | |
4a3f77ea | 593 | addr = ioread8(SMBNTFDADD(priv)) >> 1; |
7b0ed334 | 594 | |
c912a25a BT |
595 | /* |
596 | * With the tested platforms, reading SMBNTFDDAT (22 + (p)->smba) | |
4d5538f5 BT |
597 | * always returns 0. Our current implementation doesn't provide |
598 | * data, so we just ignore it. | |
c912a25a | 599 | */ |
4d5538f5 | 600 | i2c_handle_smbus_host_notify(&priv->adapter, addr); |
7b0ed334 BT |
601 | |
602 | /* clear Host Notify bit and return */ | |
4a3f77ea | 603 | iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); |
7b0ed334 BT |
604 | return IRQ_HANDLED; |
605 | } | |
606 | ||
636752bc | 607 | /* |
7b0ed334 | 608 | * There are three kinds of interrupts: |
d3ff6ce4 DK |
609 | * |
610 | * 1) i801 signals transaction completion with one of these interrupts: | |
611 | * INTR - Success | |
612 | * DEV_ERR - Invalid command, NAK or communication timeout | |
613 | * BUS_ERR - SMI# transaction collision | |
614 | * FAILED - transaction was canceled due to a KILL request | |
1de93d5d | 615 | * When any of these occur, update ->status and signal completion. |
d3ff6ce4 DK |
616 | * |
617 | * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt | |
618 | * occurs for each byte of a byte-by-byte to prepare the next byte. | |
7b0ed334 BT |
619 | * |
620 | * 3) Host Notify interrupts | |
636752bc DK |
621 | */ |
622 | static irqreturn_t i801_isr(int irq, void *dev_id) | |
623 | { | |
624 | struct i801_priv *priv = dev_id; | |
625 | u16 pcists; | |
626 | u8 status; | |
627 | ||
628 | /* Confirm this is our interrupt */ | |
0d3f1e45 HK |
629 | pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); |
630 | if (!(pcists & PCI_STATUS_INTERRUPT)) | |
636752bc DK |
631 | return IRQ_NONE; |
632 | ||
7b0ed334 | 633 | if (priv->features & FEATURE_HOST_NOTIFY) { |
4a3f77ea | 634 | status = ioread8(SMBSLVSTS(priv)); |
7b0ed334 BT |
635 | if (status & SMBSLVSTS_HST_NTFY_STS) |
636 | return i801_host_notify_isr(priv); | |
637 | } | |
638 | ||
4a3f77ea | 639 | status = ioread8(SMBHSTSTS(priv)); |
c467d919 | 640 | if ((status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS)) == SMBHSTSTS_BYTE_DONE) |
d3ff6ce4 DK |
641 | i801_isr_byte_done(priv); |
642 | ||
636752bc | 643 | /* |
c467d919 HK |
644 | * Clear IRQ sources: SMB_ALERT status is set after signal assertion |
645 | * independently of the interrupt generation being blocked or not | |
646 | * so clear it always when the status is set. | |
636752bc | 647 | */ |
c467d919 | 648 | status &= STATUS_FLAGS | SMBHSTSTS_SMBALERT_STS; |
4a3f77ea | 649 | iowrite8(status, SMBHSTSTS(priv)); |
c467d919 HK |
650 | |
651 | status &= STATUS_ERROR_FLAGS | SMBHSTSTS_INTR; | |
636752bc | 652 | if (status) { |
de461a26 | 653 | priv->status = status & STATUS_ERROR_FLAGS; |
1de93d5d | 654 | complete(&priv->done); |
636752bc DK |
655 | } |
656 | ||
657 | return IRQ_HANDLED; | |
658 | } | |
659 | ||
efa3cb15 DK |
660 | /* |
661 | * For "byte-by-byte" block transactions: | |
662 | * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1 | |
663 | * I2C read uses cmd=I801_I2C_BLOCK_DATA | |
664 | */ | |
0cd96eb0 DW |
665 | static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, |
666 | union i2c_smbus_data *data, | |
a6b8bb6a | 667 | char read_write, int command) |
1da177e4 LT |
668 | { |
669 | int i, len; | |
670 | int smbcmd; | |
2b73809d | 671 | int status; |
1de93d5d | 672 | unsigned long result; |
b3b8df97 | 673 | const struct i2c_adapter *adap = &priv->adapter; |
cf898dc5 | 674 | |
315cd67c AS |
675 | if (command == I2C_SMBUS_BLOCK_PROC_CALL) |
676 | return -EOPNOTSUPP; | |
677 | ||
7edcb9ab | 678 | len = data->block[0]; |
1da177e4 LT |
679 | |
680 | if (read_write == I2C_SMBUS_WRITE) { | |
4a3f77ea HK |
681 | iowrite8(len, SMBHSTDAT0(priv)); |
682 | iowrite8(data->block[1], SMBBLKDAT(priv)); | |
1da177e4 LT |
683 | } |
684 | ||
efa3cb15 DK |
685 | if (command == I2C_SMBUS_I2C_BLOCK_DATA && |
686 | read_write == I2C_SMBUS_READ) | |
687 | smbcmd = I801_I2C_BLOCK_DATA; | |
688 | else | |
689 | smbcmd = I801_BLOCK_DATA; | |
690 | ||
d3ff6ce4 DK |
691 | if (priv->features & FEATURE_IRQ) { |
692 | priv->is_read = (read_write == I2C_SMBUS_READ); | |
693 | if (len == 1 && priv->is_read) | |
694 | smbcmd |= SMBHSTCNT_LAST_BYTE; | |
695 | priv->cmd = smbcmd | SMBHSTCNT_INTREN; | |
696 | priv->len = len; | |
697 | priv->count = 0; | |
698 | priv->data = &data->block[1]; | |
699 | ||
1de93d5d | 700 | reinit_completion(&priv->done); |
4a3f77ea | 701 | iowrite8(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv)); |
1de93d5d | 702 | result = wait_for_completion_timeout(&priv->done, adap->timeout); |
de461a26 | 703 | return result ? priv->status : -ETIMEDOUT; |
d3ff6ce4 DK |
704 | } |
705 | ||
f78ca48a HK |
706 | if (len == 1 && read_write == I2C_SMBUS_READ) |
707 | smbcmd |= SMBHSTCNT_LAST_BYTE; | |
4a3f77ea | 708 | iowrite8(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv)); |
1da177e4 | 709 | |
f78ca48a | 710 | for (i = 1; i <= len; i++) { |
6cad93c4 JD |
711 | status = i801_wait_byte_done(priv); |
712 | if (status) | |
de461a26 | 713 | return status; |
1da177e4 | 714 | |
29dae457 HK |
715 | /* |
716 | * At transfer start i801_smbus_block_transaction() marks | |
717 | * the block length as invalid. Check for this sentinel value | |
718 | * and read the block length from SMBHSTDAT0. | |
719 | */ | |
720 | if (len == SMBUS_LEN_SENTINEL) { | |
857cc04c HK |
721 | len = i801_get_block_len(priv); |
722 | if (len < 0) { | |
cf898dc5 | 723 | /* Recover */ |
4a3f77ea | 724 | while (ioread8(SMBHSTSTS(priv)) & |
0cd96eb0 | 725 | SMBHSTSTS_HOST_BUSY) |
4a3f77ea | 726 | iowrite8(SMBHSTSTS_BYTE_DONE, |
0cd96eb0 | 727 | SMBHSTSTS(priv)); |
4a3f77ea | 728 | iowrite8(SMBHSTSTS_INTR, SMBHSTSTS(priv)); |
97140342 | 729 | return -EPROTO; |
cf898dc5 | 730 | } |
1da177e4 LT |
731 | data->block[0] = len; |
732 | } | |
733 | ||
f78ca48a | 734 | if (read_write == I2C_SMBUS_READ) { |
4a3f77ea | 735 | data->block[i] = ioread8(SMBBLKDAT(priv)); |
f78ca48a | 736 | if (i == len - 1) |
4a3f77ea | 737 | iowrite8(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv)); |
f78ca48a HK |
738 | } |
739 | ||
1da177e4 | 740 | if (read_write == I2C_SMBUS_WRITE && i+1 <= len) |
4a3f77ea | 741 | iowrite8(data->block[i+1], SMBBLKDAT(priv)); |
1da177e4 | 742 | |
cf898dc5 | 743 | /* signals SMBBLKDAT ready */ |
4a3f77ea | 744 | iowrite8(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv)); |
1da177e4 | 745 | } |
cf898dc5 | 746 | |
de461a26 | 747 | return i801_wait_intr(priv); |
7edcb9ab | 748 | } |
1da177e4 | 749 | |
eb4d8bac HK |
750 | static void i801_set_hstadd(struct i801_priv *priv, u8 addr, char read_write) |
751 | { | |
4a3f77ea | 752 | iowrite8((addr << 1) | (read_write & 0x01), SMBHSTADD(priv)); |
eb4d8bac HK |
753 | } |
754 | ||
dd2d18b5 HK |
755 | /* Single value transaction function */ |
756 | static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data *data, | |
24592482 | 757 | u8 addr, u8 hstcmd, char read_write, int command) |
dd2d18b5 HK |
758 | { |
759 | int xact, ret; | |
760 | ||
761 | switch (command) { | |
762 | case I2C_SMBUS_QUICK: | |
24592482 | 763 | i801_set_hstadd(priv, addr, read_write); |
dd2d18b5 HK |
764 | xact = I801_QUICK; |
765 | break; | |
766 | case I2C_SMBUS_BYTE: | |
24592482 HK |
767 | i801_set_hstadd(priv, addr, read_write); |
768 | if (read_write == I2C_SMBUS_WRITE) | |
4a3f77ea | 769 | iowrite8(hstcmd, SMBHSTCMD(priv)); |
dd2d18b5 HK |
770 | xact = I801_BYTE; |
771 | break; | |
772 | case I2C_SMBUS_BYTE_DATA: | |
24592482 | 773 | i801_set_hstadd(priv, addr, read_write); |
dd2d18b5 | 774 | if (read_write == I2C_SMBUS_WRITE) |
4a3f77ea HK |
775 | iowrite8(data->byte, SMBHSTDAT0(priv)); |
776 | iowrite8(hstcmd, SMBHSTCMD(priv)); | |
dd2d18b5 HK |
777 | xact = I801_BYTE_DATA; |
778 | break; | |
779 | case I2C_SMBUS_WORD_DATA: | |
24592482 | 780 | i801_set_hstadd(priv, addr, read_write); |
dd2d18b5 | 781 | if (read_write == I2C_SMBUS_WRITE) { |
4a3f77ea HK |
782 | iowrite8(data->word & 0xff, SMBHSTDAT0(priv)); |
783 | iowrite8((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); | |
dd2d18b5 | 784 | } |
4a3f77ea | 785 | iowrite8(hstcmd, SMBHSTCMD(priv)); |
dd2d18b5 HK |
786 | xact = I801_WORD_DATA; |
787 | break; | |
788 | case I2C_SMBUS_PROC_CALL: | |
24592482 | 789 | i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); |
4a3f77ea HK |
790 | iowrite8(data->word & 0xff, SMBHSTDAT0(priv)); |
791 | iowrite8((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); | |
792 | iowrite8(hstcmd, SMBHSTCMD(priv)); | |
24592482 | 793 | read_write = I2C_SMBUS_READ; |
dd2d18b5 HK |
794 | xact = I801_PROC_CALL; |
795 | break; | |
796 | default: | |
24592482 | 797 | pci_err(priv->pci_dev, "Unsupported transaction %d\n", command); |
dd2d18b5 HK |
798 | return -EOPNOTSUPP; |
799 | } | |
800 | ||
801 | ret = i801_transaction(priv, xact); | |
802 | if (ret || read_write == I2C_SMBUS_WRITE) | |
803 | return ret; | |
804 | ||
805 | switch (command) { | |
806 | case I2C_SMBUS_BYTE: | |
807 | case I2C_SMBUS_BYTE_DATA: | |
4a3f77ea | 808 | data->byte = ioread8(SMBHSTDAT0(priv)); |
dd2d18b5 HK |
809 | break; |
810 | case I2C_SMBUS_WORD_DATA: | |
811 | case I2C_SMBUS_PROC_CALL: | |
4a3f77ea HK |
812 | data->word = ioread8(SMBHSTDAT0(priv)) + |
813 | (ioread8(SMBHSTDAT1(priv)) << 8); | |
dd2d18b5 HK |
814 | break; |
815 | } | |
816 | ||
817 | return 0; | |
818 | } | |
819 | ||
6ff9d46c HK |
820 | static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data, |
821 | u8 addr, u8 hstcmd, char read_write, int command) | |
7edcb9ab | 822 | { |
effa4531 | 823 | if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA) |
29dae457 HK |
824 | /* Mark block length as invalid */ |
825 | data->block[0] = SMBUS_LEN_SENTINEL; | |
effa4531 HK |
826 | else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) |
827 | return -EPROTO; | |
828 | ||
6ff9d46c | 829 | if (command == I2C_SMBUS_BLOCK_PROC_CALL) |
a3989dc0 HK |
830 | /* Needs to be flagged as write transaction */ |
831 | i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); | |
6ff9d46c HK |
832 | else |
833 | i801_set_hstadd(priv, addr, read_write); | |
4a3f77ea | 834 | iowrite8(hstcmd, SMBHSTCMD(priv)); |
6ff9d46c HK |
835 | |
836 | if (priv->features & FEATURE_BLOCK_BUFFER) | |
837 | return i801_block_transaction_by_block(priv, data, read_write, command); | |
838 | else | |
839 | return i801_block_transaction_byte_by_byte(priv, data, read_write, command); | |
840 | } | |
841 | ||
842 | static int i801_i2c_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data, | |
843 | u8 addr, u8 hstcmd, char read_write, int command) | |
844 | { | |
845 | int result; | |
846 | u8 hostc; | |
847 | ||
848 | if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) | |
849 | return -EPROTO; | |
850 | /* | |
851 | * NB: page 240 of ICH5 datasheet shows that the R/#W bit should be cleared here, | |
852 | * even when reading. However if SPD Write Disable is set (Lynx Point and later), | |
853 | * the read will fail if we don't set the R/#W bit. | |
854 | */ | |
855 | i801_set_hstadd(priv, addr, | |
856 | priv->original_hstcfg & SMBHSTCFG_SPD_WD ? read_write : I2C_SMBUS_WRITE); | |
857 | ||
858 | /* NB: page 240 of ICH5 datasheet shows that DATA1 is the cmd field when reading */ | |
859 | if (read_write == I2C_SMBUS_READ) | |
4a3f77ea | 860 | iowrite8(hstcmd, SMBHSTDAT1(priv)); |
6ff9d46c | 861 | else |
4a3f77ea | 862 | iowrite8(hstcmd, SMBHSTCMD(priv)); |
6ff9d46c HK |
863 | |
864 | if (read_write == I2C_SMBUS_WRITE) { | |
865 | /* set I2C_EN bit in configuration register */ | |
866 | pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); | |
867 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); | |
868 | } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { | |
869 | pci_err(priv->pci_dev, "I2C block read is unsupported!\n"); | |
870 | return -EOPNOTSUPP; | |
7edcb9ab OR |
871 | } |
872 | ||
6ff9d46c HK |
873 | /* Block buffer isn't supported for I2C block transactions */ |
874 | result = i801_block_transaction_byte_by_byte(priv, data, read_write, command); | |
7edcb9ab | 875 | |
6ff9d46c HK |
876 | /* restore saved configuration register value */ |
877 | if (read_write == I2C_SMBUS_WRITE) | |
0cd96eb0 | 878 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); |
6ff9d46c | 879 | |
1da177e4 LT |
880 | return result; |
881 | } | |
882 | ||
97140342 | 883 | /* Return negative errno on error. */ |
3fb21c64 | 884 | static s32 i801_access(struct i2c_adapter *adap, u16 addr, |
1da177e4 | 885 | unsigned short flags, char read_write, u8 command, |
3fb21c64 | 886 | int size, union i2c_smbus_data *data) |
1da177e4 | 887 | { |
a3989dc0 | 888 | int hwpec, ret; |
0cd96eb0 | 889 | struct i801_priv *priv = i2c_get_adapdata(adap); |
1da177e4 | 890 | |
f707d6b9 | 891 | if (priv->acpi_reserved) |
a7ae8195 | 892 | return -EBUSY; |
a7ae8195 | 893 | |
a7401ca5 JN |
894 | pm_runtime_get_sync(&priv->pci_dev->dev); |
895 | ||
1f760b87 HK |
896 | ret = i801_check_pre(priv); |
897 | if (ret) | |
898 | goto out; | |
899 | ||
0cd96eb0 | 900 | hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) |
e8aac4a9 JD |
901 | && size != I2C_SMBUS_QUICK |
902 | && size != I2C_SMBUS_I2C_BLOCK_DATA; | |
1da177e4 | 903 | |
ca8b9e32 | 904 | if (hwpec) /* enable/disable hardware PEC */ |
4a3f77ea | 905 | iowrite8(ioread8(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); |
ca8b9e32 | 906 | else |
4a3f77ea | 907 | iowrite8(ioread8(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), |
0cd96eb0 | 908 | SMBAUXCTL(priv)); |
e8aac4a9 | 909 | |
6ff9d46c HK |
910 | if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_BLOCK_PROC_CALL) |
911 | ret = i801_smbus_block_transaction(priv, data, addr, command, read_write, size); | |
912 | else if (size == I2C_SMBUS_I2C_BLOCK_DATA) | |
913 | ret = i801_i2c_block_transaction(priv, data, addr, command, read_write, size); | |
7edcb9ab | 914 | else |
24592482 | 915 | ret = i801_simple_transaction(priv, data, addr, command, read_write, size); |
1da177e4 | 916 | |
de461a26 HK |
917 | ret = i801_check_post(priv, ret); |
918 | ||
c79cfbac | 919 | /* Some BIOSes don't like it when PEC is enabled at reboot or resume |
63fd342f HK |
920 | * time, so we forcibly disable it after every transaction. |
921 | */ | |
922 | if (hwpec) | |
4a3f77ea | 923 | iowrite8(ioread8(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv)); |
1f760b87 | 924 | out: |
4f7275fc HK |
925 | /* |
926 | * Unlock the SMBus device for use by BIOS/ACPI, | |
927 | * and clear status flags if not done already. | |
928 | */ | |
4a3f77ea | 929 | iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv)); |
065b6211 | 930 | |
a7401ca5 JN |
931 | pm_runtime_mark_last_busy(&priv->pci_dev->dev); |
932 | pm_runtime_put_autosuspend(&priv->pci_dev->dev); | |
933 | return ret; | |
1da177e4 LT |
934 | } |
935 | ||
936 | ||
937 | static u32 i801_func(struct i2c_adapter *adapter) | |
938 | { | |
0cd96eb0 DW |
939 | struct i801_priv *priv = i2c_get_adapdata(adapter); |
940 | ||
1da177e4 | 941 | return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | |
369f6f4a | 942 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | |
55b6f82e | 943 | I2C_FUNC_SMBUS_PROC_CALL | |
369f6f4a | 944 | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | |
0cd96eb0 | 945 | ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | |
315cd67c AS |
946 | ((priv->features & FEATURE_BLOCK_PROC) ? |
947 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL : 0) | | |
0cd96eb0 | 948 | ((priv->features & FEATURE_I2C_BLOCK_READ) ? |
7b0ed334 BT |
949 | I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | |
950 | ((priv->features & FEATURE_HOST_NOTIFY) ? | |
951 | I2C_FUNC_SMBUS_HOST_NOTIFY : 0); | |
952 | } | |
953 | ||
4d5538f5 | 954 | static void i801_enable_host_notify(struct i2c_adapter *adapter) |
7b0ed334 BT |
955 | { |
956 | struct i801_priv *priv = i2c_get_adapdata(adapter); | |
957 | ||
958 | if (!(priv->features & FEATURE_HOST_NOTIFY)) | |
4d5538f5 | 959 | return; |
7b0ed334 | 960 | |
03a976c9 JN |
961 | /* |
962 | * Enable host notify interrupt and block the generation of interrupt | |
963 | * from the SMB_ALERT signal because the driver does not support | |
964 | * SMBus Alert. | |
965 | */ | |
4a3f77ea | 966 | iowrite8(SMBSLVCMD_HST_NTFY_INTREN | SMBSLVCMD_SMBALERT_DISABLE | |
03a976c9 | 967 | priv->original_slvcmd, SMBSLVCMD(priv)); |
22e94bd6 | 968 | |
7b0ed334 | 969 | /* clear Host Notify bit to allow a new notification */ |
4a3f77ea | 970 | iowrite8(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); |
1da177e4 LT |
971 | } |
972 | ||
22e94bd6 BT |
973 | static void i801_disable_host_notify(struct i801_priv *priv) |
974 | { | |
975 | if (!(priv->features & FEATURE_HOST_NOTIFY)) | |
976 | return; | |
977 | ||
4a3f77ea | 978 | iowrite8(priv->original_slvcmd, SMBSLVCMD(priv)); |
22e94bd6 BT |
979 | } |
980 | ||
8f9082c5 | 981 | static const struct i2c_algorithm smbus_algorithm = { |
1da177e4 LT |
982 | .smbus_xfer = i801_access, |
983 | .functionality = i801_func, | |
984 | }; | |
985 | ||
41acd4b0 HK |
986 | #define FEATURES_ICH4 (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER | \ |
987 | FEATURE_HOST_NOTIFY) | |
ea4f3297 HK |
988 | #define FEATURES_ICH5 (FEATURES_ICH4 | FEATURE_BLOCK_PROC | \ |
989 | FEATURE_I2C_BLOCK_READ | FEATURE_IRQ) | |
41acd4b0 | 990 | |
392debf1 | 991 | static const struct pci_device_id i801_ids[] = { |
eb9c18bf JN |
992 | { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, |
993 | { PCI_DEVICE_DATA(INTEL, 82801AB_3, 0) }, | |
994 | { PCI_DEVICE_DATA(INTEL, 82801BA_2, 0) }, | |
995 | { PCI_DEVICE_DATA(INTEL, 82801CA_3, FEATURE_HOST_NOTIFY) }, | |
996 | { PCI_DEVICE_DATA(INTEL, 82801DB_3, FEATURES_ICH4) }, | |
997 | { PCI_DEVICE_DATA(INTEL, 82801EB_3, FEATURES_ICH5) }, | |
998 | { PCI_DEVICE_DATA(INTEL, ESB_4, FEATURES_ICH5) }, | |
999 | { PCI_DEVICE_DATA(INTEL, ICH6_16, FEATURES_ICH5) }, | |
1000 | { PCI_DEVICE_DATA(INTEL, ICH7_17, FEATURES_ICH5) }, | |
1001 | { PCI_DEVICE_DATA(INTEL, ESB2_17, FEATURES_ICH5) }, | |
1002 | { PCI_DEVICE_DATA(INTEL, ICH8_5, FEATURES_ICH5) }, | |
1003 | { PCI_DEVICE_DATA(INTEL, ICH9_6, FEATURES_ICH5) }, | |
1004 | { PCI_DEVICE_DATA(INTEL, EP80579_1, FEATURES_ICH5) }, | |
1005 | { PCI_DEVICE_DATA(INTEL, ICH10_4, FEATURES_ICH5) }, | |
1006 | { PCI_DEVICE_DATA(INTEL, ICH10_5, FEATURES_ICH5) }, | |
1007 | { PCI_DEVICE_DATA(INTEL, 5_3400_SERIES_SMBUS, FEATURES_ICH5) }, | |
1008 | { PCI_DEVICE_DATA(INTEL, COUGARPOINT_SMBUS, FEATURES_ICH5) }, | |
1009 | { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS, FEATURES_ICH5) }, | |
1010 | { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF0, FEATURES_ICH5 | FEATURE_IDF) }, | |
1011 | { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF1, FEATURES_ICH5 | FEATURE_IDF) }, | |
1012 | { PCI_DEVICE_DATA(INTEL, PATSBURG_SMBUS_IDF2, FEATURES_ICH5 | FEATURE_IDF) }, | |
1013 | { PCI_DEVICE_DATA(INTEL, DH89XXCC_SMBUS, FEATURES_ICH5) }, | |
1014 | { PCI_DEVICE_DATA(INTEL, PANTHERPOINT_SMBUS, FEATURES_ICH5) }, | |
1015 | { PCI_DEVICE_DATA(INTEL, LYNXPOINT_SMBUS, FEATURES_ICH5) }, | |
1016 | { PCI_DEVICE_DATA(INTEL, LYNXPOINT_LP_SMBUS, FEATURES_ICH5) }, | |
1017 | { PCI_DEVICE_DATA(INTEL, AVOTON_SMBUS, FEATURES_ICH5) }, | |
1018 | { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS, FEATURES_ICH5) }, | |
1019 | { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS0, FEATURES_ICH5 | FEATURE_IDF) }, | |
1020 | { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS1, FEATURES_ICH5 | FEATURE_IDF) }, | |
1021 | { PCI_DEVICE_DATA(INTEL, WELLSBURG_SMBUS_MS2, FEATURES_ICH5 | FEATURE_IDF) }, | |
1022 | { PCI_DEVICE_DATA(INTEL, COLETOCREEK_SMBUS, FEATURES_ICH5) }, | |
1023 | { PCI_DEVICE_DATA(INTEL, GEMINILAKE_SMBUS, FEATURES_ICH5) }, | |
1024 | { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_SMBUS, FEATURES_ICH5) }, | |
1025 | { PCI_DEVICE_DATA(INTEL, WILDCATPOINT_LP_SMBUS, FEATURES_ICH5) }, | |
1026 | { PCI_DEVICE_DATA(INTEL, BAYTRAIL_SMBUS, FEATURES_ICH5) }, | |
1027 | { PCI_DEVICE_DATA(INTEL, BRASWELL_SMBUS, FEATURES_ICH5) }, | |
1028 | { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1029 | { PCI_DEVICE_DATA(INTEL, SUNRISEPOINT_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1030 | { PCI_DEVICE_DATA(INTEL, CDF_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1031 | { PCI_DEVICE_DATA(INTEL, DNV_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1032 | { PCI_DEVICE_DATA(INTEL, EBG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1033 | { PCI_DEVICE_DATA(INTEL, BROXTON_SMBUS, FEATURES_ICH5) }, | |
1034 | { PCI_DEVICE_DATA(INTEL, LEWISBURG_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1035 | { PCI_DEVICE_DATA(INTEL, LEWISBURG_SSKU_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1036 | { PCI_DEVICE_DATA(INTEL, KABYLAKE_PCH_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1037 | { PCI_DEVICE_DATA(INTEL, CANNONLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1038 | { PCI_DEVICE_DATA(INTEL, CANNONLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1039 | { PCI_DEVICE_DATA(INTEL, ICELAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1040 | { PCI_DEVICE_DATA(INTEL, ICELAKE_N_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1041 | { PCI_DEVICE_DATA(INTEL, COMETLAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1042 | { PCI_DEVICE_DATA(INTEL, COMETLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1043 | { PCI_DEVICE_DATA(INTEL, COMETLAKE_V_SMBUS, FEATURES_ICH5 | FEATURE_TCO_SPT) }, | |
1044 | { PCI_DEVICE_DATA(INTEL, ELKHART_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1045 | { PCI_DEVICE_DATA(INTEL, TIGERLAKE_LP_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1046 | { PCI_DEVICE_DATA(INTEL, TIGERLAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1047 | { PCI_DEVICE_DATA(INTEL, JASPER_LAKE_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1048 | { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1049 | { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1050 | { PCI_DEVICE_DATA(INTEL, ALDER_LAKE_M_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1051 | { PCI_DEVICE_DATA(INTEL, RAPTOR_LAKE_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1052 | { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
e755ef00 | 1053 | { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, |
bcfc2ab7 | 1054 | { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, |
8c56f9ef | 1055 | { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, |
f0eda4dd | 1056 | { PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, |
bd492b58 JN |
1057 | { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, |
1058 | { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, | |
1da177e4 LT |
1059 | { 0, } |
1060 | }; | |
1061 | ||
3fb21c64 | 1062 | MODULE_DEVICE_TABLE(pci, i801_ids); |
1da177e4 | 1063 | |
8eacfceb | 1064 | #if defined CONFIG_X86 && defined CONFIG_DMI |
355b1513 | 1065 | static unsigned char apanel_addr __ro_after_init; |
1561bfe5 JD |
1066 | |
1067 | /* Scan the system ROM for the signature "FJKEYINF" */ | |
1068 | static __init const void __iomem *bios_signature(const void __iomem *bios) | |
1069 | { | |
1070 | ssize_t offset; | |
1071 | const unsigned char signature[] = "FJKEYINF"; | |
1072 | ||
1073 | for (offset = 0; offset < 0x10000; offset += 0x10) { | |
1074 | if (check_signature(bios + offset, signature, | |
1075 | sizeof(signature)-1)) | |
1076 | return bios + offset; | |
1077 | } | |
1078 | return NULL; | |
1079 | } | |
1080 | ||
1081 | static void __init input_apanel_init(void) | |
1082 | { | |
1083 | void __iomem *bios; | |
1084 | const void __iomem *p; | |
1085 | ||
1086 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | |
1087 | p = bios_signature(bios); | |
1088 | if (p) { | |
1089 | /* just use the first address */ | |
1090 | apanel_addr = readb(p + 8 + 3) >> 1; | |
1091 | } | |
1092 | iounmap(bios); | |
1093 | } | |
1561bfe5 | 1094 | |
fa5bfab7 HG |
1095 | struct dmi_onboard_device_info { |
1096 | const char *name; | |
1097 | u8 type; | |
1098 | unsigned short i2c_addr; | |
1099 | const char *i2c_type; | |
1100 | }; | |
1101 | ||
0b255e92 | 1102 | static const struct dmi_onboard_device_info dmi_devices[] = { |
fa5bfab7 HG |
1103 | { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" }, |
1104 | { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" }, | |
1105 | { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" }, | |
1106 | }; | |
1107 | ||
0b255e92 BP |
1108 | static void dmi_check_onboard_device(u8 type, const char *name, |
1109 | struct i2c_adapter *adap) | |
fa5bfab7 HG |
1110 | { |
1111 | int i; | |
1112 | struct i2c_board_info info; | |
1113 | ||
1114 | for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) { | |
1115 | /* & ~0x80, ignore enabled/disabled bit */ | |
1116 | if ((type & ~0x80) != dmi_devices[i].type) | |
1117 | continue; | |
faabd47f | 1118 | if (strcasecmp(name, dmi_devices[i].name)) |
fa5bfab7 HG |
1119 | continue; |
1120 | ||
1121 | memset(&info, 0, sizeof(struct i2c_board_info)); | |
1122 | info.addr = dmi_devices[i].i2c_addr; | |
ea1558ce | 1123 | strscpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE); |
41d06630 | 1124 | i2c_new_client_device(adap, &info); |
fa5bfab7 HG |
1125 | break; |
1126 | } | |
1127 | } | |
1128 | ||
1129 | /* We use our own function to check for onboard devices instead of | |
1130 | dmi_find_device() as some buggy BIOS's have the devices we are interested | |
1131 | in marked as disabled */ | |
0b255e92 | 1132 | static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) |
fa5bfab7 HG |
1133 | { |
1134 | int i, count; | |
1135 | ||
ecaaeff9 | 1136 | if (dm->type != DMI_ENTRY_ONBOARD_DEVICE) |
fa5bfab7 HG |
1137 | return; |
1138 | ||
1139 | count = (dm->length - sizeof(struct dmi_header)) / 2; | |
1140 | for (i = 0; i < count; i++) { | |
1141 | const u8 *d = (char *)(dm + 1) + (i * 2); | |
1142 | const char *name = ((char *) dm) + dm->length; | |
1143 | u8 type = d[0]; | |
1144 | u8 s = d[1]; | |
1145 | ||
1146 | if (!s) | |
1147 | continue; | |
1148 | s--; | |
1149 | while (s > 0 && name[0]) { | |
1150 | name += strlen(name) + 1; | |
1151 | s--; | |
1152 | } | |
1153 | if (name[0] == 0) /* Bogus string reference */ | |
1154 | continue; | |
1155 | ||
1156 | dmi_check_onboard_device(type, name, adap); | |
1157 | } | |
1158 | } | |
fa5bfab7 | 1159 | |
d08cac0a WS |
1160 | /* Register optional targets */ |
1161 | static void i801_probe_optional_targets(struct i801_priv *priv) | |
e7198fbf | 1162 | { |
d08cac0a | 1163 | /* Only register targets on main SMBus channel */ |
e7198fbf JD |
1164 | if (priv->features & FEATURE_IDF) |
1165 | return; | |
1166 | ||
e7198fbf | 1167 | if (apanel_addr) { |
8d83973e HK |
1168 | struct i2c_board_info info = { |
1169 | .addr = apanel_addr, | |
1170 | .type = "fujitsu_apanel", | |
1171 | }; | |
e7198fbf | 1172 | |
41d06630 | 1173 | i2c_new_client_device(&priv->adapter, &info); |
e7198fbf | 1174 | } |
8eacfceb | 1175 | |
e7198fbf JD |
1176 | if (dmi_name_in_vendors("FUJITSU")) |
1177 | dmi_walk(dmi_check_onboard_devices, &priv->adapter); | |
19b07cb4 | 1178 | |
01590f36 | 1179 | /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ |
9c535237 | 1180 | #ifdef CONFIG_I2C_I801_MUX |
80e56b86 | 1181 | if (!priv->mux_pdev) |
01590f36 | 1182 | #endif |
4d6d35d3 | 1183 | i2c_register_spd_write_enable(&priv->adapter); |
e7198fbf | 1184 | } |
8eacfceb JD |
1185 | #else |
1186 | static void __init input_apanel_init(void) {} | |
d08cac0a | 1187 | static void i801_probe_optional_targets(struct i801_priv *priv) {} |
8eacfceb | 1188 | #endif /* CONFIG_X86 && CONFIG_DMI */ |
e7198fbf | 1189 | |
9c535237 | 1190 | #ifdef CONFIG_I2C_I801_MUX |
3ad7ea18 JD |
1191 | static struct i801_mux_config i801_mux_config_asus_z8_d12 = { |
1192 | .gpio_chip = "gpio_ich", | |
1193 | .values = { 0x02, 0x03 }, | |
1194 | .n_values = 2, | |
3ad7ea18 JD |
1195 | .gpios = { 52, 53 }, |
1196 | .n_gpios = 2, | |
1197 | }; | |
1198 | ||
1199 | static struct i801_mux_config i801_mux_config_asus_z8_d18 = { | |
1200 | .gpio_chip = "gpio_ich", | |
1201 | .values = { 0x02, 0x03, 0x01 }, | |
1202 | .n_values = 3, | |
3ad7ea18 JD |
1203 | .gpios = { 52, 53 }, |
1204 | .n_gpios = 2, | |
1205 | }; | |
1206 | ||
0b255e92 | 1207 | static const struct dmi_system_id mux_dmi_table[] = { |
3ad7ea18 JD |
1208 | { |
1209 | .matches = { | |
1210 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1211 | DMI_MATCH(DMI_BOARD_NAME, "Z8NA-D6(C)"), | |
1212 | }, | |
1213 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1214 | }, | |
1215 | { | |
1216 | .matches = { | |
1217 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1218 | DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)E-D12(X)"), | |
1219 | }, | |
1220 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1221 | }, | |
1222 | { | |
1223 | .matches = { | |
1224 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1225 | DMI_MATCH(DMI_BOARD_NAME, "Z8NH-D12"), | |
1226 | }, | |
1227 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1228 | }, | |
1229 | { | |
1230 | .matches = { | |
1231 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1232 | DMI_MATCH(DMI_BOARD_NAME, "Z8PH-D12/IFB"), | |
1233 | }, | |
1234 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1235 | }, | |
1236 | { | |
1237 | .matches = { | |
1238 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1239 | DMI_MATCH(DMI_BOARD_NAME, "Z8NR-D12"), | |
1240 | }, | |
1241 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1242 | }, | |
1243 | { | |
1244 | .matches = { | |
1245 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1246 | DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)H-D12"), | |
1247 | }, | |
1248 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1249 | }, | |
1250 | { | |
1251 | .matches = { | |
1252 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1253 | DMI_MATCH(DMI_BOARD_NAME, "Z8PG-D18"), | |
1254 | }, | |
1255 | .driver_data = &i801_mux_config_asus_z8_d18, | |
1256 | }, | |
1257 | { | |
1258 | .matches = { | |
1259 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1260 | DMI_MATCH(DMI_BOARD_NAME, "Z8PE-D18"), | |
1261 | }, | |
1262 | .driver_data = &i801_mux_config_asus_z8_d18, | |
1263 | }, | |
1264 | { | |
1265 | .matches = { | |
1266 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | |
1267 | DMI_MATCH(DMI_BOARD_NAME, "Z8PS-D12"), | |
1268 | }, | |
1269 | .driver_data = &i801_mux_config_asus_z8_d12, | |
1270 | }, | |
1271 | { } | |
1272 | }; | |
1273 | ||
893fef0b HK |
1274 | static int i801_notifier_call(struct notifier_block *nb, unsigned long action, |
1275 | void *data) | |
1276 | { | |
1277 | struct i801_priv *priv = container_of(nb, struct i801_priv, mux_notifier_block); | |
1278 | struct device *dev = data; | |
1279 | ||
1280 | if (action != BUS_NOTIFY_ADD_DEVICE || | |
1281 | dev->type != &i2c_adapter_type || | |
1282 | i2c_root_adapter(dev) != &priv->adapter) | |
1283 | return NOTIFY_DONE; | |
1284 | ||
1285 | /* Call i2c_register_spd for muxed child segments */ | |
4d6d35d3 | 1286 | i2c_register_spd_write_enable(to_i2c_adapter(dev)); |
893fef0b HK |
1287 | |
1288 | return NOTIFY_OK; | |
1289 | } | |
1290 | ||
3ad7ea18 | 1291 | /* Setup multiplexing if needed */ |
4c591063 | 1292 | static void i801_add_mux(struct i801_priv *priv) |
3ad7ea18 JD |
1293 | { |
1294 | struct device *dev = &priv->adapter.dev; | |
1295 | const struct i801_mux_config *mux_config; | |
3ad7ea18 | 1296 | struct i2c_mux_gpio_platform_data gpio_data; |
d308dfbf | 1297 | struct gpiod_lookup_table *lookup; |
80e56b86 | 1298 | const struct dmi_system_id *id; |
5581b416 | 1299 | int i; |
3ad7ea18 | 1300 | |
80e56b86 HK |
1301 | id = dmi_first_match(mux_dmi_table); |
1302 | if (!id) | |
4c591063 | 1303 | return; |
80e56b86 HK |
1304 | |
1305 | mux_config = id->driver_data; | |
3ad7ea18 | 1306 | |
3ad7ea18 JD |
1307 | /* Prepare the platform data */ |
1308 | memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data)); | |
1309 | gpio_data.parent = priv->adapter.nr; | |
1310 | gpio_data.values = mux_config->values; | |
1311 | gpio_data.n_values = mux_config->n_values; | |
3ad7ea18 JD |
1312 | gpio_data.idle = I2C_MUX_GPIO_NO_IDLE; |
1313 | ||
d308dfbf LW |
1314 | /* Register GPIO descriptor lookup table */ |
1315 | lookup = devm_kzalloc(dev, | |
0b3ea2a0 | 1316 | struct_size(lookup, table, mux_config->n_gpios + 1), |
d308dfbf LW |
1317 | GFP_KERNEL); |
1318 | if (!lookup) | |
4c591063 | 1319 | return; |
d308dfbf | 1320 | lookup->dev_id = "i2c-mux-gpio"; |
4c591063 HK |
1321 | for (i = 0; i < mux_config->n_gpios; i++) |
1322 | lookup->table[i] = GPIO_LOOKUP(mux_config->gpio_chip, | |
1323 | mux_config->gpios[i], "mux", 0); | |
d308dfbf | 1324 | gpiod_add_lookup_table(lookup); |
d308dfbf | 1325 | |
893fef0b HK |
1326 | priv->mux_notifier_block.notifier_call = i801_notifier_call; |
1327 | if (bus_register_notifier(&i2c_bus_type, &priv->mux_notifier_block)) | |
1328 | return; | |
d308dfbf LW |
1329 | /* |
1330 | * Register the mux device, we use PLATFORM_DEVID_NONE here | |
1331 | * because since we are referring to the GPIO chip by name we are | |
1332 | * anyways in deep trouble if there is more than one of these | |
1333 | * devices, and there should likely only be one platform controller | |
1334 | * hub. | |
1335 | */ | |
3ad7ea18 | 1336 | priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio", |
d308dfbf | 1337 | PLATFORM_DEVID_NONE, &gpio_data, |
3ad7ea18 JD |
1338 | sizeof(struct i2c_mux_gpio_platform_data)); |
1339 | if (IS_ERR(priv->mux_pdev)) { | |
d308dfbf | 1340 | gpiod_remove_lookup_table(lookup); |
ceb013b2 | 1341 | devm_kfree(dev, lookup); |
3ad7ea18 | 1342 | dev_err(dev, "Failed to register i2c-mux-gpio device\n"); |
ceb013b2 HK |
1343 | } else { |
1344 | priv->lookup = lookup; | |
3ad7ea18 | 1345 | } |
3ad7ea18 JD |
1346 | } |
1347 | ||
0b255e92 | 1348 | static void i801_del_mux(struct i801_priv *priv) |
3ad7ea18 | 1349 | { |
893fef0b | 1350 | bus_unregister_notifier(&i2c_bus_type, &priv->mux_notifier_block); |
5581b416 | 1351 | platform_device_unregister(priv->mux_pdev); |
926e6b2c | 1352 | gpiod_remove_lookup_table(priv->lookup); |
3ad7ea18 | 1353 | } |
3ad7ea18 | 1354 | #else |
4c591063 | 1355 | static inline void i801_add_mux(struct i801_priv *priv) { } |
3ad7ea18 | 1356 | static inline void i801_del_mux(struct i801_priv *priv) { } |
3ad7ea18 JD |
1357 | #endif |
1358 | ||
b84398d6 | 1359 | static struct platform_device * |
4810603c | 1360 | i801_add_tco_spt(struct pci_dev *pci_dev, struct resource *tco_res) |
94246930 | 1361 | { |
2352b05f HK |
1362 | static const struct itco_wdt_platform_data pldata = { |
1363 | .name = "Intel PCH", | |
1364 | .version = 4, | |
1365 | }; | |
b84398d6 | 1366 | struct resource *res; |
5c7b9167 | 1367 | int ret; |
94246930 | 1368 | |
94246930 MW |
1369 | /* |
1370 | * We must access the NO_REBOOT bit over the Primary to Sideband | |
5c7b9167 | 1371 | * (P2SB) bridge. |
94246930 | 1372 | */ |
94246930 | 1373 | |
04bbb97d | 1374 | res = &tco_res[1]; |
5c7b9167 AS |
1375 | ret = p2sb_bar(pci_dev->bus, 0, res); |
1376 | if (ret) | |
1377 | return ERR_PTR(ret); | |
1378 | ||
851a1511 | 1379 | if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS) |
5c7b9167 | 1380 | res->start += SBREG_SMBCTRL_DNV; |
851a1511 | 1381 | else |
5c7b9167 | 1382 | res->start += SBREG_SMBCTRL; |
851a1511 | 1383 | |
94246930 | 1384 | res->end = res->start + 3; |
94246930 | 1385 | |
b84398d6 | 1386 | return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, |
2352b05f | 1387 | tco_res, 2, &pldata, sizeof(pldata)); |
b84398d6 MW |
1388 | } |
1389 | ||
b84398d6 | 1390 | static struct platform_device * |
4810603c | 1391 | i801_add_tco_cnl(struct pci_dev *pci_dev, struct resource *tco_res) |
b84398d6 | 1392 | { |
2352b05f HK |
1393 | static const struct itco_wdt_platform_data pldata = { |
1394 | .name = "Intel PCH", | |
1395 | .version = 6, | |
1396 | }; | |
1397 | ||
1398 | return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1, | |
1399 | tco_res, 1, &pldata, sizeof(pldata)); | |
b84398d6 MW |
1400 | } |
1401 | ||
1402 | static void i801_add_tco(struct i801_priv *priv) | |
1403 | { | |
b84398d6 | 1404 | struct pci_dev *pci_dev = priv->pci_dev; |
04bbb97d MW |
1405 | struct resource tco_res[2], *res; |
1406 | u32 tco_base, tco_ctl; | |
b84398d6 MW |
1407 | |
1408 | /* If we have ACPI based watchdog use that instead */ | |
1409 | if (acpi_has_watchdog()) | |
94246930 | 1410 | return; |
94246930 | 1411 | |
b84398d6 | 1412 | if (!(priv->features & (FEATURE_TCO_SPT | FEATURE_TCO_CNL))) |
94246930 | 1413 | return; |
94246930 | 1414 | |
b84398d6 MW |
1415 | pci_read_config_dword(pci_dev, TCOBASE, &tco_base); |
1416 | pci_read_config_dword(pci_dev, TCOCTL, &tco_ctl); | |
1417 | if (!(tco_ctl & TCOCTL_EN)) | |
1418 | return; | |
1419 | ||
1420 | memset(tco_res, 0, sizeof(tco_res)); | |
b84398d6 | 1421 | /* |
04bbb97d MW |
1422 | * Always populate the main iTCO IO resource here. The second entry |
1423 | * for NO_REBOOT MMIO is filled by the SPT specific function. | |
b84398d6 | 1424 | */ |
04bbb97d MW |
1425 | res = &tco_res[0]; |
1426 | res->start = tco_base & ~1; | |
1427 | res->end = res->start + 32 - 1; | |
b84398d6 MW |
1428 | res->flags = IORESOURCE_IO; |
1429 | ||
b84398d6 | 1430 | if (priv->features & FEATURE_TCO_CNL) |
4810603c | 1431 | priv->tco_pdev = i801_add_tco_cnl(pci_dev, tco_res); |
b84398d6 | 1432 | else |
4810603c | 1433 | priv->tco_pdev = i801_add_tco_spt(pci_dev, tco_res); |
b84398d6 MW |
1434 | |
1435 | if (IS_ERR(priv->tco_pdev)) | |
9d515bf7 | 1436 | pci_warn(pci_dev, "failed to create iTCO device\n"); |
94246930 MW |
1437 | } |
1438 | ||
a7ae8195 | 1439 | #ifdef CONFIG_ACPI |
7fd6d98b MW |
1440 | static bool i801_acpi_is_smbus_ioport(const struct i801_priv *priv, |
1441 | acpi_physical_address address) | |
1442 | { | |
4a3f77ea | 1443 | return address >= pci_resource_start(priv->pci_dev, SMBBAR) && |
7fd6d98b MW |
1444 | address <= pci_resource_end(priv->pci_dev, SMBBAR); |
1445 | } | |
1446 | ||
a7ae8195 MW |
1447 | static acpi_status |
1448 | i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, | |
1449 | u64 *value, void *handler_context, void *region_context) | |
1450 | { | |
1451 | struct i801_priv *priv = handler_context; | |
1452 | struct pci_dev *pdev = priv->pci_dev; | |
1453 | acpi_status status; | |
1454 | ||
1455 | /* | |
1456 | * Once BIOS AML code touches the OpRegion we warn and inhibit any | |
1457 | * further access from the driver itself. This device is now owned | |
1458 | * by the system firmware. | |
1459 | */ | |
f707d6b9 | 1460 | i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT); |
a7ae8195 | 1461 | |
7fd6d98b | 1462 | if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) { |
a7ae8195 MW |
1463 | priv->acpi_reserved = true; |
1464 | ||
9d515bf7 HK |
1465 | pci_warn(pdev, "BIOS is accessing SMBus registers\n"); |
1466 | pci_warn(pdev, "Driver SMBus register access inhibited\n"); | |
a7ae8195 MW |
1467 | |
1468 | /* | |
1469 | * BIOS is accessing the host controller so prevent it from | |
1470 | * suspending automatically from now on. | |
1471 | */ | |
c073b25d | 1472 | pm_runtime_get_sync(&pdev->dev); |
a7ae8195 MW |
1473 | } |
1474 | ||
1475 | if ((function & ACPI_IO_MASK) == ACPI_READ) | |
1476 | status = acpi_os_read_port(address, (u32 *)value, bits); | |
1477 | else | |
1478 | status = acpi_os_write_port(address, (u32)*value, bits); | |
1479 | ||
f707d6b9 | 1480 | i2c_unlock_bus(&priv->adapter, I2C_LOCK_SEGMENT); |
a7ae8195 MW |
1481 | |
1482 | return status; | |
1483 | } | |
1484 | ||
1485 | static int i801_acpi_probe(struct i801_priv *priv) | |
1486 | { | |
4811a411 | 1487 | acpi_handle ah = ACPI_HANDLE(&priv->pci_dev->dev); |
a7ae8195 MW |
1488 | acpi_status status; |
1489 | ||
4811a411 HK |
1490 | status = acpi_install_address_space_handler(ah, ACPI_ADR_SPACE_SYSTEM_IO, |
1491 | i801_acpi_io_handler, NULL, priv); | |
1492 | if (ACPI_SUCCESS(status)) | |
1493 | return 0; | |
a7ae8195 MW |
1494 | |
1495 | return acpi_check_resource_conflict(&priv->pci_dev->resource[SMBBAR]); | |
1496 | } | |
1497 | ||
1498 | static void i801_acpi_remove(struct i801_priv *priv) | |
1499 | { | |
4811a411 | 1500 | acpi_handle ah = ACPI_HANDLE(&priv->pci_dev->dev); |
a7ae8195 | 1501 | |
4811a411 | 1502 | acpi_remove_address_space_handler(ah, ACPI_ADR_SPACE_SYSTEM_IO, i801_acpi_io_handler); |
a7ae8195 MW |
1503 | } |
1504 | #else | |
1505 | static inline int i801_acpi_probe(struct i801_priv *priv) { return 0; } | |
1506 | static inline void i801_acpi_remove(struct i801_priv *priv) { } | |
1507 | #endif | |
1508 | ||
c601610c | 1509 | static void i801_setup_hstcfg(struct i801_priv *priv) |
66d402e2 VR |
1510 | { |
1511 | unsigned char hstcfg = priv->original_hstcfg; | |
1512 | ||
1513 | hstcfg &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ | |
1514 | hstcfg |= SMBHSTCFG_HST_EN; | |
1515 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); | |
66d402e2 VR |
1516 | } |
1517 | ||
3b0e2091 HK |
1518 | static void i801_restore_regs(struct i801_priv *priv) |
1519 | { | |
4a3f77ea | 1520 | iowrite8(priv->original_hstcnt, SMBHSTCNT(priv)); |
3b0e2091 HK |
1521 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); |
1522 | } | |
1523 | ||
0b255e92 | 1524 | static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
1da177e4 | 1525 | { |
d50f2f5d | 1526 | int err, i, bar = SMBBAR; |
0cd96eb0 DW |
1527 | struct i801_priv *priv; |
1528 | ||
1621c59d | 1529 | priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL); |
0cd96eb0 DW |
1530 | if (!priv) |
1531 | return -ENOMEM; | |
1532 | ||
1533 | i2c_set_adapdata(&priv->adapter, priv); | |
1534 | priv->adapter.owner = THIS_MODULE; | |
80e56b86 | 1535 | priv->adapter.class = I2C_CLASS_HWMON; |
0cd96eb0 | 1536 | priv->adapter.algo = &smbus_algorithm; |
8eb5c87a | 1537 | priv->adapter.dev.parent = &dev->dev; |
d8d9919f | 1538 | acpi_use_parent_companion(&priv->adapter.dev); |
8eb5c87a | 1539 | priv->adapter.retries = 3; |
1da177e4 | 1540 | |
0cd96eb0 | 1541 | priv->pci_dev = dev; |
41acd4b0 | 1542 | priv->features = id->driver_data; |
02dd7ae2 | 1543 | |
adff687d JD |
1544 | /* Disable features on user request */ |
1545 | for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { | |
0cd96eb0 | 1546 | if (priv->features & disable_features & (1 << i)) |
9d515bf7 | 1547 | pci_notice(dev, "%s disabled by user\n", i801_feature_names[i]); |
adff687d | 1548 | } |
0cd96eb0 | 1549 | priv->features &= ~disable_features; |
adff687d | 1550 | |
e98a3bc0 HK |
1551 | /* The block process call uses block buffer mode */ |
1552 | if (!(priv->features & FEATURE_BLOCK_BUFFER)) | |
1553 | priv->features &= ~FEATURE_BLOCK_PROC; | |
1554 | ||
65cba48d PS |
1555 | /* |
1556 | * Do not call pcim_enable_device(), because the device has to remain | |
1557 | * enabled on driver detach. See i801_remove() for the reasoning. | |
1558 | */ | |
1559 | err = pci_enable_device(dev); | |
02dd7ae2 | 1560 | if (err) { |
9d515bf7 | 1561 | pci_err(dev, "Failed to enable SMBus PCI device (%d)\n", err); |
fef220da | 1562 | return err; |
02dd7ae2 JD |
1563 | } |
1564 | ||
1565 | /* Determine the address of the SMBus area */ | |
4a3f77ea | 1566 | if (!pci_resource_start(dev, SMBBAR)) { |
9d515bf7 | 1567 | pci_err(dev, "SMBus base address uninitialized, upgrade BIOS\n"); |
fef220da | 1568 | return -ENODEV; |
02dd7ae2 JD |
1569 | } |
1570 | ||
a7ae8195 | 1571 | if (i801_acpi_probe(priv)) |
fef220da | 1572 | return -ENODEV; |
54fb4a05 | 1573 | |
d50f2f5d HK |
1574 | if (pci_resource_flags(dev, SMBBAR_MMIO) & IORESOURCE_MEM) |
1575 | bar = SMBBAR_MMIO; | |
1576 | ||
1577 | priv->smba = pcim_iomap_region(dev, bar, DRV_NAME); | |
4a3f77ea | 1578 | if (IS_ERR(priv->smba)) { |
9d515bf7 | 1579 | pci_err(dev, "Failed to request SMBus region %pr\n", |
d50f2f5d | 1580 | pci_resource_n(dev, bar)); |
a7ae8195 | 1581 | i801_acpi_remove(priv); |
4a3f77ea | 1582 | return PTR_ERR(priv->smba); |
02dd7ae2 JD |
1583 | } |
1584 | ||
9d515bf7 | 1585 | pci_read_config_byte(dev, SMBHSTCFG, &priv->original_hstcfg); |
c601610c | 1586 | i801_setup_hstcfg(priv); |
66d402e2 | 1587 | if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN)) |
9d515bf7 | 1588 | pci_info(dev, "Enabling SMBus device\n"); |
02dd7ae2 | 1589 | |
c601610c | 1590 | if (priv->original_hstcfg & SMBHSTCFG_SMB_SMI_EN) { |
9d515bf7 | 1591 | pci_dbg(dev, "SMBus using interrupt SMI#\n"); |
636752bc DK |
1592 | /* Disable SMBus interrupt feature if SMBus using SMI# */ |
1593 | priv->features &= ~FEATURE_IRQ; | |
636752bc | 1594 | } |
c601610c | 1595 | if (priv->original_hstcfg & SMBHSTCFG_SPD_WD) |
9d515bf7 | 1596 | pci_info(dev, "SPD Write Disable is set\n"); |
1da177e4 | 1597 | |
a0921b6c | 1598 | /* Clear special mode bits */ |
0cd96eb0 | 1599 | if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) |
4a3f77ea | 1600 | iowrite8(ioread8(SMBAUXCTL(priv)) & |
0cd96eb0 | 1601 | ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); |
a0921b6c | 1602 | |
b3b8df97 JD |
1603 | /* Default timeout in interrupt mode: 200 ms */ |
1604 | priv->adapter.timeout = HZ / 5; | |
1605 | ||
6e0c9507 HG |
1606 | if (dev->irq == IRQ_NOTCONNECTED) |
1607 | priv->features &= ~FEATURE_IRQ; | |
1608 | ||
aeb8a3d1 | 1609 | if (priv->features & FEATURE_IRQ) { |
e462aa7e | 1610 | u16 pcists; |
aeb8a3d1 JD |
1611 | |
1612 | /* Complain if an interrupt is already pending */ | |
0d3f1e45 HK |
1613 | pci_read_config_word(priv->pci_dev, PCI_STATUS, &pcists); |
1614 | if (pcists & PCI_STATUS_INTERRUPT) | |
9d515bf7 | 1615 | pci_warn(dev, "An interrupt is pending!\n"); |
aeb8a3d1 JD |
1616 | } |
1617 | ||
636752bc | 1618 | if (priv->features & FEATURE_IRQ) { |
1de93d5d | 1619 | init_completion(&priv->done); |
636752bc | 1620 | |
1621c59d | 1621 | err = devm_request_irq(&dev->dev, dev->irq, i801_isr, |
d4a994f6 | 1622 | IRQF_SHARED, DRV_NAME, priv); |
636752bc | 1623 | if (err) { |
9d515bf7 | 1624 | pci_err(dev, "Failed to allocate irq %d: %d\n", dev->irq, err); |
ae944717 | 1625 | priv->features &= ~FEATURE_IRQ; |
636752bc DK |
1626 | } |
1627 | } | |
9d515bf7 | 1628 | pci_info(dev, "SMBus using %s\n", |
ae944717 | 1629 | priv->features & FEATURE_IRQ ? "PCI interrupt" : "polling"); |
636752bc | 1630 | |
f0c8f0ee HK |
1631 | /* Host notification uses an interrupt */ |
1632 | if (!(priv->features & FEATURE_IRQ)) | |
1633 | priv->features &= ~FEATURE_HOST_NOTIFY; | |
1634 | ||
1635 | /* Remember original Interrupt and Host Notify settings */ | |
4a3f77ea | 1636 | priv->original_hstcnt = ioread8(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL; |
f0c8f0ee | 1637 | if (priv->features & FEATURE_HOST_NOTIFY) |
4a3f77ea | 1638 | priv->original_slvcmd = ioread8(SMBSLVCMD(priv)); |
f0c8f0ee | 1639 | |
94246930 MW |
1640 | i801_add_tco(priv); |
1641 | ||
43457ada HG |
1642 | /* |
1643 | * adapter.name is used by platform code to find the main I801 adapter | |
1644 | * to instantiante i2c_clients, do not change. | |
1645 | */ | |
0cd96eb0 | 1646 | snprintf(priv->adapter.name, sizeof(priv->adapter.name), |
4a3f77ea | 1647 | "SMBus %s adapter at %s", |
43457ada | 1648 | (priv->features & FEATURE_IDF) ? "I801 IDF" : "I801", |
4a3f77ea | 1649 | pci_name(dev)); |
43457ada | 1650 | |
0cd96eb0 | 1651 | err = i2c_add_adapter(&priv->adapter); |
02dd7ae2 | 1652 | if (err) { |
39147845 | 1653 | platform_device_unregister(priv->tco_pdev); |
a7ae8195 | 1654 | i801_acpi_remove(priv); |
3b0e2091 | 1655 | i801_restore_regs(priv); |
fef220da | 1656 | return err; |
02dd7ae2 | 1657 | } |
1561bfe5 | 1658 | |
4d5538f5 | 1659 | i801_enable_host_notify(&priv->adapter); |
7b0ed334 | 1660 | |
3ad7ea18 JD |
1661 | /* We ignore errors - multiplexing is optional */ |
1662 | i801_add_mux(priv); | |
d08cac0a | 1663 | i801_probe_optional_targets(priv); |
1561bfe5 | 1664 | |
0cd96eb0 | 1665 | pci_set_drvdata(dev, priv); |
636752bc | 1666 | |
845b8912 | 1667 | dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE); |
a7401ca5 JN |
1668 | pm_runtime_set_autosuspend_delay(&dev->dev, 1000); |
1669 | pm_runtime_use_autosuspend(&dev->dev); | |
1670 | pm_runtime_put_autosuspend(&dev->dev); | |
1671 | pm_runtime_allow(&dev->dev); | |
1672 | ||
d6fcb3b9 | 1673 | return 0; |
1da177e4 LT |
1674 | } |
1675 | ||
0b255e92 | 1676 | static void i801_remove(struct pci_dev *dev) |
1da177e4 | 1677 | { |
0cd96eb0 DW |
1678 | struct i801_priv *priv = pci_get_drvdata(dev); |
1679 | ||
22e94bd6 | 1680 | i801_disable_host_notify(priv); |
3ad7ea18 | 1681 | i801_del_mux(priv); |
0cd96eb0 | 1682 | i2c_del_adapter(&priv->adapter); |
a7ae8195 | 1683 | i801_acpi_remove(priv); |
636752bc | 1684 | |
94246930 MW |
1685 | platform_device_unregister(priv->tco_pdev); |
1686 | ||
c073b25d HK |
1687 | /* if acpi_reserved is set then usage_count is incremented already */ |
1688 | if (!priv->acpi_reserved) | |
1689 | pm_runtime_get_noresume(&dev->dev); | |
1690 | ||
3b0e2091 HK |
1691 | i801_restore_regs(priv); |
1692 | ||
d6fcb3b9 DR |
1693 | /* |
1694 | * do not call pci_disable_device(dev) since it can cause hard hangs on | |
1695 | * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) | |
1696 | */ | |
1da177e4 LT |
1697 | } |
1698 | ||
f7f6d915 JD |
1699 | static void i801_shutdown(struct pci_dev *dev) |
1700 | { | |
1701 | struct i801_priv *priv = pci_get_drvdata(dev); | |
1702 | ||
f7f6d915 | 1703 | i801_disable_host_notify(priv); |
3b0e2091 HK |
1704 | /* Restore config registers to avoid hard hang on some systems */ |
1705 | i801_restore_regs(priv); | |
f7f6d915 JD |
1706 | } |
1707 | ||
2ee73c48 | 1708 | static int i801_suspend(struct device *dev) |
a5aaea37 | 1709 | { |
811a6e18 | 1710 | struct i801_priv *priv = dev_get_drvdata(dev); |
0cd96eb0 | 1711 | |
d0d0f827 | 1712 | i2c_mark_adapter_suspended(&priv->adapter); |
3b0e2091 HK |
1713 | i801_restore_regs(priv); |
1714 | ||
a5aaea37 JD |
1715 | return 0; |
1716 | } | |
1717 | ||
2ee73c48 | 1718 | static int i801_resume(struct device *dev) |
a5aaea37 | 1719 | { |
7735eeeb | 1720 | struct i801_priv *priv = dev_get_drvdata(dev); |
7b0ed334 | 1721 | |
66d402e2 | 1722 | i801_setup_hstcfg(priv); |
4d5538f5 | 1723 | i801_enable_host_notify(&priv->adapter); |
d0d0f827 | 1724 | i2c_mark_adapter_resumed(&priv->adapter); |
7b0ed334 | 1725 | |
f85da3f5 | 1726 | return 0; |
a5aaea37 | 1727 | } |
a5aaea37 | 1728 | |
a6273e41 | 1729 | static DEFINE_SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume); |
2ee73c48 | 1730 | |
1da177e4 | 1731 | static struct pci_driver i801_driver = { |
d4a994f6 | 1732 | .name = DRV_NAME, |
1da177e4 LT |
1733 | .id_table = i801_ids, |
1734 | .probe = i801_probe, | |
0b255e92 | 1735 | .remove = i801_remove, |
f7f6d915 | 1736 | .shutdown = i801_shutdown, |
2ee73c48 | 1737 | .driver = { |
a6273e41 | 1738 | .pm = pm_sleep_ptr(&i801_pm_ops), |
342530f7 | 1739 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
2ee73c48 | 1740 | }, |
1da177e4 LT |
1741 | }; |
1742 | ||
19b6ffd5 | 1743 | static int __init i2c_i801_init(struct pci_driver *drv) |
1da177e4 | 1744 | { |
6aa1464d JD |
1745 | if (dmi_name_in_vendors("FUJITSU")) |
1746 | input_apanel_init(); | |
19b6ffd5 | 1747 | return pci_register_driver(drv); |
1da177e4 LT |
1748 | } |
1749 | ||
f80531c8 JN |
1750 | MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); |
1751 | MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); | |
1da177e4 LT |
1752 | MODULE_DESCRIPTION("I801 SMBus driver"); |
1753 | MODULE_LICENSE("GPL"); | |
1754 | ||
19b6ffd5 | 1755 | module_driver(i801_driver, i2c_i801_init, pci_unregister_driver); |