|
Lines 43-55
__FBSDID("$FreeBSD$");
Link Here
|
| 43 |
* See ig4_var.h for locking semantics. |
43 |
* See ig4_var.h for locking semantics. |
| 44 |
*/ |
44 |
*/ |
| 45 |
|
45 |
|
|
|
46 |
#include "opt_acpi.h" |
| 47 |
|
| 46 |
#include <sys/param.h> |
48 |
#include <sys/param.h> |
| 47 |
#include <sys/systm.h> |
49 |
#include <sys/systm.h> |
| 48 |
#include <sys/kernel.h> |
50 |
#include <sys/kernel.h> |
| 49 |
#include <sys/module.h> |
51 |
#include <sys/module.h> |
| 50 |
#include <sys/errno.h> |
52 |
#include <sys/errno.h> |
|
|
53 |
#include <sys/kdb.h> |
| 51 |
#include <sys/lock.h> |
54 |
#include <sys/lock.h> |
| 52 |
#include <sys/mutex.h> |
55 |
#include <sys/mutex.h> |
|
|
56 |
#include <sys/proc.h> |
| 53 |
#include <sys/sx.h> |
57 |
#include <sys/sx.h> |
| 54 |
#include <sys/syslog.h> |
58 |
#include <sys/syslog.h> |
| 55 |
#include <sys/bus.h> |
59 |
#include <sys/bus.h> |
|
Lines 58-63
__FBSDID("$FreeBSD$");
Link Here
|
| 58 |
#include <machine/bus.h> |
62 |
#include <machine/bus.h> |
| 59 |
#include <sys/rman.h> |
63 |
#include <sys/rman.h> |
| 60 |
|
64 |
|
|
|
65 |
#ifdef DEV_ACPI |
| 66 |
#include <contrib/dev/acpica/include/acpi.h> |
| 67 |
#include <contrib/dev/acpica/include/accommon.h> |
| 68 |
#include <dev/acpica/acpivar.h> |
| 69 |
#endif |
| 70 |
|
| 61 |
#include <dev/pci/pcivar.h> |
71 |
#include <dev/pci/pcivar.h> |
| 62 |
#include <dev/pci/pcireg.h> |
72 |
#include <dev/pci/pcireg.h> |
| 63 |
#include <dev/iicbus/iicbus.h> |
73 |
#include <dev/iicbus/iicbus.h> |
|
Lines 70-76
__FBSDID("$FreeBSD$");
Link Here
|
| 70 |
#define TRANS_PCALL 2 |
80 |
#define TRANS_PCALL 2 |
| 71 |
#define TRANS_BLOCK 3 |
81 |
#define TRANS_BLOCK 3 |
| 72 |
|
82 |
|
| 73 |
static void ig4iic_start(void *xdev); |
83 |
#define DO_POLL(sc) (cold || kdb_active || SCHEDULER_STOPPED() || \ |
|
|
84 |
sc->poll || sc->resume) |
| 85 |
|
| 86 |
/* |
| 87 |
* Clock register values calculation formulas and timings are snarfed from |
| 88 |
* Linux driver. |
| 89 |
* *S_SCL_HCNT = IC clock rate * (tHIGH + SDA falling time) - 3 |
| 90 |
* *S_SCL_LCNT = IC clock rate * (tLOW + SCL falling time) - 1 |
| 91 |
* SDA_TX_HOLD = IC clock rate * SDA hold time |
| 92 |
* All results are rounded to nearest. |
| 93 |
* |
| 94 |
* tLOW and tHIGH periods of the SCL clock are taken from I2C specification: |
| 95 |
* Speed mode STD FAST FAST+ HIGH |
| 96 |
* tHIGH 4.0 ns 0.6 ns 0.26 ns 0.06-0.12 ns |
| 97 |
* tLOW 4.7 ns 1.3 ns 0.5 ns 0.16-0.32 ns |
| 98 |
* |
| 99 |
* HIGH Speed mode tHIGH/tLOW values are depend on bus capacitance. |
| 100 |
*/ |
| 101 |
static const struct ig4_cfg ig4iic_configs[] = { |
| 102 |
[IG4_HASWELL] = { |
| 103 |
.bus_speed = IG4_CTL_SPEED_FAST, |
| 104 |
.ss_scl_hcnt = 432, |
| 105 |
.ss_scl_lcnt = 507, |
| 106 |
.fs_scl_hcnt = 110, |
| 107 |
.fs_scl_lcnt = 160, |
| 108 |
.sda_tx_hold = 9, |
| 109 |
.txfifo_depth = 32, |
| 110 |
.rxfifo_depth = 32, |
| 111 |
}, |
| 112 |
[IG4_ATOM] = { |
| 113 |
.bus_speed = IG4_CTL_SPEED_FAST, |
| 114 |
.ss_scl_hcnt = 512, |
| 115 |
.ss_scl_lcnt = 512, |
| 116 |
.fs_scl_hcnt = 85, |
| 117 |
.fs_scl_lcnt = 153, |
| 118 |
.sda_tx_hold = 6, |
| 119 |
.txfifo_depth = 32, |
| 120 |
.rxfifo_depth = 32, |
| 121 |
}, |
| 122 |
[IG4_SKYLAKE] = { |
| 123 |
/* |
| 124 |
* IC clock rate: 120 MHz |
| 125 |
* SDA hold time: 230 ns |
| 126 |
* SDA falling time: 300 ns |
| 127 |
* SCL falling time: 300 ns |
| 128 |
*/ |
| 129 |
.bus_speed = IG4_CTL_SPEED_FAST, |
| 130 |
.ss_scl_hcnt = 513, |
| 131 |
.ss_scl_lcnt = 599, |
| 132 |
.fs_scl_hcnt = 105, |
| 133 |
.fs_scl_lcnt = 191, |
| 134 |
.sda_tx_hold = 28, |
| 135 |
.txfifo_depth = 64, |
| 136 |
.rxfifo_depth = 64, |
| 137 |
}, |
| 138 |
[IG4_APL] = { |
| 139 |
/* |
| 140 |
* IC clock rate: 133 MHz |
| 141 |
* SDA hold time: 207 ns |
| 142 |
* SDA falling time: 171 ns |
| 143 |
* SCL falling time: 208 ns |
| 144 |
*/ |
| 145 |
.bus_speed = IG4_CTL_SPEED_FAST, |
| 146 |
.ss_scl_hcnt = 552, |
| 147 |
.ss_scl_lcnt = 652, |
| 148 |
.fs_scl_hcnt = 100, |
| 149 |
.fs_scl_lcnt = 200, |
| 150 |
.sda_tx_hold = 28, |
| 151 |
}, |
| 152 |
}; |
| 153 |
|
| 154 |
static int ig4iic_set_config(ig4iic_softc_t *sc); |
| 74 |
static void ig4iic_intr(void *cookie); |
155 |
static void ig4iic_intr(void *cookie); |
| 75 |
static void ig4iic_dump(ig4iic_softc_t *sc); |
156 |
static void ig4iic_dump(ig4iic_softc_t *sc); |
| 76 |
|
157 |
|
|
Lines 98-103
reg_read(ig4iic_softc_t *sc, uint32_t reg)
Link Here
|
| 98 |
return (value); |
179 |
return (value); |
| 99 |
} |
180 |
} |
| 100 |
|
181 |
|
|
|
182 |
static void |
| 183 |
set_intr_mask(ig4iic_softc_t *sc, uint32_t val) |
| 184 |
{ |
| 185 |
if (sc->intr_mask != val) { |
| 186 |
reg_write(sc, IG4_REG_INTR_MASK, val); |
| 187 |
sc->intr_mask = val; |
| 188 |
} |
| 189 |
} |
| 190 |
|
| 191 |
static int |
| 192 |
intrstat2iic(ig4iic_softc_t *sc, uint32_t val) |
| 193 |
{ |
| 194 |
uint32_t src; |
| 195 |
|
| 196 |
if (val & IG4_INTR_RX_UNDER) |
| 197 |
reg_read(sc, IG4_REG_CLR_RX_UNDER); |
| 198 |
if (val & IG4_INTR_RX_OVER) |
| 199 |
reg_read(sc, IG4_REG_CLR_RX_OVER); |
| 200 |
if (val & IG4_INTR_TX_OVER) |
| 201 |
reg_read(sc, IG4_REG_CLR_TX_OVER); |
| 202 |
|
| 203 |
if (val & IG4_INTR_TX_ABRT) { |
| 204 |
src = reg_read(sc, IG4_REG_TX_ABRT_SOURCE); |
| 205 |
reg_read(sc, IG4_REG_CLR_TX_ABORT); |
| 206 |
/* User-requested abort. Not really a error */ |
| 207 |
if (src & IG4_ABRTSRC_TRANSFER) |
| 208 |
return (IIC_ESTATUS); |
| 209 |
/* Master has lost arbitration */ |
| 210 |
if (src & IG4_ABRTSRC_ARBLOST) |
| 211 |
return (IIC_EBUSBSY); |
| 212 |
/* Did not receive an acknowledge from the remote slave */ |
| 213 |
if (src & (IG4_ABRTSRC_TXNOACK_ADDR7 | |
| 214 |
IG4_ABRTSRC_TXNOACK_ADDR10_1 | |
| 215 |
IG4_ABRTSRC_TXNOACK_ADDR10_2 | |
| 216 |
IG4_ABRTSRC_TXNOACK_DATA | |
| 217 |
IG4_ABRTSRC_GENCALL_NOACK)) |
| 218 |
return (IIC_ENOACK); |
| 219 |
/* Programming errors */ |
| 220 |
if (src & (IG4_ABRTSRC_GENCALL_READ | |
| 221 |
IG4_ABRTSRC_NORESTART_START | |
| 222 |
IG4_ABRTSRC_NORESTART_10)) |
| 223 |
return (IIC_ENOTSUPP); |
| 224 |
/* Other errors */ |
| 225 |
if (src & IG4_ABRTSRC_ACKED_START) |
| 226 |
return (IIC_EBUSERR); |
| 227 |
} |
| 228 |
/* |
| 229 |
* TX_OVER, RX_OVER and RX_UNDER are caused by wrong RX/TX FIFO depth |
| 230 |
* detection or driver's read/write pipelining errors. |
| 231 |
*/ |
| 232 |
if (val & (IG4_INTR_TX_OVER | IG4_INTR_RX_OVER)) |
| 233 |
return (IIC_EOVERFLOW); |
| 234 |
if (val & IG4_INTR_RX_UNDER) |
| 235 |
return (IIC_EUNDERFLOW); |
| 236 |
|
| 237 |
return (IIC_NOERR); |
| 238 |
} |
| 239 |
|
| 101 |
/* |
240 |
/* |
| 102 |
* Enable or disable the controller and wait for the controller to acknowledge |
241 |
* Enable or disable the controller and wait for the controller to acknowledge |
| 103 |
* the state change. |
242 |
* the state change. |
|
Lines 113-124
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
Link Here
|
| 113 |
* When the controller is enabled, interrupt on STOP detect |
252 |
* When the controller is enabled, interrupt on STOP detect |
| 114 |
* or receive character ready and clear pending interrupts. |
253 |
* or receive character ready and clear pending interrupts. |
| 115 |
*/ |
254 |
*/ |
| 116 |
if (ctl & IG4_I2C_ENABLE) { |
255 |
set_intr_mask(sc, 0); |
| 117 |
reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | |
256 |
if (ctl & IG4_I2C_ENABLE) |
| 118 |
IG4_INTR_RX_FULL); |
|
|
| 119 |
reg_read(sc, IG4_REG_CLR_INTR); |
257 |
reg_read(sc, IG4_REG_CLR_INTR); |
| 120 |
} else |
|
|
| 121 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
| 122 |
|
258 |
|
| 123 |
reg_write(sc, IG4_REG_I2C_EN, ctl); |
259 |
reg_write(sc, IG4_REG_I2C_EN, ctl); |
| 124 |
error = IIC_ETIMEOUT; |
260 |
error = IIC_ETIMEOUT; |
|
Lines 129-147
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
Link Here
|
| 129 |
error = 0; |
265 |
error = 0; |
| 130 |
break; |
266 |
break; |
| 131 |
} |
267 |
} |
| 132 |
if (cold) |
268 |
pause("i2cslv", 1); |
| 133 |
DELAY(1000); |
|
|
| 134 |
else |
| 135 |
mtx_sleep(sc, &sc->io_lock, 0, "i2cslv", 1); |
| 136 |
} |
269 |
} |
| 137 |
return (error); |
270 |
return (error); |
| 138 |
} |
271 |
} |
| 139 |
|
272 |
|
| 140 |
/* |
273 |
/* |
| 141 |
* Wait up to 25ms for the requested status using a 25uS polling loop. |
274 |
* Wait up to 25ms for the requested interrupt using a 25uS polling loop. |
| 142 |
*/ |
275 |
*/ |
| 143 |
static int |
276 |
static int |
| 144 |
wait_status(ig4iic_softc_t *sc, uint32_t status) |
277 |
wait_intr(ig4iic_softc_t *sc, uint32_t intr) |
| 145 |
{ |
278 |
{ |
| 146 |
uint32_t v; |
279 |
uint32_t v; |
| 147 |
int error; |
280 |
int error; |
|
Lines 151-175
wait_status(ig4iic_softc_t *sc, uint32_t status)
Link Here
|
| 151 |
|
284 |
|
| 152 |
error = IIC_ETIMEOUT; |
285 |
error = IIC_ETIMEOUT; |
| 153 |
|
286 |
|
| 154 |
for (;;) { |
287 |
while (error == IIC_ETIMEOUT) { |
| 155 |
/* |
288 |
/* |
| 156 |
* Check requested status |
289 |
* Check requested status |
| 157 |
*/ |
290 |
*/ |
| 158 |
v = reg_read(sc, IG4_REG_I2C_STA); |
291 |
v = reg_read(sc, IG4_REG_RAW_INTR_STAT); |
| 159 |
if (v & status) { |
292 |
error = intrstat2iic(sc, v & IG4_INTR_ERR_MASK); |
| 160 |
error = 0; |
293 |
if (error) |
| 161 |
break; |
294 |
break; |
| 162 |
} |
|
|
| 163 |
|
295 |
|
| 164 |
/* |
296 |
if (v & intr) { |
| 165 |
* When waiting for receive data break-out if the interrupt |
297 |
error = 0; |
| 166 |
* loaded data into the FIFO. |
298 |
break; |
| 167 |
*/ |
|
|
| 168 |
if (status & IG4_STATUS_RX_NOTEMPTY) { |
| 169 |
if (sc->rpos != sc->rnext) { |
| 170 |
error = 0; |
| 171 |
break; |
| 172 |
} |
| 173 |
} |
299 |
} |
| 174 |
|
300 |
|
| 175 |
/* |
301 |
/* |
|
Lines 177-183
wait_status(ig4iic_softc_t *sc, uint32_t status)
Link Here
|
| 177 |
* reset the timeout if we see a change in the transmit |
303 |
* reset the timeout if we see a change in the transmit |
| 178 |
* FIFO level as progress is being made. |
304 |
* FIFO level as progress is being made. |
| 179 |
*/ |
305 |
*/ |
| 180 |
if (status & IG4_STATUS_TX_EMPTY) { |
306 |
if (intr & (IG4_INTR_TX_EMPTY | IG4_INTR_STOP_DET)) { |
| 181 |
v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK; |
307 |
v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK; |
| 182 |
if (txlvl != v) { |
308 |
if (txlvl != v) { |
| 183 |
txlvl = v; |
309 |
txlvl = v; |
|
Lines 188-232
wait_status(ig4iic_softc_t *sc, uint32_t status)
Link Here
|
| 188 |
/* |
314 |
/* |
| 189 |
* Stop if we've run out of time. |
315 |
* Stop if we've run out of time. |
| 190 |
*/ |
316 |
*/ |
| 191 |
if (count_us >= limit_us) |
317 |
if (count_us >= limit_us) { |
|
|
318 |
error = IIC_ETIMEOUT; |
| 192 |
break; |
319 |
break; |
|
|
320 |
} |
| 193 |
|
321 |
|
| 194 |
/* |
322 |
/* |
| 195 |
* When waiting for receive data let the interrupt do its |
323 |
* When polling is not requested let the interrupt do its work. |
| 196 |
* work, otherwise poll with the lock held. |
|
|
| 197 |
*/ |
324 |
*/ |
| 198 |
if (status & IG4_STATUS_RX_NOTEMPTY) { |
325 |
if (!DO_POLL(sc)) { |
| 199 |
mtx_sleep(sc, &sc->io_lock, 0, "i2cwait", |
326 |
mtx_lock(&sc->io_lock); |
|
|
327 |
sc->error = 0; |
| 328 |
set_intr_mask(sc, intr | IG4_INTR_ERR_MASK); |
| 329 |
error = mtx_sleep(sc, &sc->io_lock, 0, "i2cwait", |
| 200 |
(hz + 99) / 100); /* sleep up to 10ms */ |
330 |
(hz + 99) / 100); /* sleep up to 10ms */ |
|
|
331 |
if (error != 0) |
| 332 |
error = IIC_ETIMEOUT; |
| 333 |
else |
| 334 |
error = sc->error; |
| 335 |
set_intr_mask(sc, 0); |
| 336 |
mtx_unlock(&sc->io_lock); |
| 201 |
count_us += 10000; |
337 |
count_us += 10000; |
| 202 |
} else { |
338 |
} else { |
| 203 |
DELAY(25); |
339 |
DELAY(25); |
| 204 |
count_us += 25; |
340 |
count_us += 25; |
|
|
341 |
error = IIC_ETIMEOUT; |
| 205 |
} |
342 |
} |
| 206 |
} |
343 |
} |
| 207 |
|
344 |
|
| 208 |
return (error); |
345 |
return (error); |
| 209 |
} |
346 |
} |
| 210 |
|
347 |
|
| 211 |
/* |
|
|
| 212 |
* Read I2C data. The data might have already been read by |
| 213 |
* the interrupt code, otherwise it is sitting in the data |
| 214 |
* register. |
| 215 |
*/ |
| 216 |
static uint8_t |
| 217 |
data_read(ig4iic_softc_t *sc) |
| 218 |
{ |
| 219 |
uint8_t c; |
| 220 |
|
| 221 |
if (sc->rpos == sc->rnext) { |
| 222 |
c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD); |
| 223 |
} else { |
| 224 |
c = sc->rbuf[sc->rpos & IG4_RBUFMASK]; |
| 225 |
++sc->rpos; |
| 226 |
} |
| 227 |
return (c); |
| 228 |
} |
| 229 |
|
| 230 |
/* |
348 |
/* |
| 231 |
* Set the slave address. The controller must be disabled when |
349 |
* Set the slave address. The controller must be disabled when |
| 232 |
* changing the address. |
350 |
* changing the address. |
|
Lines 250-271
set_slave_addr(ig4iic_softc_t *sc, uint8_t slave)
Link Here
|
| 250 |
|
368 |
|
| 251 |
/* |
369 |
/* |
| 252 |
* Wait for TXFIFO to drain before disabling the controller. |
370 |
* Wait for TXFIFO to drain before disabling the controller. |
| 253 |
* |
|
|
| 254 |
* If a write message has not been completed it's really a |
| 255 |
* programming error, but for now in that case issue an extra |
| 256 |
* byte + STOP. |
| 257 |
* |
| 258 |
* If a read message has not been completed it's also a programming |
| 259 |
* error, for now just ignore it. |
| 260 |
*/ |
371 |
*/ |
| 261 |
wait_status(sc, IG4_STATUS_TX_NOTFULL); |
372 |
wait_intr(sc, IG4_INTR_TX_EMPTY); |
| 262 |
if (sc->write_started) { |
|
|
| 263 |
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP); |
| 264 |
sc->write_started = 0; |
| 265 |
} |
| 266 |
if (sc->read_started) |
| 267 |
sc->read_started = 0; |
| 268 |
wait_status(sc, IG4_STATUS_TX_EMPTY); |
| 269 |
|
373 |
|
| 270 |
set_controller(sc, 0); |
374 |
set_controller(sc, 0); |
| 271 |
ctl = reg_read(sc, IG4_REG_CTL); |
375 |
ctl = reg_read(sc, IG4_REG_CTL); |
|
Lines 288-335
set_slave_addr(ig4iic_softc_t *sc, uint8_t slave)
Link Here
|
| 288 |
* IICBUS API FUNCTIONS |
392 |
* IICBUS API FUNCTIONS |
| 289 |
*/ |
393 |
*/ |
| 290 |
static int |
394 |
static int |
| 291 |
ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave) |
395 |
ig4iic_xfer_start(ig4iic_softc_t *sc, uint16_t slave, bool repeated_start) |
| 292 |
{ |
396 |
{ |
| 293 |
set_slave_addr(sc, slave >> 1); |
397 |
set_slave_addr(sc, slave >> 1); |
|
|
398 |
|
| 399 |
if (!repeated_start) { |
| 400 |
/* |
| 401 |
* Clear any previous TX/RX FIFOs overflow/underflow bits |
| 402 |
* and I2C bus STOP condition. |
| 403 |
*/ |
| 404 |
reg_read(sc, IG4_REG_CLR_INTR); |
| 405 |
} |
| 406 |
|
| 294 |
return (0); |
407 |
return (0); |
| 295 |
} |
408 |
} |
| 296 |
|
409 |
|
|
|
410 |
static int |
| 411 |
ig4iic_xfer_abort(ig4iic_softc_t *sc) |
| 412 |
{ |
| 413 |
int error; |
| 414 |
|
| 415 |
/* Request send of STOP condition and flush of TX FIFO */ |
| 416 |
set_controller(sc, IG4_I2C_ABORT | IG4_I2C_ENABLE); |
| 417 |
/* |
| 418 |
* Wait for the TX_ABRT interrupt with ABRTSRC_TRANSFER |
| 419 |
* bit set in TX_ABRT_SOURCE register. |
| 420 |
*/ |
| 421 |
error = wait_intr(sc, IG4_INTR_STOP_DET); |
| 422 |
set_controller(sc, IG4_I2C_ENABLE); |
| 423 |
|
| 424 |
return (error == IIC_ESTATUS ? 0 : error); |
| 425 |
} |
| 426 |
|
| 427 |
/* |
| 428 |
* Amount of unread data before next burst to get better I2C bus utilization. |
| 429 |
* 2 bytes is enough in FAST mode. 8 bytes is better in FAST+ and HIGH modes. |
| 430 |
* Intel-recommended value is 16 for DMA transfers with 64-byte depth FIFOs. |
| 431 |
*/ |
| 432 |
#define IG4_FIFO_LOWAT 2 |
| 433 |
|
| 297 |
static int |
434 |
static int |
| 298 |
ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len, |
435 |
ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len, |
| 299 |
bool repeated_start, bool stop) |
436 |
bool repeated_start, bool stop) |
| 300 |
{ |
437 |
{ |
| 301 |
uint32_t cmd; |
438 |
uint32_t cmd; |
| 302 |
uint16_t i; |
439 |
int requested = 0; |
|
|
440 |
int received = 0; |
| 441 |
int burst, target, lowat = 0; |
| 303 |
int error; |
442 |
int error; |
| 304 |
|
443 |
|
| 305 |
if (len == 0) |
444 |
if (len == 0) |
| 306 |
return (0); |
445 |
return (0); |
| 307 |
|
446 |
|
| 308 |
cmd = IG4_DATA_COMMAND_RD; |
447 |
while (received < len) { |
| 309 |
cmd |= repeated_start ? IG4_DATA_RESTART : 0; |
448 |
burst = sc->cfg.txfifo_depth - |
| 310 |
cmd |= stop && len == 1 ? IG4_DATA_STOP : 0; |
449 |
(reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK); |
| 311 |
|
450 |
if (burst <= 0) { |
| 312 |
/* Issue request for the first byte (could be last as well). */ |
451 |
error = wait_intr(sc, IG4_INTR_TX_EMPTY); |
| 313 |
reg_write(sc, IG4_REG_DATA_CMD, cmd); |
452 |
if (error) |
| 314 |
|
453 |
break; |
| 315 |
for (i = 0; i < len; i++) { |
454 |
burst = sc->cfg.txfifo_depth; |
| 316 |
/* |
455 |
} |
| 317 |
* Maintain a pipeline by queueing the allowance for the next |
456 |
/* Ensure we have enough free space in RXFIFO */ |
| 318 |
* read before waiting for the current read. |
457 |
burst = MIN(burst, sc->cfg.rxfifo_depth - lowat); |
| 319 |
*/ |
458 |
target = MIN(requested + burst, (int)len); |
| 320 |
cmd = IG4_DATA_COMMAND_RD; |
459 |
while (requested < target) { |
| 321 |
if (i < len - 1) { |
|
|
| 322 |
cmd = IG4_DATA_COMMAND_RD; |
460 |
cmd = IG4_DATA_COMMAND_RD; |
| 323 |
cmd |= stop && i == len - 2 ? IG4_DATA_STOP : 0; |
461 |
if (repeated_start && requested == 0) |
|
|
462 |
cmd |= IG4_DATA_RESTART; |
| 463 |
if (stop && requested == len - 1) |
| 464 |
cmd |= IG4_DATA_STOP; |
| 324 |
reg_write(sc, IG4_REG_DATA_CMD, cmd); |
465 |
reg_write(sc, IG4_REG_DATA_CMD, cmd); |
|
|
466 |
requested++; |
| 467 |
} |
| 468 |
/* Leave some data queued to maintain the hardware pipeline */ |
| 469 |
lowat = 0; |
| 470 |
if (requested != len && requested - received > IG4_FIFO_LOWAT) |
| 471 |
lowat = IG4_FIFO_LOWAT; |
| 472 |
/* After TXFLR fills up, clear it by reading available data */ |
| 473 |
while (received < requested - lowat) { |
| 474 |
burst = MIN((int)len - received, |
| 475 |
reg_read(sc, IG4_REG_RXFLR) & IG4_FIFOLVL_MASK); |
| 476 |
if (burst > 0) { |
| 477 |
while (burst--) |
| 478 |
buf[received++] = 0xFF & |
| 479 |
reg_read(sc, IG4_REG_DATA_CMD); |
| 480 |
} else { |
| 481 |
error = wait_intr(sc, IG4_INTR_RX_FULL); |
| 482 |
if (error) |
| 483 |
goto out; |
| 484 |
} |
| 325 |
} |
485 |
} |
| 326 |
error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY); |
|
|
| 327 |
if (error) |
| 328 |
break; |
| 329 |
buf[i] = data_read(sc); |
| 330 |
} |
486 |
} |
| 331 |
|
487 |
out: |
| 332 |
(void)reg_read(sc, IG4_REG_TX_ABRT_SOURCE); |
|
|
| 333 |
return (error); |
488 |
return (error); |
| 334 |
} |
489 |
} |
| 335 |
|
490 |
|
|
Lines 338-361
ig4iic_write(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
Link Here
|
| 338 |
bool repeated_start, bool stop) |
493 |
bool repeated_start, bool stop) |
| 339 |
{ |
494 |
{ |
| 340 |
uint32_t cmd; |
495 |
uint32_t cmd; |
| 341 |
uint16_t i; |
496 |
int sent = 0; |
|
|
497 |
int burst, target; |
| 342 |
int error; |
498 |
int error; |
|
|
499 |
bool lowat_set = false; |
| 343 |
|
500 |
|
| 344 |
if (len == 0) |
501 |
if (len == 0) |
| 345 |
return (0); |
502 |
return (0); |
| 346 |
|
503 |
|
| 347 |
cmd = repeated_start ? IG4_DATA_RESTART : 0; |
504 |
while (sent < len) { |
| 348 |
for (i = 0; i < len; i++) { |
505 |
burst = sc->cfg.txfifo_depth - |
| 349 |
error = wait_status(sc, IG4_STATUS_TX_NOTFULL); |
506 |
(reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK); |
| 350 |
if (error) |
507 |
target = MIN(sent + burst, (int)len); |
| 351 |
break; |
508 |
/* Leave some data queued to maintain the hardware pipeline */ |
| 352 |
cmd |= buf[i]; |
509 |
if (sent == 0 && target != len) { |
| 353 |
cmd |= stop && i == len - 1 ? IG4_DATA_STOP : 0; |
510 |
lowat_set = true; |
| 354 |
reg_write(sc, IG4_REG_DATA_CMD, cmd); |
511 |
reg_write(sc, IG4_REG_TX_TL, IG4_FIFO_LOWAT); |
| 355 |
cmd = 0; |
512 |
} |
|
|
513 |
while(sent < target) { |
| 514 |
cmd = buf[sent]; |
| 515 |
if (repeated_start && sent == 0) |
| 516 |
cmd |= IG4_DATA_RESTART; |
| 517 |
if (stop && sent == len - 1) |
| 518 |
cmd |= IG4_DATA_STOP; |
| 519 |
reg_write(sc, IG4_REG_DATA_CMD, cmd); |
| 520 |
sent++; |
| 521 |
} |
| 522 |
if (sent < len) { |
| 523 |
error = wait_intr(sc, IG4_INTR_TX_EMPTY); |
| 524 |
if (error) |
| 525 |
break; |
| 526 |
} |
| 356 |
} |
527 |
} |
|
|
528 |
if (lowat_set) |
| 529 |
reg_write(sc, IG4_REG_TX_TL, 0); |
| 357 |
|
530 |
|
| 358 |
(void)reg_read(sc, IG4_REG_TX_ABRT_SOURCE); |
|
|
| 359 |
return (error); |
531 |
return (error); |
| 360 |
} |
532 |
} |
| 361 |
|
533 |
|
|
Lines 369-374
ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
Link Here
|
| 369 |
int unit; |
541 |
int unit; |
| 370 |
bool rpstart; |
542 |
bool rpstart; |
| 371 |
bool stop; |
543 |
bool stop; |
|
|
544 |
bool allocated; |
| 372 |
|
545 |
|
| 373 |
/* |
546 |
/* |
| 374 |
* The hardware interface imposes limits on allowed I2C messages. |
547 |
* The hardware interface imposes limits on allowed I2C messages. |
|
Lines 429-436
ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
Link Here
|
| 429 |
return (IIC_ENOTSUPP); |
602 |
return (IIC_ENOTSUPP); |
| 430 |
} |
603 |
} |
| 431 |
|
604 |
|
| 432 |
sx_xlock(&sc->call_lock); |
605 |
/* Check if device is already allocated with iicbus_request_bus() */ |
| 433 |
mtx_lock(&sc->io_lock); |
606 |
allocated = sx_xlocked(&sc->call_lock) != 0; |
|
|
607 |
if (!allocated) |
| 608 |
sx_xlock(&sc->call_lock); |
| 434 |
|
609 |
|
| 435 |
/* Debugging - dump registers. */ |
610 |
/* Debugging - dump registers. */ |
| 436 |
if (ig4_dump) { |
611 |
if (ig4_dump) { |
|
Lines 447-467
ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
Link Here
|
| 447 |
*/ |
622 |
*/ |
| 448 |
reg_read(sc, IG4_REG_CLR_TX_ABORT); |
623 |
reg_read(sc, IG4_REG_CLR_TX_ABORT); |
| 449 |
|
624 |
|
| 450 |
/* |
|
|
| 451 |
* Clean out any previously received data. |
| 452 |
*/ |
| 453 |
if (sc->rpos != sc->rnext && bootverbose) { |
| 454 |
device_printf(sc->dev, "discarding %d bytes of spurious data\n", |
| 455 |
sc->rnext - sc->rpos); |
| 456 |
} |
| 457 |
sc->rpos = 0; |
| 458 |
sc->rnext = 0; |
| 459 |
|
| 460 |
rpstart = false; |
625 |
rpstart = false; |
| 461 |
error = 0; |
626 |
error = 0; |
| 462 |
for (i = 0; i < nmsgs; i++) { |
627 |
for (i = 0; i < nmsgs; i++) { |
| 463 |
if ((msgs[i].flags & IIC_M_NOSTART) == 0) { |
628 |
if ((msgs[i].flags & IIC_M_NOSTART) == 0) { |
| 464 |
error = ig4iic_xfer_start(sc, msgs[i].slave); |
629 |
error = ig4iic_xfer_start(sc, msgs[i].slave, rpstart); |
| 465 |
} else { |
630 |
} else { |
| 466 |
if (!sc->slave_valid || |
631 |
if (!sc->slave_valid || |
| 467 |
(msgs[i].slave >> 1) != sc->last_slave) { |
632 |
(msgs[i].slave >> 1) != sc->last_slave) { |
|
Lines 482-495
ig4iic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
Link Here
|
| 482 |
else |
647 |
else |
| 483 |
error = ig4iic_write(sc, msgs[i].buf, msgs[i].len, |
648 |
error = ig4iic_write(sc, msgs[i].buf, msgs[i].len, |
| 484 |
rpstart, stop); |
649 |
rpstart, stop); |
| 485 |
if (error != 0) |
650 |
|
|
|
651 |
/* Wait for error or stop condition occurred on the I2C bus */ |
| 652 |
if (stop && error == 0) { |
| 653 |
error = wait_intr(sc, IG4_INTR_STOP_DET); |
| 654 |
if (error == 0) |
| 655 |
reg_read(sc, IG4_REG_CLR_INTR); |
| 656 |
} |
| 657 |
|
| 658 |
if (error != 0) { |
| 659 |
/* |
| 660 |
* Send STOP condition if it's not done yet and flush |
| 661 |
* both FIFOs. Do a controller soft reset if transfer |
| 662 |
* abort is failed. |
| 663 |
*/ |
| 664 |
if (((reg_read(sc, IG4_REG_RAW_INTR_STAT) & |
| 665 |
(IG4_INTR_START_DET | IG4_INTR_STOP_DET)) |
| 666 |
== IG4_INTR_START_DET) && |
| 667 |
ig4iic_xfer_abort(sc) != 0) { |
| 668 |
device_printf(sc->dev, "Failed to abort " |
| 669 |
"transfer. Do the controller reset.\n"); |
| 670 |
ig4iic_set_config(sc); |
| 671 |
} else { |
| 672 |
while (reg_read(sc, IG4_REG_I2C_STA) & |
| 673 |
IG4_STATUS_RX_NOTEMPTY) |
| 674 |
reg_read(sc, IG4_REG_DATA_CMD); |
| 675 |
reg_read(sc, IG4_REG_TX_ABRT_SOURCE); |
| 676 |
reg_read(sc, IG4_REG_CLR_INTR); |
| 677 |
} |
| 486 |
break; |
678 |
break; |
|
|
679 |
} |
| 487 |
|
680 |
|
| 488 |
rpstart = !stop; |
681 |
rpstart = !stop; |
| 489 |
} |
682 |
} |
| 490 |
|
683 |
|
| 491 |
mtx_unlock(&sc->io_lock); |
684 |
if (!allocated) |
| 492 |
sx_unlock(&sc->call_lock); |
685 |
sx_unlock(&sc->call_lock); |
| 493 |
return (error); |
686 |
return (error); |
| 494 |
} |
687 |
} |
| 495 |
|
688 |
|
|
Lines 497-505
int
Link Here
|
| 497 |
ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) |
690 |
ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) |
| 498 |
{ |
691 |
{ |
| 499 |
ig4iic_softc_t *sc = device_get_softc(dev); |
692 |
ig4iic_softc_t *sc = device_get_softc(dev); |
|
|
693 |
bool allocated; |
| 500 |
|
694 |
|
| 501 |
sx_xlock(&sc->call_lock); |
695 |
allocated = sx_xlocked(&sc->call_lock) != 0; |
| 502 |
mtx_lock(&sc->io_lock); |
696 |
if (!allocated) |
|
|
697 |
sx_xlock(&sc->call_lock); |
| 503 |
|
698 |
|
| 504 |
/* TODO handle speed configuration? */ |
699 |
/* TODO handle speed configuration? */ |
| 505 |
if (oldaddr != NULL) |
700 |
if (oldaddr != NULL) |
|
Lines 508-539
ig4iic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
Link Here
|
| 508 |
if (addr == IIC_UNKNOWN) |
703 |
if (addr == IIC_UNKNOWN) |
| 509 |
sc->slave_valid = false; |
704 |
sc->slave_valid = false; |
| 510 |
|
705 |
|
| 511 |
mtx_unlock(&sc->io_lock); |
706 |
if (!allocated) |
| 512 |
sx_unlock(&sc->call_lock); |
707 |
sx_unlock(&sc->call_lock); |
| 513 |
return (0); |
708 |
return (0); |
| 514 |
} |
709 |
} |
| 515 |
|
710 |
|
| 516 |
/* |
|
|
| 517 |
* Called from ig4iic_pci_attach/detach() |
| 518 |
*/ |
| 519 |
int |
711 |
int |
| 520 |
ig4iic_attach(ig4iic_softc_t *sc) |
712 |
ig4iic_callback(device_t dev, int index, caddr_t data) |
|
|
713 |
{ |
| 714 |
ig4iic_softc_t *sc = device_get_softc(dev); |
| 715 |
int error = 0; |
| 716 |
int how; |
| 717 |
|
| 718 |
/* |
| 719 |
* Unfortunately, iicbus_request_bus() can return error code in both |
| 720 |
* formats, POSIX and IIC. Here we use EAGAIN instead of IIC_EBUSBSY |
| 721 |
* to match other possibly buggy iicbus_callback implementations. |
| 722 |
* As iicbus_poll() returns IIC_EBUSBSY, caller should check returned |
| 723 |
* value for both EAGAIN and IIC_EBUSBSY. Other error codes are POSIX. |
| 724 |
*/ |
| 725 |
switch (index) { |
| 726 |
case IIC_REQUEST_BUS: |
| 727 |
/* force polling if ig4iic is requested with IIC_DONTWAIT */ |
| 728 |
how = *(int *)data; |
| 729 |
if ((how & IIC_WAIT) == 0) { |
| 730 |
if (sx_try_xlock(&sc->call_lock) == 0) |
| 731 |
error = EWOULDBLOCK; |
| 732 |
else |
| 733 |
sc->poll = true; |
| 734 |
} else |
| 735 |
sx_xlock(&sc->call_lock); |
| 736 |
break; |
| 737 |
|
| 738 |
case IIC_RELEASE_BUS: |
| 739 |
sc->poll = false; |
| 740 |
sx_unlock(&sc->call_lock); |
| 741 |
break; |
| 742 |
|
| 743 |
default: |
| 744 |
error = EINVAL; |
| 745 |
} |
| 746 |
|
| 747 |
return (error); |
| 748 |
} |
| 749 |
|
| 750 |
#ifdef DEV_ACPI |
| 751 |
static int |
| 752 |
ig4iic_acpi_params(ig4iic_softc_t *sc, char *method, |
| 753 |
uint16_t *scl_hcnt, uint16_t *scl_lcnt, uint16_t *sda_tx_hold) |
| 521 |
{ |
754 |
{ |
|
|
755 |
ACPI_BUFFER buf; |
| 756 |
ACPI_HANDLE handle; |
| 757 |
ACPI_OBJECT *obj, *elems; |
| 522 |
int error; |
758 |
int error; |
|
|
759 |
|
| 760 |
handle = acpi_get_handle(sc->dev); |
| 761 |
if (handle == NULL) |
| 762 |
return (ENXIO); |
| 763 |
|
| 764 |
buf.Pointer = NULL; |
| 765 |
buf.Length = ACPI_ALLOCATE_BUFFER; |
| 766 |
|
| 767 |
if (ACPI_FAILURE(AcpiEvaluateObject(handle, method, NULL, &buf))) |
| 768 |
return (ENXIO); |
| 769 |
|
| 770 |
error = ENXIO; |
| 771 |
obj = (ACPI_OBJECT *)buf.Pointer; |
| 772 |
if (obj->Type == ACPI_TYPE_PACKAGE && obj->Package.Count == 3) { |
| 773 |
elems = obj->Package.Elements; |
| 774 |
*scl_hcnt = elems[0].Integer.Value & IG4_SCL_CLOCK_MASK; |
| 775 |
*scl_lcnt = elems[1].Integer.Value & IG4_SCL_CLOCK_MASK; |
| 776 |
*sda_tx_hold = elems[2].Integer.Value & IG4_SDA_TX_HOLD_MASK; |
| 777 |
error = 0; |
| 778 |
} |
| 779 |
|
| 780 |
AcpiOsFree(obj); |
| 781 |
|
| 782 |
return (error); |
| 783 |
} |
| 784 |
#endif /* DEV_ACPI */ |
| 785 |
|
| 786 |
static void |
| 787 |
ig4iic_get_config(ig4iic_softc_t *sc) |
| 788 |
{ |
| 789 |
const struct ig4_cfg *cfg; |
| 523 |
uint32_t v; |
790 |
uint32_t v; |
|
|
791 |
#ifdef DEV_ACPI |
| 792 |
uint16_t sda_tx_hold; |
| 793 |
#endif |
| 524 |
|
794 |
|
| 525 |
mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_DEF); |
795 |
/* Fetch default hardware config from controller */ |
| 526 |
sx_init(&sc->call_lock, "IG4 call lock"); |
796 |
sc->cfg.version = reg_read(sc, IG4_REG_COMP_VER); |
|
|
797 |
sc->cfg.bus_speed = reg_read(sc, IG4_REG_CTL) & IG4_CTL_SPEED_MASK; |
| 798 |
sc->cfg.ss_scl_hcnt = |
| 799 |
reg_read(sc, IG4_REG_SS_SCL_HCNT) & IG4_SCL_CLOCK_MASK; |
| 800 |
sc->cfg.ss_scl_lcnt = |
| 801 |
reg_read(sc, IG4_REG_SS_SCL_LCNT) & IG4_SCL_CLOCK_MASK; |
| 802 |
sc->cfg.fs_scl_hcnt = |
| 803 |
reg_read(sc, IG4_REG_FS_SCL_HCNT) & IG4_SCL_CLOCK_MASK; |
| 804 |
sc->cfg.fs_scl_lcnt = |
| 805 |
reg_read(sc, IG4_REG_FS_SCL_LCNT) & IG4_SCL_CLOCK_MASK; |
| 806 |
sc->cfg.sda_tx_hold = |
| 807 |
reg_read(sc, IG4_REG_SDA_HOLD) & IG4_SDA_TX_HOLD_MASK; |
| 808 |
|
| 809 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
| 810 |
/* REG_COMP_PARAM1 register is not documented in Intel specs */ |
| 811 |
v = reg_read(sc, IG4_REG_COMP_PARAM1); |
| 812 |
if (IG4_PARAM1_TXFIFO_DEPTH(v) != 0) |
| 813 |
sc->cfg.txfifo_depth = IG4_PARAM1_TXFIFO_DEPTH(v); |
| 814 |
if (IG4_PARAM1_RXFIFO_DEPTH(v) != 0) |
| 815 |
sc->cfg.rxfifo_depth = IG4_PARAM1_RXFIFO_DEPTH(v); |
| 816 |
} else { |
| 817 |
/* |
| 818 |
* Hardware does not allow FIFO Threshold Levels value to be |
| 819 |
* set larger than the depth of the buffer. If an attempt is |
| 820 |
* made to do that, the actual value set will be the maximum |
| 821 |
* depth of the buffer. |
| 822 |
*/ |
| 823 |
v = reg_read(sc, IG4_REG_TX_TL); |
| 824 |
reg_write(sc, IG4_REG_TX_TL, v | IG4_FIFO_MASK); |
| 825 |
sc->cfg.txfifo_depth = |
| 826 |
(reg_read(sc, IG4_REG_TX_TL) & IG4_FIFO_MASK) + 1; |
| 827 |
reg_write(sc, IG4_REG_TX_TL, v); |
| 828 |
v = reg_read(sc, IG4_REG_RX_TL); |
| 829 |
reg_write(sc, IG4_REG_RX_TL, v | IG4_FIFO_MASK); |
| 830 |
sc->cfg.rxfifo_depth = |
| 831 |
(reg_read(sc, IG4_REG_RX_TL) & IG4_FIFO_MASK) + 1; |
| 832 |
reg_write(sc, IG4_REG_RX_TL, v); |
| 833 |
} |
| 834 |
|
| 835 |
/* Override hardware config with precalculated counter values */ |
| 836 |
if (sc->version < nitems(ig4iic_configs)) { |
| 837 |
cfg = &ig4iic_configs[sc->version]; |
| 838 |
if (cfg->bus_speed != 0) |
| 839 |
sc->cfg.bus_speed = cfg->bus_speed; |
| 840 |
if (cfg->ss_scl_hcnt != 0) |
| 841 |
sc->cfg.ss_scl_hcnt = cfg->ss_scl_hcnt; |
| 842 |
if (cfg->ss_scl_lcnt != 0) |
| 843 |
sc->cfg.ss_scl_lcnt = cfg->ss_scl_lcnt; |
| 844 |
if (cfg->fs_scl_hcnt != 0) |
| 845 |
sc->cfg.fs_scl_hcnt = cfg->fs_scl_hcnt; |
| 846 |
if (cfg->fs_scl_lcnt != 0) |
| 847 |
sc->cfg.fs_scl_lcnt = cfg->fs_scl_lcnt; |
| 848 |
if (cfg->sda_tx_hold != 0) |
| 849 |
sc->cfg.sda_tx_hold = cfg->sda_tx_hold; |
| 850 |
if (cfg->txfifo_depth != 0) |
| 851 |
sc->cfg.txfifo_depth = cfg->txfifo_depth; |
| 852 |
if (cfg->rxfifo_depth != 0) |
| 853 |
sc->cfg.rxfifo_depth = cfg->rxfifo_depth; |
| 854 |
} |
| 855 |
|
| 856 |
if (sc->cfg.bus_speed != IG4_CTL_SPEED_STD) |
| 857 |
sc->cfg.bus_speed = IG4_CTL_SPEED_FAST; |
| 858 |
|
| 859 |
#ifdef DEV_ACPI |
| 860 |
/* Evaluate SSCN and FMCN ACPI methods to fetch timings */ |
| 861 |
if (ig4iic_acpi_params(sc, "SSCN", |
| 862 |
&sc->cfg.ss_scl_hcnt, &sc->cfg.ss_scl_lcnt, &sda_tx_hold) == 0 && |
| 863 |
sc->cfg.bus_speed == IG4_CTL_SPEED_STD && |
| 864 |
sda_tx_hold != 0) |
| 865 |
sc->cfg.sda_tx_hold = sda_tx_hold; |
| 866 |
if (ig4iic_acpi_params(sc, "FMCN", |
| 867 |
&sc->cfg.fs_scl_hcnt, &sc->cfg.fs_scl_lcnt, &sda_tx_hold) == 0 && |
| 868 |
sc->cfg.bus_speed == IG4_CTL_SPEED_FAST && |
| 869 |
sda_tx_hold != 0) |
| 870 |
sc->cfg.sda_tx_hold = sda_tx_hold; |
| 871 |
#endif |
| 872 |
} |
| 873 |
|
| 874 |
static int |
| 875 |
ig4iic_set_config(ig4iic_softc_t *sc) |
| 876 |
{ |
| 877 |
uint32_t v; |
| 527 |
|
878 |
|
| 528 |
v = reg_read(sc, IG4_REG_DEVIDLE_CTRL); |
879 |
v = reg_read(sc, IG4_REG_DEVIDLE_CTRL); |
| 529 |
if (sc->version == IG4_SKYLAKE && (v & IG4_RESTORE_REQUIRED) ) { |
880 |
if (sc->version == IG4_SKYLAKE && (v & IG4_RESTORE_REQUIRED) ) { |
| 530 |
reg_write(sc, IG4_REG_DEVIDLE_CTRL, IG4_DEVICE_IDLE | IG4_RESTORE_REQUIRED); |
881 |
reg_write(sc, IG4_REG_DEVIDLE_CTRL, IG4_DEVICE_IDLE | IG4_RESTORE_REQUIRED); |
| 531 |
reg_write(sc, IG4_REG_DEVIDLE_CTRL, 0); |
882 |
reg_write(sc, IG4_REG_DEVIDLE_CTRL, 0); |
|
|
883 |
} |
| 532 |
|
884 |
|
|
|
885 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
| 886 |
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_ASSERT_HSW); |
| 887 |
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_DEASSERT_HSW); |
| 888 |
} else if (sc->version == IG4_SKYLAKE) { |
| 533 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); |
889 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); |
| 534 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL); |
890 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL); |
| 535 |
DELAY(1000); |
|
|
| 536 |
} |
891 |
} |
|
|
892 |
pause("i2crst", 1); |
| 537 |
|
893 |
|
| 538 |
if (sc->version == IG4_ATOM) |
894 |
if (sc->version == IG4_ATOM) |
| 539 |
v = reg_read(sc, IG4_REG_COMP_TYPE); |
895 |
v = reg_read(sc, IG4_REG_COMP_TYPE); |
|
Lines 563-597
ig4iic_attach(ig4iic_softc_t *sc)
Link Here
|
| 563 |
|
919 |
|
| 564 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
920 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
| 565 |
v = reg_read(sc, IG4_REG_COMP_VER); |
921 |
v = reg_read(sc, IG4_REG_COMP_VER); |
| 566 |
if (v < IG4_COMP_MIN_VER) { |
922 |
if (v < IG4_COMP_MIN_VER) |
| 567 |
error = ENXIO; |
923 |
return(ENXIO); |
| 568 |
goto done; |
|
|
| 569 |
} |
| 570 |
} |
924 |
} |
| 571 |
v = reg_read(sc, IG4_REG_SS_SCL_HCNT); |
|
|
| 572 |
v = reg_read(sc, IG4_REG_SS_SCL_LCNT); |
| 573 |
v = reg_read(sc, IG4_REG_FS_SCL_HCNT); |
| 574 |
v = reg_read(sc, IG4_REG_FS_SCL_LCNT); |
| 575 |
v = reg_read(sc, IG4_REG_SDA_HOLD); |
| 576 |
|
925 |
|
| 577 |
v = reg_read(sc, IG4_REG_SS_SCL_HCNT); |
926 |
if (set_controller(sc, 0)) { |
| 578 |
reg_write(sc, IG4_REG_FS_SCL_HCNT, v); |
927 |
device_printf(sc->dev, "controller error during attach-1\n"); |
| 579 |
v = reg_read(sc, IG4_REG_SS_SCL_LCNT); |
928 |
return (ENXIO); |
| 580 |
reg_write(sc, IG4_REG_FS_SCL_LCNT, v); |
929 |
} |
| 581 |
|
930 |
|
| 582 |
/* |
931 |
reg_read(sc, IG4_REG_CLR_INTR); |
| 583 |
* Program based on a 25000 Hz clock. This is a bit of a |
932 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
| 584 |
* hack (obviously). The defaults are 400 and 470 for standard |
933 |
sc->intr_mask = 0; |
| 585 |
* and 60 and 130 for fast. The defaults for standard fail |
934 |
|
| 586 |
* utterly (presumably cause an abort) because the clock time |
935 |
reg_write(sc, IG4_REG_SS_SCL_HCNT, sc->cfg.ss_scl_hcnt); |
| 587 |
* is ~18.8ms by default. This brings it down to ~4ms (for now). |
936 |
reg_write(sc, IG4_REG_SS_SCL_LCNT, sc->cfg.ss_scl_lcnt); |
| 588 |
*/ |
937 |
reg_write(sc, IG4_REG_FS_SCL_HCNT, sc->cfg.fs_scl_hcnt); |
| 589 |
reg_write(sc, IG4_REG_SS_SCL_HCNT, 100); |
938 |
reg_write(sc, IG4_REG_FS_SCL_LCNT, sc->cfg.fs_scl_lcnt); |
| 590 |
reg_write(sc, IG4_REG_SS_SCL_LCNT, 125); |
939 |
reg_write(sc, IG4_REG_SDA_HOLD, sc->cfg.sda_tx_hold); |
| 591 |
reg_write(sc, IG4_REG_FS_SCL_HCNT, 100); |
|
|
| 592 |
reg_write(sc, IG4_REG_FS_SCL_LCNT, 125); |
| 593 |
if (sc->version == IG4_SKYLAKE) |
| 594 |
reg_write(sc, IG4_REG_SDA_HOLD, 28); |
| 595 |
|
940 |
|
| 596 |
/* |
941 |
/* |
| 597 |
* Use a threshold of 1 so we get interrupted on each character, |
942 |
* Use a threshold of 1 so we get interrupted on each character, |
|
Lines 600-612
ig4iic_attach(ig4iic_softc_t *sc)
Link Here
|
| 600 |
* |
945 |
* |
| 601 |
* See ig4_var.h for details on interrupt handler synchronization. |
946 |
* See ig4_var.h for details on interrupt handler synchronization. |
| 602 |
*/ |
947 |
*/ |
| 603 |
reg_write(sc, IG4_REG_RX_TL, 1); |
948 |
reg_write(sc, IG4_REG_RX_TL, 0); |
|
|
949 |
reg_write(sc, IG4_REG_TX_TL, 0); |
| 604 |
|
950 |
|
| 605 |
reg_write(sc, IG4_REG_CTL, |
951 |
reg_write(sc, IG4_REG_CTL, |
| 606 |
IG4_CTL_MASTER | |
952 |
IG4_CTL_MASTER | |
| 607 |
IG4_CTL_SLAVE_DISABLE | |
953 |
IG4_CTL_SLAVE_DISABLE | |
| 608 |
IG4_CTL_RESTARTEN | |
954 |
IG4_CTL_RESTARTEN | |
| 609 |
IG4_CTL_SPEED_STD); |
955 |
(sc->cfg.bus_speed & IG4_CTL_SPEED_MASK)); |
|
|
956 |
|
| 957 |
/* Force setting of the target address on the next transfer */ |
| 958 |
sc->slave_valid = 0; |
| 959 |
|
| 960 |
return (0); |
| 961 |
} |
| 962 |
|
| 963 |
/* |
| 964 |
* Called from ig4iic_pci_attach/detach() |
| 965 |
*/ |
| 966 |
int |
| 967 |
ig4iic_attach(ig4iic_softc_t *sc) |
| 968 |
{ |
| 969 |
int error; |
| 970 |
|
| 971 |
mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_DEF); |
| 972 |
sx_init(&sc->call_lock, "IG4 call lock"); |
| 973 |
|
| 974 |
ig4iic_get_config(sc); |
| 975 |
|
| 976 |
error = ig4iic_set_config(sc); |
| 977 |
if (error) |
| 978 |
goto done; |
| 610 |
|
979 |
|
| 611 |
sc->iicbus = device_add_child(sc->dev, "iicbus", -1); |
980 |
sc->iicbus = device_add_child(sc->dev, "iicbus", -1); |
| 612 |
if (sc->iicbus == NULL) { |
981 |
if (sc->iicbus == NULL) { |
|
Lines 615-639
ig4iic_attach(ig4iic_softc_t *sc)
Link Here
|
| 615 |
goto done; |
984 |
goto done; |
| 616 |
} |
985 |
} |
| 617 |
|
986 |
|
| 618 |
#if 0 |
987 |
if (set_controller(sc, IG4_I2C_ENABLE)) { |
| 619 |
/* |
|
|
| 620 |
* Don't do this, it blows up the PCI config |
| 621 |
*/ |
| 622 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
| 623 |
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_ASSERT_HSW); |
| 624 |
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_DEASSERT_HSW); |
| 625 |
} else if (sc->version = IG4_SKYLAKE) { |
| 626 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); |
| 627 |
reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL); |
| 628 |
} |
| 629 |
#endif |
| 630 |
|
| 631 |
mtx_lock(&sc->io_lock); |
| 632 |
if (set_controller(sc, 0)) |
| 633 |
device_printf(sc->dev, "controller error during attach-1\n"); |
| 634 |
if (set_controller(sc, IG4_I2C_ENABLE)) |
| 635 |
device_printf(sc->dev, "controller error during attach-2\n"); |
988 |
device_printf(sc->dev, "controller error during attach-2\n"); |
| 636 |
mtx_unlock(&sc->io_lock); |
989 |
error = ENXIO; |
|
|
990 |
goto done; |
| 991 |
} |
| 992 |
if (set_controller(sc, 0)) { |
| 993 |
device_printf(sc->dev, "controller error during attach-3\n"); |
| 994 |
error = ENXIO; |
| 995 |
goto done; |
| 996 |
} |
| 637 |
error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, |
997 |
error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE, |
| 638 |
NULL, ig4iic_intr, sc, &sc->intr_handle); |
998 |
NULL, ig4iic_intr, sc, &sc->intr_handle); |
| 639 |
if (error) { |
999 |
if (error) { |
|
Lines 641-678
ig4iic_attach(ig4iic_softc_t *sc)
Link Here
|
| 641 |
"Unable to setup irq: error %d\n", error); |
1001 |
"Unable to setup irq: error %d\n", error); |
| 642 |
} |
1002 |
} |
| 643 |
|
1003 |
|
| 644 |
sc->enum_hook.ich_func = ig4iic_start; |
|
|
| 645 |
sc->enum_hook.ich_arg = sc->dev; |
| 646 |
|
| 647 |
/* |
| 648 |
* We have to wait until interrupts are enabled. I2C read and write |
| 649 |
* only works if the interrupts are available. |
| 650 |
*/ |
| 651 |
if (config_intrhook_establish(&sc->enum_hook) != 0) |
| 652 |
error = ENOMEM; |
| 653 |
else |
| 654 |
error = 0; |
| 655 |
|
| 656 |
done: |
| 657 |
return (error); |
| 658 |
} |
| 659 |
|
| 660 |
void |
| 661 |
ig4iic_start(void *xdev) |
| 662 |
{ |
| 663 |
int error; |
| 664 |
ig4iic_softc_t *sc; |
| 665 |
device_t dev = (device_t)xdev; |
| 666 |
|
| 667 |
sc = device_get_softc(dev); |
| 668 |
|
| 669 |
config_intrhook_disestablish(&sc->enum_hook); |
| 670 |
|
| 671 |
error = bus_generic_attach(sc->dev); |
1004 |
error = bus_generic_attach(sc->dev); |
| 672 |
if (error) { |
1005 |
if (error) { |
| 673 |
device_printf(sc->dev, |
1006 |
device_printf(sc->dev, |
| 674 |
"failed to attach child: error %d\n", error); |
1007 |
"failed to attach child: error %d\n", error); |
| 675 |
} |
1008 |
} |
|
|
1009 |
|
| 1010 |
done: |
| 1011 |
return (error); |
| 676 |
} |
1012 |
} |
| 677 |
|
1013 |
|
| 678 |
int |
1014 |
int |
|
Lines 691-704
ig4iic_detach(ig4iic_softc_t *sc)
Link Here
|
| 691 |
bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); |
1027 |
bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle); |
| 692 |
|
1028 |
|
| 693 |
sx_xlock(&sc->call_lock); |
1029 |
sx_xlock(&sc->call_lock); |
| 694 |
mtx_lock(&sc->io_lock); |
|
|
| 695 |
|
1030 |
|
| 696 |
sc->iicbus = NULL; |
1031 |
sc->iicbus = NULL; |
| 697 |
sc->intr_handle = NULL; |
1032 |
sc->intr_handle = NULL; |
| 698 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
1033 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
| 699 |
set_controller(sc, 0); |
1034 |
set_controller(sc, 0); |
| 700 |
|
1035 |
|
| 701 |
mtx_unlock(&sc->io_lock); |
|
|
| 702 |
sx_xunlock(&sc->call_lock); |
1036 |
sx_xunlock(&sc->call_lock); |
| 703 |
|
1037 |
|
| 704 |
mtx_destroy(&sc->io_lock); |
1038 |
mtx_destroy(&sc->io_lock); |
|
Lines 707-712
ig4iic_detach(ig4iic_softc_t *sc)
Link Here
|
| 707 |
return (0); |
1041 |
return (0); |
| 708 |
} |
1042 |
} |
| 709 |
|
1043 |
|
|
|
1044 |
int |
| 1045 |
ig4iic_suspend(ig4iic_softc_t *sc) |
| 1046 |
{ |
| 1047 |
int error; |
| 1048 |
|
| 1049 |
/* suspend all children */ |
| 1050 |
error = bus_generic_suspend(sc->dev); |
| 1051 |
|
| 1052 |
/* |
| 1053 |
* set IG4_DEVICE_IDLE and IG4_RESTORE_REQUIRED |
| 1054 |
* to place the device in the idle state, just to be safe |
| 1055 |
*/ |
| 1056 |
if (sc->version == IG4_SKYLAKE) { |
| 1057 |
sx_xlock(&sc->call_lock); |
| 1058 |
|
| 1059 |
reg_write(sc, IG4_REG_DEVIDLE_CTRL, |
| 1060 |
IG4_DEVICE_IDLE | IG4_RESTORE_REQUIRED); |
| 1061 |
|
| 1062 |
sx_xunlock(&sc->call_lock); |
| 1063 |
} |
| 1064 |
|
| 1065 |
return (error); |
| 1066 |
} |
| 1067 |
|
| 1068 |
int ig4iic_resume(ig4iic_softc_t *sc) |
| 1069 |
{ |
| 1070 |
int error; |
| 1071 |
|
| 1072 |
sx_xlock(&sc->call_lock); |
| 1073 |
/* Use polling as interrupts might not be available at this moment */ |
| 1074 |
sc->resume = true; |
| 1075 |
if (ig4iic_set_config(sc)) |
| 1076 |
device_printf(sc->dev, "controller error during resume\n"); |
| 1077 |
sx_xunlock(&sc->call_lock); |
| 1078 |
|
| 1079 |
error = bus_generic_resume(sc->dev); |
| 1080 |
|
| 1081 |
sx_xlock(&sc->call_lock); |
| 1082 |
sc->resume = false; |
| 1083 |
sx_xunlock(&sc->call_lock); |
| 1084 |
|
| 1085 |
return (error); |
| 1086 |
} |
| 1087 |
|
| 710 |
/* |
1088 |
/* |
| 711 |
* Interrupt Operation, see ig4_var.h for locking semantics. |
1089 |
* Interrupt Operation, see ig4_var.h for locking semantics. |
| 712 |
*/ |
1090 |
*/ |
|
Lines 717-745
ig4iic_intr(void *cookie)
Link Here
|
| 717 |
uint32_t status; |
1095 |
uint32_t status; |
| 718 |
|
1096 |
|
| 719 |
mtx_lock(&sc->io_lock); |
1097 |
mtx_lock(&sc->io_lock); |
| 720 |
/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/ |
1098 |
if (sc->intr_mask != 0) { |
| 721 |
reg_read(sc, IG4_REG_CLR_INTR); |
1099 |
status = reg_read(sc, IG4_REG_INTR_STAT); |
| 722 |
status = reg_read(sc, IG4_REG_I2C_STA); |
1100 |
set_intr_mask(sc, 0); |
| 723 |
while (status & IG4_STATUS_RX_NOTEMPTY) { |
1101 |
sc->error = intrstat2iic(sc, status); |
| 724 |
sc->rbuf[sc->rnext & IG4_RBUFMASK] = |
1102 |
wakeup(sc); |
| 725 |
(uint8_t)reg_read(sc, IG4_REG_DATA_CMD); |
1103 |
} else |
| 726 |
++sc->rnext; |
1104 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
| 727 |
status = reg_read(sc, IG4_REG_I2C_STA); |
|
|
| 728 |
} |
| 729 |
|
| 730 |
/* |
| 731 |
* Workaround to trigger pending interrupt if IG4_REG_INTR_STAT |
| 732 |
* is changed after clearing it |
| 733 |
*/ |
| 734 |
if (sc->access_intr_mask != 0) { |
| 735 |
status = reg_read(sc, IG4_REG_INTR_MASK); |
| 736 |
if (status != 0) { |
| 737 |
reg_write(sc, IG4_REG_INTR_MASK, 0); |
| 738 |
reg_write(sc, IG4_REG_INTR_MASK, status); |
| 739 |
} |
| 740 |
} |
| 741 |
|
| 742 |
wakeup(sc); |
| 743 |
mtx_unlock(&sc->io_lock); |
1105 |
mtx_unlock(&sc->io_lock); |
| 744 |
} |
1106 |
} |
| 745 |
|
1107 |
|
|
Lines 773-782
ig4iic_dump(ig4iic_softc_t *sc)
Link Here
|
| 773 |
REGDUMP(sc, IG4_REG_DMA_RDLR); |
1135 |
REGDUMP(sc, IG4_REG_DMA_RDLR); |
| 774 |
REGDUMP(sc, IG4_REG_SDA_SETUP); |
1136 |
REGDUMP(sc, IG4_REG_SDA_SETUP); |
| 775 |
REGDUMP(sc, IG4_REG_ENABLE_STATUS); |
1137 |
REGDUMP(sc, IG4_REG_ENABLE_STATUS); |
| 776 |
if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { |
1138 |
REGDUMP(sc, IG4_REG_COMP_PARAM1); |
| 777 |
REGDUMP(sc, IG4_REG_COMP_PARAM1); |
1139 |
REGDUMP(sc, IG4_REG_COMP_VER); |
| 778 |
REGDUMP(sc, IG4_REG_COMP_VER); |
|
|
| 779 |
} |
| 780 |
if (sc->version == IG4_ATOM) { |
1140 |
if (sc->version == IG4_ATOM) { |
| 781 |
REGDUMP(sc, IG4_REG_COMP_TYPE); |
1141 |
REGDUMP(sc, IG4_REG_COMP_TYPE); |
| 782 |
REGDUMP(sc, IG4_REG_CLK_PARMS); |
1142 |
REGDUMP(sc, IG4_REG_CLK_PARMS); |