diff options
-rw-r--r-- | Documentation/i2c/busses/i2c-i801 | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 99 |
2 files changed, 105 insertions, 7 deletions
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 71f55bbcefc8..615142da4ef6 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 | |||
@@ -38,9 +38,10 @@ Module Parameters | |||
38 | Disable selected features normally supported by the device. This makes it | 38 | Disable selected features normally supported by the device. This makes it |
39 | possible to work around possible driver or hardware bugs if the feature in | 39 | possible to work around possible driver or hardware bugs if the feature in |
40 | question doesn't work as intended for whatever reason. Bit values: | 40 | question doesn't work as intended for whatever reason. Bit values: |
41 | 1 disable SMBus PEC | 41 | 0x01 disable SMBus PEC |
42 | 2 disable the block buffer | 42 | 0x02 disable the block buffer |
43 | 8 disable the I2C block read functionality | 43 | 0x08 disable the I2C block read functionality |
44 | 0x10 don't use interrupts | ||
44 | 45 | ||
45 | 46 | ||
46 | Description | 47 | Description |
@@ -86,6 +87,12 @@ SMBus 2.0 Support | |||
86 | The 82801DB (ICH4) and later chips support several SMBus 2.0 features. | 87 | The 82801DB (ICH4) and later chips support several SMBus 2.0 features. |
87 | 88 | ||
88 | 89 | ||
90 | Interrupt Support | ||
91 | ----------------- | ||
92 | |||
93 | PCI interrupt support is supported on the 82801EB (ICH5) and later chips. | ||
94 | |||
95 | |||
89 | Hidden ICH SMBus | 96 | Hidden ICH SMBus |
90 | ---------------- | 97 | ---------------- |
91 | 98 | ||
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index a1ce4e68b49a..bcce18dfcc39 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -60,10 +60,12 @@ | |||
60 | Block process call transaction no | 60 | Block process call transaction no |
61 | I2C block read transaction yes (doesn't use the block buffer) | 61 | I2C block read transaction yes (doesn't use the block buffer) |
62 | Slave mode no | 62 | Slave mode no |
63 | Interrupt processing yes | ||
63 | 64 | ||
64 | See the file Documentation/i2c/busses/i2c-i801 for details. | 65 | See the file Documentation/i2c/busses/i2c-i801 for details. |
65 | */ | 66 | */ |
66 | 67 | ||
68 | #include <linux/interrupt.h> | ||
67 | #include <linux/module.h> | 69 | #include <linux/module.h> |
68 | #include <linux/pci.h> | 70 | #include <linux/pci.h> |
69 | #include <linux/kernel.h> | 71 | #include <linux/kernel.h> |
@@ -76,6 +78,7 @@ | |||
76 | #include <linux/io.h> | 78 | #include <linux/io.h> |
77 | #include <linux/dmi.h> | 79 | #include <linux/dmi.h> |
78 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
81 | #include <linux/wait.h> | ||
79 | 82 | ||
80 | /* I801 SMBus address offsets */ | 83 | /* I801 SMBus address offsets */ |
81 | #define SMBHSTSTS(p) (0 + (p)->smba) | 84 | #define SMBHSTSTS(p) (0 + (p)->smba) |
@@ -91,8 +94,12 @@ | |||
91 | 94 | ||
92 | /* PCI Address Constants */ | 95 | /* PCI Address Constants */ |
93 | #define SMBBAR 4 | 96 | #define SMBBAR 4 |
97 | #define SMBPCISTS 0x006 | ||
94 | #define SMBHSTCFG 0x040 | 98 | #define SMBHSTCFG 0x040 |
95 | 99 | ||
100 | /* Host status bits for SMBPCISTS */ | ||
101 | #define SMBPCISTS_INTS 0x08 | ||
102 | |||
96 | /* Host configuration bits for SMBHSTCFG */ | 103 | /* Host configuration bits for SMBHSTCFG */ |
97 | #define SMBHSTCFG_HST_EN 1 | 104 | #define SMBHSTCFG_HST_EN 1 |
98 | #define SMBHSTCFG_SMB_SMI_EN 2 | 105 | #define SMBHSTCFG_SMB_SMI_EN 2 |
@@ -155,6 +162,10 @@ struct i801_priv { | |||
155 | unsigned char original_hstcfg; | 162 | unsigned char original_hstcfg; |
156 | struct pci_dev *pci_dev; | 163 | struct pci_dev *pci_dev; |
157 | unsigned int features; | 164 | unsigned int features; |
165 | |||
166 | /* isr processing */ | ||
167 | wait_queue_head_t waitq; | ||
168 | u8 status; | ||
158 | }; | 169 | }; |
159 | 170 | ||
160 | static struct pci_driver i801_driver; | 171 | static struct pci_driver i801_driver; |
@@ -163,6 +174,7 @@ static struct pci_driver i801_driver; | |||
163 | #define FEATURE_BLOCK_BUFFER (1 << 1) | 174 | #define FEATURE_BLOCK_BUFFER (1 << 1) |
164 | #define FEATURE_BLOCK_PROC (1 << 2) | 175 | #define FEATURE_BLOCK_PROC (1 << 2) |
165 | #define FEATURE_I2C_BLOCK_READ (1 << 3) | 176 | #define FEATURE_I2C_BLOCK_READ (1 << 3) |
177 | #define FEATURE_IRQ (1 << 4) | ||
166 | /* Not really a feature, but it's convenient to handle it as such */ | 178 | /* Not really a feature, but it's convenient to handle it as such */ |
167 | #define FEATURE_IDF (1 << 15) | 179 | #define FEATURE_IDF (1 << 15) |
168 | 180 | ||
@@ -171,6 +183,7 @@ static const char *i801_feature_names[] = { | |||
171 | "Block buffer", | 183 | "Block buffer", |
172 | "Block process call", | 184 | "Block process call", |
173 | "I2C block read", | 185 | "I2C block read", |
186 | "Interrupt", | ||
174 | }; | 187 | }; |
175 | 188 | ||
176 | static unsigned int disable_features; | 189 | static unsigned int disable_features; |
@@ -215,7 +228,12 @@ static int i801_check_post(struct i801_priv *priv, int status) | |||
215 | { | 228 | { |
216 | int result = 0; | 229 | int result = 0; |
217 | 230 | ||
218 | /* If the SMBus is still busy, we give up */ | 231 | /* |
232 | * If the SMBus is still busy, we give up | ||
233 | * Note: This timeout condition only happens when using polling | ||
234 | * transactions. For interrupt operation, NAK/timeout is indicated by | ||
235 | * DEV_ERR. | ||
236 | */ | ||
219 | if (unlikely(status < 0)) { | 237 | if (unlikely(status < 0)) { |
220 | dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); | 238 | dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); |
221 | /* try to stop the current command */ | 239 | /* try to stop the current command */ |
@@ -305,6 +323,14 @@ static int i801_transaction(struct i801_priv *priv, int xact) | |||
305 | if (result < 0) | 323 | if (result < 0) |
306 | return result; | 324 | return result; |
307 | 325 | ||
326 | if (priv->features & FEATURE_IRQ) { | ||
327 | outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START, | ||
328 | SMBHSTCNT(priv)); | ||
329 | wait_event(priv->waitq, (status = priv->status)); | ||
330 | priv->status = 0; | ||
331 | return i801_check_post(priv, status); | ||
332 | } | ||
333 | |||
308 | /* the current contents of SMBHSTCNT can be overwritten, since PEC, | 334 | /* the current contents of SMBHSTCNT can be overwritten, since PEC, |
309 | * SMBSCMD are passed in xact */ | 335 | * SMBSCMD are passed in xact */ |
310 | outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); | 336 | outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv)); |
@@ -348,6 +374,44 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, | |||
348 | } | 374 | } |
349 | 375 | ||
350 | /* | 376 | /* |
377 | * i801 signals transaction completion with one of these interrupts: | ||
378 | * INTR - Success | ||
379 | * DEV_ERR - Invalid command, NAK or communication timeout | ||
380 | * BUS_ERR - SMI# transaction collision | ||
381 | * FAILED - transaction was canceled due to a KILL request | ||
382 | * When any of these occur, update ->status and wake up the waitq. | ||
383 | * ->status must be cleared before kicking off the next transaction. | ||
384 | */ | ||
385 | static irqreturn_t i801_isr(int irq, void *dev_id) | ||
386 | { | ||
387 | struct i801_priv *priv = dev_id; | ||
388 | u16 pcists; | ||
389 | u8 status; | ||
390 | |||
391 | /* Confirm this is our interrupt */ | ||
392 | pci_read_config_word(priv->pci_dev, SMBPCISTS, &pcists); | ||
393 | if (!(pcists & SMBPCISTS_INTS)) | ||
394 | return IRQ_NONE; | ||
395 | |||
396 | status = inb_p(SMBHSTSTS(priv)); | ||
397 | if (status != 0x42) | ||
398 | dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status); | ||
399 | |||
400 | /* | ||
401 | * Clear irq sources and report transaction result. | ||
402 | * ->status must be cleared before the next transaction is started. | ||
403 | */ | ||
404 | status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS; | ||
405 | if (status) { | ||
406 | outb_p(status, SMBHSTSTS(priv)); | ||
407 | priv->status |= status; | ||
408 | wake_up(&priv->waitq); | ||
409 | } | ||
410 | |||
411 | return IRQ_HANDLED; | ||
412 | } | ||
413 | |||
414 | /* | ||
351 | * For "byte-by-byte" block transactions: | 415 | * For "byte-by-byte" block transactions: |
352 | * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1 | 416 | * I2C write uses cmd=I801_BLOCK_DATA, I2C_EN=1 |
353 | * I2C read uses cmd=I801_I2C_BLOCK_DATA | 417 | * I2C read uses cmd=I801_I2C_BLOCK_DATA |
@@ -799,6 +863,10 @@ static int __devinit i801_probe(struct pci_dev *dev, | |||
799 | break; | 863 | break; |
800 | } | 864 | } |
801 | 865 | ||
866 | /* IRQ processing only tested on CougarPoint PCH */ | ||
867 | if (dev->device == PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) | ||
868 | priv->features |= FEATURE_IRQ; | ||
869 | |||
802 | /* Disable features on user request */ | 870 | /* Disable features on user request */ |
803 | for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { | 871 | for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { |
804 | if (priv->features & disable_features & (1 << i)) | 872 | if (priv->features & disable_features & (1 << i)) |
@@ -846,16 +914,31 @@ static int __devinit i801_probe(struct pci_dev *dev, | |||
846 | } | 914 | } |
847 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp); | 915 | pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp); |
848 | 916 | ||
849 | if (temp & SMBHSTCFG_SMB_SMI_EN) | 917 | if (temp & SMBHSTCFG_SMB_SMI_EN) { |
850 | dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); | 918 | dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); |
851 | else | 919 | /* Disable SMBus interrupt feature if SMBus using SMI# */ |
920 | priv->features &= ~FEATURE_IRQ; | ||
921 | } else { | ||
852 | dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); | 922 | dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); |
923 | } | ||
853 | 924 | ||
854 | /* Clear special mode bits */ | 925 | /* Clear special mode bits */ |
855 | if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) | 926 | if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) |
856 | outb_p(inb_p(SMBAUXCTL(priv)) & | 927 | outb_p(inb_p(SMBAUXCTL(priv)) & |
857 | ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); | 928 | ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); |
858 | 929 | ||
930 | if (priv->features & FEATURE_IRQ) { | ||
931 | init_waitqueue_head(&priv->waitq); | ||
932 | |||
933 | err = request_irq(dev->irq, i801_isr, IRQF_SHARED, | ||
934 | i801_driver.name, priv); | ||
935 | if (err) { | ||
936 | dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", | ||
937 | dev->irq, err); | ||
938 | goto exit_release; | ||
939 | } | ||
940 | } | ||
941 | |||
859 | /* set up the sysfs linkage to our parent device */ | 942 | /* set up the sysfs linkage to our parent device */ |
860 | priv->adapter.dev.parent = &dev->dev; | 943 | priv->adapter.dev.parent = &dev->dev; |
861 | 944 | ||
@@ -867,14 +950,18 @@ static int __devinit i801_probe(struct pci_dev *dev, | |||
867 | err = i2c_add_adapter(&priv->adapter); | 950 | err = i2c_add_adapter(&priv->adapter); |
868 | if (err) { | 951 | if (err) { |
869 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); | 952 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); |
870 | goto exit_release; | 953 | goto exit_free_irq; |
871 | } | 954 | } |
872 | 955 | ||
873 | i801_probe_optional_slaves(priv); | 956 | i801_probe_optional_slaves(priv); |
874 | 957 | ||
875 | pci_set_drvdata(dev, priv); | 958 | pci_set_drvdata(dev, priv); |
959 | |||
876 | return 0; | 960 | return 0; |
877 | 961 | ||
962 | exit_free_irq: | ||
963 | if (priv->features & FEATURE_IRQ) | ||
964 | free_irq(dev->irq, priv); | ||
878 | exit_release: | 965 | exit_release: |
879 | pci_release_region(dev, SMBBAR); | 966 | pci_release_region(dev, SMBBAR); |
880 | exit: | 967 | exit: |
@@ -888,7 +975,11 @@ static void __devexit i801_remove(struct pci_dev *dev) | |||
888 | 975 | ||
889 | i2c_del_adapter(&priv->adapter); | 976 | i2c_del_adapter(&priv->adapter); |
890 | pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); | 977 | pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); |
978 | |||
979 | if (priv->features & FEATURE_IRQ) | ||
980 | free_irq(dev->irq, priv); | ||
891 | pci_release_region(dev, SMBBAR); | 981 | pci_release_region(dev, SMBBAR); |
982 | |||
892 | pci_set_drvdata(dev, NULL); | 983 | pci_set_drvdata(dev, NULL); |
893 | kfree(priv); | 984 | kfree(priv); |
894 | /* | 985 | /* |