This source file includes following definitions.
- amdpm_match
- amdpm_attach
- amdpm_rnd_callout
- amdpm_get_timecount
- amdpm_i2c_acquire_bus
- amdpm_i2c_release_bus
- amdpm_i2c_exec
- amdpm_intr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/device.h>
58 #include <sys/kernel.h>
59 #include <sys/rwlock.h>
60 #include <sys/proc.h>
61 #include <sys/timeout.h>
62 #ifdef __HAVE_TIMECOUNTER
63 #include <sys/timetc.h>
64 #endif
65
66 #include <machine/bus.h>
67
68 #include <dev/pci/pcivar.h>
69 #include <dev/pci/pcireg.h>
70 #include <dev/pci/pcidevs.h>
71
72 #include <dev/rndvar.h>
73 #include <dev/i2c/i2cvar.h>
74
75 #ifdef AMDPM_DEBUG
76 #define DPRINTF(x...) printf(x)
77 #else
78 #define DPRINTF(x...)
79 #endif
80
81 #define AMDPM_SMBUS_DELAY 100
82 #define AMDPM_SMBUS_TIMEOUT 1
83
84 #ifdef __HAVE_TIMECOUNTER
85 u_int amdpm_get_timecount(struct timecounter *tc);
86
87 #ifndef AMDPM_FREQUENCY
88 #define AMDPM_FREQUENCY 3579545
89 #endif
90
91 static struct timecounter amdpm_timecounter = {
92 amdpm_get_timecount,
93 0,
94 0xffffff,
95 AMDPM_FREQUENCY,
96 "AMDPM",
97 1000
98 };
99 #endif
100
101 #define AMDPM_CONFREG 0x40
102
103
104 #define AMDPM_RNGEN 0x00000080
105 #define AMDPM_STOPTMR 0x00000040
106
107
108 #define AMDPM_PMIOEN 0x00008000
109 #define AMDPM_TMRRST 0x00004000
110 #define AMDPM_TMR32 0x00000800
111
112
113
114
115 #define AMDPM_PMPTR 0x58
116
117 #define NFPM_PMPTR 0x14
118
119 #define AMDPM_PMBASE(x) ((x) & 0xff00)
120 #define AMDPM_PMSIZE 256
121
122
123 #define AMDPM_TMR 0x08
124
125 #define AMDPM_RNGDATA 0xf0
126 #define AMDPM_RNGSTAT 0xf4
127 #define AMDPM_RNGDONE 0x00000001
128
129 #define AMDPM_SMB_REGS 0xe0
130 #define AMDPM_SMB_SIZE 0xf
131 #define AMDPM_SMBSTAT 0x0
132 #define AMDPM_SMBSTAT_ABRT (1 << 0)
133 #define AMDPM_SMBSTAT_COL (1 << 1)
134 #define AMDPM_SMBSTAT_PRERR (1 << 2)
135 #define AMDPM_SMBSTAT_HBSY (1 << 3)
136 #define AMDPM_SMBSTAT_CYC (1 << 4)
137 #define AMDPM_SMBSTAT_TO (1 << 5)
138 #define AMDPM_SMBSTAT_SNP (1 << 8)
139 #define AMDPM_SMBSTAT_SLV (1 << 9)
140 #define AMDPM_SMBSTAT_SMBA (1 << 10)
141 #define AMDPM_SMBSTAT_BSY (1 << 11)
142 #define AMDPM_SMBSTAT_BITS "\020\001ABRT\002COL\003PRERR\004HBSY\005CYC\006TO\011SNP\012SLV\013SMBA\014BSY"
143 #define AMDPM_SMBCTL 0x2
144 #define AMDPM_SMBCTL_CMD_QUICK 0
145 #define AMDPM_SMBCTL_CMD_BYTE 1
146 #define AMDPM_SMBCTL_CMD_BDATA 2
147 #define AMDPM_SMBCTL_CMD_WDATA 3
148 #define AMDPM_SMBCTL_CMD_PCALL 4
149 #define AMDPM_SMBCTL_CMD_BLOCK 5
150 #define AMDPM_SMBCTL_START (1 << 3)
151 #define AMDPM_SMBCTL_CYCEN (1 << 4)
152 #define AMDPM_SMBCTL_ABORT (1 << 5)
153 #define AMDPM_SMBCTL_SNPEN (1 << 8)
154 #define AMDPM_SMBCTL_SLVEN (1 << 9)
155 #define AMDPM_SMBCTL_SMBAEN (1 << 10)
156 #define AMDPM_SMBADDR 0x4
157 #define AMDPM_SMBADDR_READ (1 << 0)
158 #define AMDPM_SMBADDR_ADDR(x) (((x) & 0x7f) << 1)
159 #define AMDPM_SMBDATA 0x6
160 #define AMDPM_SMBCMD 0x8
161
162
163 struct amdpm_softc {
164 struct device sc_dev;
165
166 pci_chipset_tag_t sc_pc;
167 pcitag_t sc_tag;
168
169 bus_space_tag_t sc_iot;
170 bus_space_handle_t sc_ioh;
171 bus_space_handle_t sc_i2c_ioh;
172 int sc_poll;
173
174 struct timeout sc_rnd_ch;
175
176 struct i2c_controller sc_i2c_tag;
177 struct rwlock sc_i2c_lock;
178 struct {
179 i2c_op_t op;
180 void *buf;
181 size_t len;
182 int flags;
183 volatile int error;
184 } sc_i2c_xfer;
185 };
186
187 int amdpm_match(struct device *, void *, void *);
188 void amdpm_attach(struct device *, struct device *, void *);
189 void amdpm_rnd_callout(void *);
190
191 int amdpm_i2c_acquire_bus(void *, int);
192 void amdpm_i2c_release_bus(void *, int);
193 int amdpm_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
194 void *, size_t, int);
195
196 int amdpm_intr(void *);
197
198 struct cfattach amdpm_ca = {
199 sizeof(struct amdpm_softc), amdpm_match, amdpm_attach
200 };
201
202 struct cfdriver amdpm_cd = {
203 NULL, "amdpm", DV_DULL
204 };
205
206 const struct pci_matchid amdpm_ids[] = {
207 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC756_PMC },
208 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_766_PMC },
209 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_PBC768_PMC },
210 { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_8111_PMC },
211 { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_SMB }
212 };
213
214 int
215 amdpm_match(struct device *parent, void *match, void *aux)
216 {
217 return (pci_matchbyid(aux, amdpm_ids,
218 sizeof(amdpm_ids) / sizeof(amdpm_ids[0])));
219 }
220
221 void
222 amdpm_attach(struct device *parent, struct device *self, void *aux)
223 {
224 struct amdpm_softc *sc = (struct amdpm_softc *) self;
225 struct pci_attach_args *pa = aux;
226 struct i2cbus_attach_args iba;
227 pcireg_t cfg_reg, reg;
228 int i;
229
230 sc->sc_pc = pa->pa_pc;
231 sc->sc_tag = pa->pa_tag;
232 sc->sc_iot = pa->pa_iot;
233 sc->sc_poll = 1;
234
235
236 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AMD) {
237 cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_CONFREG);
238 if ((cfg_reg & AMDPM_PMIOEN) == 0) {
239 printf(": PMxx space isn't enabled\n");
240 return;
241 }
242
243 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AMDPM_PMPTR);
244 if (AMDPM_PMBASE(reg) == 0 ||
245 bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_PMSIZE,
246 0, &sc->sc_ioh)) {
247 printf("\n");
248 return;
249 }
250 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, AMDPM_SMB_REGS,
251 AMDPM_SMB_SIZE, &sc->sc_i2c_ioh)) {
252 printf(": failed to map I2C subregion\n");
253 return;
254 }
255
256 #ifdef __HAVE_TIMECOUNTER
257 if ((cfg_reg & AMDPM_TMRRST) == 0 &&
258 (cfg_reg & AMDPM_STOPTMR) == 0 &&
259 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC) {
260 printf(": %d-bit timer at %dHz",
261 (cfg_reg & AMDPM_TMR32) ? 32 : 24,
262 amdpm_timecounter.tc_frequency);
263
264 amdpm_timecounter.tc_priv = sc;
265 if (cfg_reg & AMDPM_TMR32)
266 amdpm_timecounter.tc_counter_mask = 0xffffffffu;
267 tc_init(&amdpm_timecounter);
268 }
269 #endif
270 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_PBC768_PMC ||
271 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AMD_8111_PMC) {
272 if ((cfg_reg & AMDPM_RNGEN) ==0) {
273 pci_conf_write(pa->pa_pc, pa->pa_tag,
274 AMDPM_CONFREG, cfg_reg | AMDPM_RNGEN);
275 cfg_reg = pci_conf_read(pa->pa_pc, pa->pa_tag,
276 AMDPM_CONFREG);
277 }
278 if (cfg_reg & AMDPM_RNGEN) {
279
280 (void) bus_space_read_4(sc->sc_iot, sc->sc_ioh,
281 AMDPM_RNGDATA);
282 for (i = 1000; i--; ) {
283 if (bus_space_read_1(sc->sc_iot,
284 sc->sc_ioh, AMDPM_RNGSTAT) &
285 AMDPM_RNGDONE)
286 break;
287 DELAY(10);
288 }
289 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh,
290 AMDPM_RNGSTAT) & AMDPM_RNGDONE) {
291 printf(": rng active");
292 timeout_set(&sc->sc_rnd_ch,
293 amdpm_rnd_callout, sc);
294 amdpm_rnd_callout(sc);
295 }
296 }
297 }
298 } else if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NVIDIA) {
299 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, NFPM_PMPTR);
300 if (AMDPM_PMBASE(reg) == 0 ||
301 bus_space_map(sc->sc_iot, AMDPM_PMBASE(reg), AMDPM_SMB_SIZE, 0,
302 &sc->sc_i2c_ioh)) {
303 printf(": failed to map I2C subregion\n");
304 return;
305 }
306 }
307 printf("\n");
308
309
310 rw_init(&sc->sc_i2c_lock, "iiclk");
311 sc->sc_i2c_tag.ic_cookie = sc;
312 sc->sc_i2c_tag.ic_acquire_bus = amdpm_i2c_acquire_bus;
313 sc->sc_i2c_tag.ic_release_bus = amdpm_i2c_release_bus;
314 sc->sc_i2c_tag.ic_exec = amdpm_i2c_exec;
315
316 bzero(&iba, sizeof(iba));
317 iba.iba_name = "iic";
318 iba.iba_tag = &sc->sc_i2c_tag;
319 config_found(self, &iba, iicbus_print);
320 }
321
322 void
323 amdpm_rnd_callout(void *v)
324 {
325 struct amdpm_softc *sc = v;
326 u_int32_t reg;
327
328 if ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGSTAT) &
329 AMDPM_RNGDONE) != 0) {
330 reg = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_RNGDATA);
331 add_true_randomness(reg);
332 }
333 timeout_add(&sc->sc_rnd_ch, 1);
334 }
335
336 #ifdef __HAVE_TIMECOUNTER
337 u_int
338 amdpm_get_timecount(struct timecounter *tc)
339 {
340 struct amdpm_softc *sc = tc->tc_priv;
341 u_int u2;
342 #if 0
343 u_int u1, u3;
344 #endif
345
346 u2 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
347 #if 0
348 u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
349 do {
350 u1 = u2;
351 u2 = u3;
352 u3 = bus_space_read_4(sc->sc_iot, sc->sc_ioh, AMDPM_TMR);
353 } while (u1 > u2 || u2 > u3);
354 #endif
355 return (u2);
356 }
357 #endif
358
359 int
360 amdpm_i2c_acquire_bus(void *cookie, int flags)
361 {
362 struct amdpm_softc *sc = cookie;
363
364 if (cold || sc->sc_poll || (flags & I2C_F_POLL))
365 return (0);
366
367 return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR));
368 }
369
370 void
371 amdpm_i2c_release_bus(void *cookie, int flags)
372 {
373 struct amdpm_softc *sc = cookie;
374
375 if (cold || sc->sc_poll || (flags & I2C_F_POLL))
376 return;
377
378 rw_exit(&sc->sc_i2c_lock);
379 }
380
381 int
382 amdpm_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
383 const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
384 {
385 struct amdpm_softc *sc = cookie;
386 u_int8_t *b;
387 u_int16_t st, ctl, data;
388 int retries;
389
390 DPRINTF("%s: exec: op %d, addr 0x%02x, cmdlen %d, len %d, "
391 "flags 0x%02x\n", sc->sc_dev.dv_xname, op, addr, cmdlen,
392 len, flags);
393
394
395 for (retries = 100; retries > 0; retries--) {
396 st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
397 if (!(st & AMDPM_SMBSTAT_BSY))
398 break;
399 DELAY(AMDPM_SMBUS_DELAY);
400 }
401 DPRINTF("%s: exec: st 0x%b\n", sc->sc_dev.dv_xname, st,
402 AMDPM_SMBSTAT_BITS);
403 if (st & AMDPM_SMBSTAT_BSY)
404 return (1);
405
406 if (cold || sc->sc_poll)
407 flags |= I2C_F_POLL;
408
409 if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2)
410 return (1);
411
412
413 sc->sc_i2c_xfer.op = op;
414 sc->sc_i2c_xfer.buf = buf;
415 sc->sc_i2c_xfer.len = len;
416 sc->sc_i2c_xfer.flags = flags;
417 sc->sc_i2c_xfer.error = 0;
418
419
420 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBADDR,
421 AMDPM_SMBADDR_ADDR(addr) |
422 (I2C_OP_READ_P(op) ? AMDPM_SMBADDR_READ : 0));
423
424 b = (void *)cmdbuf;
425 if (cmdlen > 0)
426
427 bus_space_write_1(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCMD, b[0]);
428
429 if (I2C_OP_WRITE_P(op)) {
430
431 data = 0;
432 b = buf;
433 if (len > 0)
434 data = b[0];
435 if (len > 1)
436 data |= ((u_int16_t)b[1] << 8);
437 if (len > 0)
438 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh,
439 AMDPM_SMBDATA, data);
440 }
441
442
443 if (len == 0)
444 ctl = AMDPM_SMBCTL_CMD_BYTE;
445 else if (len == 1)
446 ctl = AMDPM_SMBCTL_CMD_BDATA;
447 else if (len == 2)
448 ctl = AMDPM_SMBCTL_CMD_WDATA;
449
450 if ((flags & I2C_F_POLL) == 0)
451 ctl |= AMDPM_SMBCTL_CYCEN;
452
453
454 ctl |= AMDPM_SMBCTL_START;
455 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCTL, ctl);
456
457 if (flags & I2C_F_POLL) {
458
459 DELAY(AMDPM_SMBUS_DELAY);
460 for (retries = 1000; retries > 0; retries--) {
461 st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh,
462 AMDPM_SMBSTAT);
463 if ((st & AMDPM_SMBSTAT_HBSY) == 0)
464 break;
465 DELAY(AMDPM_SMBUS_DELAY);
466 }
467 if (st & AMDPM_SMBSTAT_HBSY)
468 goto timeout;
469 amdpm_intr(sc);
470 } else {
471
472 if (tsleep(sc, PRIBIO, "iicexec", AMDPM_SMBUS_TIMEOUT * hz))
473 goto timeout;
474 }
475
476 if (sc->sc_i2c_xfer.error)
477 return (1);
478
479 return (0);
480
481 timeout:
482
483
484
485 printf("%s: exec: op %d, addr 0x%02x, cmdlen %d, len %d, "
486 "flags 0x%02x: timeout, status 0x%b\n",
487 sc->sc_dev.dv_xname, op, addr, cmdlen, len, flags,
488 st, AMDPM_SMBSTAT_BITS);
489 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBCTL,
490 AMDPM_SMBCTL_ABORT);
491 DELAY(AMDPM_SMBUS_DELAY);
492 st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
493 if ((st & AMDPM_SMBSTAT_ABRT) == 0)
494 printf("%s: abort failed, status 0x%b\n",
495 sc->sc_dev.dv_xname, st, AMDPM_SMBSTAT_BITS);
496 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT, st);
497 return (1);
498 }
499
500 int
501 amdpm_intr(void *arg)
502 {
503 struct amdpm_softc *sc = arg;
504 u_int16_t st, data;
505 u_int8_t *b;
506 size_t len;
507
508
509 st = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT);
510 if ((st & AMDPM_SMBSTAT_HBSY) != 0 || (st & (AMDPM_SMBSTAT_ABRT |
511 AMDPM_SMBSTAT_COL | AMDPM_SMBSTAT_PRERR | AMDPM_SMBSTAT_CYC |
512 AMDPM_SMBSTAT_TO | AMDPM_SMBSTAT_SNP | AMDPM_SMBSTAT_SLV |
513 AMDPM_SMBSTAT_SMBA)) == 0)
514
515 return (0);
516
517 DPRINTF("%s: intr: st 0x%b\n", sc->sc_dev.dv_xname, st,
518 AMDPM_SMBSTAT_BITS);
519
520
521 bus_space_write_2(sc->sc_iot, sc->sc_i2c_ioh, AMDPM_SMBSTAT, st);
522
523
524 if (st & (AMDPM_SMBSTAT_COL | AMDPM_SMBSTAT_PRERR |
525 AMDPM_SMBSTAT_TO)) {
526 sc->sc_i2c_xfer.error = 1;
527 goto done;
528 }
529
530 if (st & AMDPM_SMBSTAT_CYC) {
531 if (I2C_OP_WRITE_P(sc->sc_i2c_xfer.op))
532 goto done;
533
534
535 b = sc->sc_i2c_xfer.buf;
536 len = sc->sc_i2c_xfer.len;
537 if (len > 0) {
538 data = bus_space_read_2(sc->sc_iot, sc->sc_i2c_ioh,
539 AMDPM_SMBDATA);
540 b[0] = data & 0xff;
541 }
542 if (len > 1)
543 b[1] = (data >> 8) & 0xff;
544 }
545
546 done:
547 if ((sc->sc_i2c_xfer.flags & I2C_F_POLL) == 0)
548 wakeup(sc);
549 return (1);
550 }