FreeBSD/Linux Kernel Cross Reference
sys/pci/amdpm.c
1 /*-
2 * Copyright (c) 2000 Matthew C. Forman
3 *
4 * Based (heavily) on alpm.c which is:
5 *
6 * Copyright (c) 1998, 1999 Nicolas Souchu
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 /*
32 * Power management function/SMBus function support for the AMD 756 chip.
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: releng/5.4/sys/pci/amdpm.c 142884 2005-03-01 08:11:52Z imp $");
37
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <sys/uio.h>
44
45 #include <machine/bus_pio.h>
46 #include <machine/bus_memio.h>
47 #include <machine/bus.h>
48 #include <machine/clock.h>
49 #include <machine/resource.h>
50 #include <sys/rman.h>
51
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/pcireg.h>
54
55 #include <dev/iicbus/iiconf.h>
56 #include <dev/smbus/smbconf.h>
57 #include "smbus_if.h"
58
59 #define AMDPM_DEBUG(x) if (amdpm_debug) (x)
60
61 #ifdef DEBUG
62 static int amdpm_debug = 1;
63 #else
64 static int amdpm_debug = 0;
65 #endif
66
67 #define AMDPM_VENDORID_AMD 0x1022
68 #define AMDPM_DEVICEID_AMD756PM 0x740b
69 #define AMDPM_DEVICEID_AMD766PM 0x7413
70 #define AMDPM_DEVICEID_AMD768PM 0x7443
71 #define AMDPM_DEVICEID_AMD8111PM 0x746A
72
73 /* nVidia nForce chipset */
74 #define AMDPM_VENDORID_NVIDIA 0x10de
75 #define AMDPM_DEVICEID_NF_SMB 0x01b4
76
77 /* PCI Configuration space registers */
78 #define AMDPCI_PMBASE 0x58
79 #define NFPCI_PMBASE 0x14
80
81 #define AMDPCI_GEN_CONFIG_PM 0x41
82 #define AMDPCI_PMIOEN (1<<7)
83
84 #define AMDPCI_SCIINT_CONFIG_PM 0x42
85 #define AMDPCI_SCISEL_IRQ11 11
86
87 #define AMDPCI_REVID 0x08
88
89 /*
90 * I/O registers.
91 * Base address programmed via AMDPCI_PMBASE.
92 */
93
94 #define AMDSMB_GLOBAL_STATUS (0x00)
95 #define AMDSMB_GS_TO_STS (1<<5)
96 #define AMDSMB_GS_HCYC_STS (1<<4)
97 #define AMDSMB_GS_HST_STS (1<<3)
98 #define AMDSMB_GS_PRERR_STS (1<<2)
99 #define AMDSMB_GS_COL_STS (1<<1)
100 #define AMDSMB_GS_ABRT_STS (1<<0)
101 #define AMDSMB_GS_CLEAR_STS (AMDSMB_GS_TO_STS|AMDSMB_GS_HCYC_STS|AMDSMB_GS_PRERR_STS|AMDSMB_GS_COL_STS|AMDSMB_GS_ABRT_STS)
102
103 #define AMDSMB_GLOBAL_ENABLE (0x02)
104 #define AMDSMB_GE_ABORT (1<<5)
105 #define AMDSMB_GE_HCYC_EN (1<<4)
106 #define AMDSMB_GE_HOST_STC (1<<3)
107 #define AMDSMB_GE_CYC_QUICK 0
108 #define AMDSMB_GE_CYC_BYTE 1
109 #define AMDSMB_GE_CYC_BDATA 2
110 #define AMDSMB_GE_CYC_WDATA 3
111 #define AMDSMB_GE_CYC_PROCCALL 4
112 #define AMDSMB_GE_CYC_BLOCK 5
113
114 #define AMDSMB_HSTADDR (0x04)
115 #define AMDSMB_HSTDATA (0x06)
116 #define AMDSMB_HSTCMD (0x08)
117 #define AMDSMB_HSTDFIFO (0x09)
118 #define AMDSMB_HSLVDATA (0x0A)
119 #define AMDSMB_HSLVDA (0x0C)
120 #define AMDSMB_HSLVDDR (0x0E)
121 #define AMDSMB_SNPADDR (0x0F)
122
123 struct amdpm_softc {
124 int base;
125 int rid;
126 struct resource *res;
127 bus_space_tag_t smbst;
128 bus_space_handle_t smbsh;
129
130 device_t smbus;
131 };
132
133 #define AMDPM_SMBINB(amdpm,register) \
134 (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register))
135 #define AMDPM_SMBOUTB(amdpm,register,value) \
136 (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value))
137 #define AMDPM_SMBINW(amdpm,register) \
138 (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register))
139 #define AMDPM_SMBOUTW(amdpm,register,value) \
140 (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value))
141
142 static int
143 amdpm_probe(device_t dev)
144 {
145 u_long base;
146 u_int16_t vid;
147 u_int16_t did;
148
149 vid = pci_get_vendor(dev);
150 did = pci_get_device(dev);
151 if ((vid == AMDPM_VENDORID_AMD) &&
152 ((did == AMDPM_DEVICEID_AMD756PM) ||
153 (did == AMDPM_DEVICEID_AMD766PM) ||
154 (did == AMDPM_DEVICEID_AMD768PM) ||
155 (did == AMDPM_DEVICEID_AMD8111PM))) {
156 device_set_desc(dev, "AMD 756/766/768/8111 Power Management Controller");
157
158 /*
159 * We have to do this, since the BIOS won't give us the
160 * resource info (not mine, anyway).
161 */
162 base = pci_read_config(dev, AMDPCI_PMBASE, 4);
163 base &= 0xff00;
164 bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE,
165 base+0xe0, 32);
166 return (BUS_PROBE_DEFAULT);
167 }
168
169 if ((vid == AMDPM_VENDORID_NVIDIA) &&
170 (did == AMDPM_DEVICEID_NF_SMB)) {
171 device_set_desc(dev, "nForce SMBus Controller");
172
173 /*
174 * We have to do this, since the BIOS won't give us the
175 * resource info (not mine, anyway).
176 */
177 base = pci_read_config(dev, NFPCI_PMBASE, 4);
178 base &= 0xff00;
179 bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE,
180 base, 32);
181
182 return (BUS_PROBE_DEFAULT);
183 }
184
185 return ENXIO;
186 }
187
188 static int
189 amdpm_attach(device_t dev)
190 {
191 struct amdpm_softc *amdpm_sc = device_get_softc(dev);
192 u_char val_b;
193
194 /* Enable I/O block access */
195 val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1);
196 pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1);
197
198 /* Allocate I/O space */
199 if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD)
200 amdpm_sc->rid = AMDPCI_PMBASE;
201 else
202 amdpm_sc->rid = NFPCI_PMBASE;
203 amdpm_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
204 &amdpm_sc->rid, RF_ACTIVE);
205
206 if (amdpm_sc->res == NULL) {
207 device_printf(dev, "could not map i/o space\n");
208 return (ENXIO);
209 }
210
211 amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res);
212 amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
213
214 /* Allocate a new smbus device */
215 amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
216 if (!amdpm_sc->smbus)
217 return (EINVAL);
218
219 bus_generic_attach(dev);
220
221 return (0);
222 }
223
224 static int
225 amdpm_detach(device_t dev)
226 {
227 struct amdpm_softc *amdpm_sc = device_get_softc(dev);
228
229 if (amdpm_sc->smbus) {
230 device_delete_child(dev, amdpm_sc->smbus);
231 amdpm_sc->smbus = NULL;
232 }
233
234 if (amdpm_sc->res)
235 bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid,
236 amdpm_sc->res);
237
238 return (0);
239 }
240
241 static int
242 amdpm_callback(device_t dev, int index, caddr_t *data)
243 {
244 int error = 0;
245
246 switch (index) {
247 case SMB_REQUEST_BUS:
248 case SMB_RELEASE_BUS:
249 break;
250 default:
251 error = EINVAL;
252 }
253
254 return (error);
255 }
256
257 static int
258 amdpm_clear(struct amdpm_softc *sc)
259 {
260 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
261 DELAY(10);
262
263 return (0);
264 }
265
266 #if 0
267 static int
268 amdpm_abort(struct amdpm_softc *sc)
269 {
270 u_short l;
271
272 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
273 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT);
274
275 return (0);
276 }
277 #endif
278
279 static int
280 amdpm_idle(struct amdpm_softc *sc)
281 {
282 u_short sts;
283
284 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
285
286 AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts));
287
288 return (~(sts & AMDSMB_GS_HST_STS));
289 }
290
291 /*
292 * Poll the SMBus controller
293 */
294 static int
295 amdpm_wait(struct amdpm_softc *sc)
296 {
297 int count = 10000;
298 u_short sts = 0;
299 int error;
300
301 /* Wait for command to complete (SMBus controller is idle) */
302 while(count--) {
303 DELAY(10);
304 sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
305 if (!(sts & AMDSMB_GS_HST_STS))
306 break;
307 }
308
309 AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count));
310
311 error = SMB_ENOERR;
312
313 if (!count)
314 error |= SMB_ETIMEOUT;
315
316 if (sts & AMDSMB_GS_ABRT_STS)
317 error |= SMB_EABORT;
318
319 if (sts & AMDSMB_GS_COL_STS)
320 error |= SMB_ENOACK;
321
322 if (sts & AMDSMB_GS_PRERR_STS)
323 error |= SMB_EBUSERR;
324
325 if (error != SMB_ENOERR)
326 amdpm_clear(sc);
327
328 return (error);
329 }
330
331 static int
332 amdpm_quick(device_t dev, u_char slave, int how)
333 {
334 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
335 int error;
336 u_short l;
337
338 amdpm_clear(sc);
339 if (!amdpm_idle(sc))
340 return (EBUSY);
341
342 switch (how) {
343 case SMB_QWRITE:
344 AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave));
345 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
346 break;
347 case SMB_QREAD:
348 AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave));
349 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
350 break;
351 default:
352 panic("%s: unknown QUICK command (%x)!", __func__, how);
353 }
354 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
355 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC);
356
357 error = amdpm_wait(sc);
358
359 AMDPM_DEBUG(printf(", error=0x%x\n", error));
360
361 return (error);
362 }
363
364 static int
365 amdpm_sendb(device_t dev, u_char slave, char byte)
366 {
367 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
368 int error;
369 u_short l;
370
371 amdpm_clear(sc);
372 if (!amdpm_idle(sc))
373 return (SMB_EBUSY);
374
375 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
376 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
377 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
378 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
379
380 error = amdpm_wait(sc);
381
382 AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
383
384 return (error);
385 }
386
387 static int
388 amdpm_recvb(device_t dev, u_char slave, char *byte)
389 {
390 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
391 int error;
392 u_short l;
393
394 amdpm_clear(sc);
395 if (!amdpm_idle(sc))
396 return (SMB_EBUSY);
397
398 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
399 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
400 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
401
402 if ((error = amdpm_wait(sc)) == SMB_ENOERR)
403 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
404
405 AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
406
407 return (error);
408 }
409
410 static int
411 amdpm_writeb(device_t dev, u_char slave, char cmd, char byte)
412 {
413 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
414 int error;
415 u_short l;
416
417 amdpm_clear(sc);
418 if (!amdpm_idle(sc))
419 return (SMB_EBUSY);
420
421 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
422 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
423 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
424 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
425 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
426
427 error = amdpm_wait(sc);
428
429 AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
430
431 return (error);
432 }
433
434 static int
435 amdpm_readb(device_t dev, u_char slave, char cmd, char *byte)
436 {
437 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
438 int error;
439 u_short l;
440
441 amdpm_clear(sc);
442 if (!amdpm_idle(sc))
443 return (SMB_EBUSY);
444
445 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
446 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
447 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
448 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
449
450 if ((error = amdpm_wait(sc)) == SMB_ENOERR)
451 *byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
452
453 AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
454
455 return (error);
456 }
457
458 static int
459 amdpm_writew(device_t dev, u_char slave, char cmd, short word)
460 {
461 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
462 int error;
463 u_short l;
464
465 amdpm_clear(sc);
466 if (!amdpm_idle(sc))
467 return (SMB_EBUSY);
468
469 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
470 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word);
471 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
472 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
473 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
474
475 error = amdpm_wait(sc);
476
477 AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
478
479 return (error);
480 }
481
482 static int
483 amdpm_readw(device_t dev, u_char slave, char cmd, short *word)
484 {
485 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
486 int error;
487 u_short l;
488
489 amdpm_clear(sc);
490 if (!amdpm_idle(sc))
491 return (SMB_EBUSY);
492
493 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
494 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
495 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
496 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
497
498 if ((error = amdpm_wait(sc)) == SMB_ENOERR)
499 *word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
500
501 AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
502
503 return (error);
504 }
505
506 static int
507 amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
508 {
509 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
510 u_char remain, len, i;
511 int error = SMB_ENOERR;
512 u_short l;
513
514 amdpm_clear(sc);
515 if(!amdpm_idle(sc))
516 return (SMB_EBUSY);
517
518 remain = count;
519 while (remain) {
520 len = min(remain, 32);
521
522 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
523
524 /*
525 * Do we have to reset the internal 32-byte buffer?
526 * Can't see how to do this from the data sheet.
527 */
528
529 AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len);
530
531 /* Fill the 32-byte internal buffer */
532 for (i=0; i<len; i++) {
533 AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+i]);
534 DELAY(2);
535 }
536 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
537 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
538 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
539
540 if ((error = amdpm_wait(sc)) != SMB_ENOERR)
541 goto error;
542
543 remain -= len;
544 }
545
546 error:
547 AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
548
549 return (error);
550 }
551
552 static int
553 amdpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
554 {
555 struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
556 u_char remain, len, i;
557 int error = SMB_ENOERR;
558 u_short l;
559
560 amdpm_clear(sc);
561 if (!amdpm_idle(sc))
562 return (SMB_EBUSY);
563
564 remain = count;
565 while (remain) {
566 AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
567
568 AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
569
570 l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
571 AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
572
573 if ((error = amdpm_wait(sc)) != SMB_ENOERR)
574 goto error;
575
576 len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
577
578 /* Read the 32-byte internal buffer */
579 for (i=0; i<len; i++) {
580 buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO);
581 DELAY(2);
582 }
583
584 remain -= len;
585 }
586 error:
587 AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
588
589 return (error);
590 }
591
592 static devclass_t amdpm_devclass;
593
594 static device_method_t amdpm_methods[] = {
595 /* Device interface */
596 DEVMETHOD(device_probe, amdpm_probe),
597 DEVMETHOD(device_attach, amdpm_attach),
598 DEVMETHOD(device_detach, amdpm_detach),
599
600 /* SMBus interface */
601 DEVMETHOD(smbus_callback, amdpm_callback),
602 DEVMETHOD(smbus_quick, amdpm_quick),
603 DEVMETHOD(smbus_sendb, amdpm_sendb),
604 DEVMETHOD(smbus_recvb, amdpm_recvb),
605 DEVMETHOD(smbus_writeb, amdpm_writeb),
606 DEVMETHOD(smbus_readb, amdpm_readb),
607 DEVMETHOD(smbus_writew, amdpm_writew),
608 DEVMETHOD(smbus_readw, amdpm_readw),
609 DEVMETHOD(smbus_bwrite, amdpm_bwrite),
610 DEVMETHOD(smbus_bread, amdpm_bread),
611
612 { 0, 0 }
613 };
614
615 static driver_t amdpm_driver = {
616 "amdpm",
617 amdpm_methods,
618 sizeof(struct amdpm_softc),
619 };
620
621 DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0);
622
623 MODULE_DEPEND(amdpm, pci, 1, 1, 1);
624 MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
625 MODULE_VERSION(amdpm, 1);
626
Cache object: 1359e63ef779be1dd33f709b576f0ad1
|