|
9 | 9 | #include <linux/delay.h>
|
10 | 10 | #include <linux/i2c.h>
|
11 | 11 | #include <linux/io.h>
|
| 12 | +#include <linux/iopoll.h> |
12 | 13 | #include <linux/kernel.h>
|
13 | 14 | #include <linux/module.h>
|
14 | 15 | #include <linux/pci.h>
|
|
52 | 53 | #define CTL_UJM BIT(8)
|
53 | 54 | #define CTL_CLK_M GENMASK(7, 0)
|
54 | 55 |
|
| 56 | +/* |
| 57 | + * The hardware (supposedly) has a 25ms timeout for clock stretching, thus |
| 58 | + * use 100ms here which should be plenty. |
| 59 | + */ |
| 60 | +#define PASEMI_TRANSFER_TIMEOUT_MS 100 |
| 61 | + |
55 | 62 | static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
|
56 | 63 | {
|
57 | 64 | dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val);
|
@@ -90,33 +97,43 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)
|
90 | 97 |
|
91 | 98 | static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
|
92 | 99 | {
|
93 |
| - int timeout = 100; |
94 | 100 | unsigned int status;
|
95 | 101 |
|
96 | 102 | if (smbus->use_irq) {
|
97 | 103 | reinit_completion(&smbus->irq_completion);
|
98 | 104 | reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
|
99 |
| - wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100)); |
| 105 | + int ret = wait_for_completion_timeout( |
| 106 | + &smbus->irq_completion, |
| 107 | + msecs_to_jiffies(PASEMI_TRANSFER_TIMEOUT_MS)); |
100 | 108 | reg_write(smbus, REG_IMASK, 0);
|
101 | 109 | status = reg_read(smbus, REG_SMSTA);
|
| 110 | + |
| 111 | + if (ret < 0) { |
| 112 | + dev_err(smbus->dev, |
| 113 | + "Completion wait failed with %d, status 0x%08x\n", |
| 114 | + ret, status); |
| 115 | + return ret; |
| 116 | + } else if (ret == 0) { |
| 117 | + dev_err(smbus->dev, "Timeout, status 0x%08x\n", status); |
| 118 | + return -ETIME; |
| 119 | + } |
102 | 120 | } else {
|
103 |
| - status = reg_read(smbus, REG_SMSTA); |
104 |
| - while (!(status & SMSTA_XEN) && timeout--) { |
105 |
| - msleep(1); |
106 |
| - status = reg_read(smbus, REG_SMSTA); |
| 121 | + int ret = readx_poll_timeout( |
| 122 | + ioread32, smbus->ioaddr + REG_SMSTA, |
| 123 | + status, status & SMSTA_XEN, |
| 124 | + USEC_PER_MSEC, |
| 125 | + USEC_PER_MSEC * PASEMI_TRANSFER_TIMEOUT_MS); |
| 126 | + |
| 127 | + if (ret < 0) { |
| 128 | + dev_err(smbus->dev, "Timeout, status 0x%08x\n", status); |
| 129 | + return -ETIME; |
107 | 130 | }
|
108 | 131 | }
|
109 | 132 |
|
110 | 133 | /* Got NACK? */
|
111 | 134 | if (status & SMSTA_MTN)
|
112 | 135 | return -ENXIO;
|
113 | 136 |
|
114 |
| - if (timeout < 0) { |
115 |
| - dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status); |
116 |
| - reg_write(smbus, REG_SMSTA, status); |
117 |
| - return -ETIME; |
118 |
| - } |
119 |
| - |
120 | 137 | /* Clear XEN */
|
121 | 138 | reg_write(smbus, REG_SMSTA, SMSTA_XEN);
|
122 | 139 |
|
|
0 commit comments