amdpm.c revision 83553
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 * $FreeBSD: head/sys/pci/amdpm.c 83553 2001-09-16 22:35:07Z murray $
31 *
32 */
33
34/*
35 * Power management function/SMBus function support for the AMD 756 chip.
36 */
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 <pci/pcivar.h>
53#include <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
62static int amdpm_debug = 1;
63#else
64static int amdpm_debug = 0;
65#endif
66
67#define AMDPM_VENDORID_AMD 0x1022
68#define AMDPM_DEVICEID_AMD756PM 0x740b
69
70/* PCI Configuration space registers */
71#define AMDPCI_PMBASE 0x58
72
73#define AMDPCI_GEN_CONFIG_PM 0x41
74#define AMDPCI_PMIOEN (1<<7)
75
76#define AMDPCI_SCIINT_CONFIG_PM 0x42
77#define AMDPCI_SCISEL_IRQ11 11
78
79#define AMDPCI_REVID 0x08
80
81/*
82 * I/O registers.
83 * Base address programmed via AMDPCI_PMBASE.
84 */
85#define AMDSMB_GLOBAL_STATUS 0xE0
86#define AMDSMB_GS_TO_STS (1<<5)
87#define AMDSMB_GS_HCYC_STS (1<<4)
88#define AMDSMB_GS_HST_STS (1<<3)
89#define AMDSMB_GS_PRERR_STS (1<<2)
90#define AMDSMB_GS_COL_STS (1<<1)
91#define AMDSMB_GS_ABRT_STS (1<<0)
92#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)
93
94#define AMDSMB_GLOBAL_ENABLE 0xE2
95#define AMDSMB_GE_ABORT (1<<5)
96#define AMDSMB_GE_HCYC_EN (1<<4)
97#define AMDSMB_GE_HOST_STC (1<<3)
98#define AMDSMB_GE_CYC_QUICK 0
99#define AMDSMB_GE_CYC_BYTE 1
100#define AMDSMB_GE_CYC_BDATA 2
101#define AMDSMB_GE_CYC_WDATA 3
102#define AMDSMB_GE_CYC_PROCCALL 4
103#define AMDSMB_GE_CYC_BLOCK 5
104
105#define AMDSMB_HSTADDR 0xE4
106#define AMDSMB_HSTDATA 0xE6
107#define AMDSMB_HSTCMD 0xE8
108#define AMDSMB_HSTDFIFO 0xE9
109#define AMDSMB_HSLVDATA 0xEA
110#define AMDSMB_HSLVDA 0xEC
111#define AMDSMB_HSLVDDR 0xEE
112#define AMDSMB_SNPADDR 0xEF
113
114struct amdpm_softc {
115	int base;
116	int rid;
117	struct resource *res;
118        bus_space_tag_t smbst;
119        bus_space_handle_t smbsh;
120};
121
122struct amdsmb_softc {
123	int base;
124	device_t smbus;
125	struct amdpm_softc *amdpm;
126};
127
128#define AMDPM_SMBINB(amdsmb,register) \
129	(bus_space_read_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
130#define AMDPM_SMBOUTB(amdsmb,register,value) \
131	(bus_space_write_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
132#define AMDPM_SMBINW(amdsmb,register) \
133	(bus_space_read_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
134#define AMDPM_SMBOUTW(amdsmb,register,value) \
135	(bus_space_write_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
136
137static int amdsmb_probe(device_t);
138static int amdsmb_attach(device_t);
139static int amdsmb_smb_callback(device_t, int, caddr_t *);
140static int amdsmb_smb_quick(device_t dev, u_char slave, int how);
141static int amdsmb_smb_sendb(device_t dev, u_char slave, char byte);
142static int amdsmb_smb_recvb(device_t dev, u_char slave, char *byte);
143static int amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte);
144static int amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte);
145static int amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word);
146static int amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word);
147static int amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
148static int amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte);
149
150static int amdpm_probe(device_t);
151static int amdpm_attach(device_t);
152
153
154static int
155amdpm_probe(device_t dev)
156{
157	u_long base;
158
159	if ((pci_get_vendor(dev) == AMDPM_VENDORID_AMD) &&
160	    (pci_get_device(dev) == AMDPM_DEVICEID_AMD756PM)) {
161	      device_set_desc(dev, "AMD 756 Power Management Controller");
162
163	      /*
164	       * We have to do this, since the BIOS won't give us the
165	       * resource info (not mine, anyway).
166	       */
167	      base = pci_read_config(dev, AMDPCI_PMBASE, 4);
168	      base &= 0xff00;
169	      bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, base, 256);
170	      return (0);
171	}
172	return ENXIO;
173}
174
175static int
176amdpm_attach(device_t dev)
177{
178	struct amdpm_softc *amdpm_sc = device_get_softc(dev);
179	u_char val_b;
180	int unit = device_get_unit(dev);
181	device_t smbinterface;
182
183	/* Enable I/O block access */
184	val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1);
185	pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1);
186
187	/* Allocate I/O space */
188	amdpm_sc->rid = AMDPCI_PMBASE;
189	amdpm_sc->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &amdpm_sc->rid, 0, ~0, 1, RF_ACTIVE);
190
191	if (amdpm_sc->res == NULL) {
192		device_printf(dev, "could not map i/o space\n");
193		return (ENXIO);
194	}
195
196	amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res);
197	amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
198
199	smbinterface = device_add_child(dev, "amdsmb", unit);
200	if (!smbinterface)
201		device_printf(dev, "could not add SMBus device\n");
202	else
203		device_probe_and_attach(smbinterface);
204
205	return (0);
206}
207
208static int
209amdsmb_probe(device_t dev)
210{
211	struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
212
213	/* Allocate a new smbus device */
214	amdsmb_sc->smbus = smbus_alloc_bus(dev);
215	if (!amdsmb_sc->smbus)
216		return (EINVAL);
217
218	device_set_desc(dev, "AMD 756 SMBus interface");
219	device_printf(dev, "AMD 756 SMBus interface\n");
220
221	return (0);
222}
223
224static int
225amdsmb_attach(device_t dev)
226{
227	struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
228
229	amdsmb_sc->amdpm = device_get_softc(device_get_parent(dev));
230
231	/* Probe and attach the smbus */
232	device_probe_and_attach(amdsmb_sc->smbus);
233
234	return (0);
235}
236
237static int
238amdsmb_smb_callback(device_t dev, int index, caddr_t *data)
239{
240	int error = 0;
241
242	switch (index) {
243	case SMB_REQUEST_BUS:
244	case SMB_RELEASE_BUS:
245		break;
246	default:
247		error = EINVAL;
248	}
249
250	return (error);
251}
252
253static int
254amdsmb_clear(struct amdsmb_softc *sc)
255{
256	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
257	DELAY(10);
258
259	return (0);
260}
261
262static int
263amdsmb_abort(struct amdsmb_softc *sc)
264{
265	u_short l;
266
267	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
268	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT);
269
270	return (0);
271}
272
273static int
274amdsmb_idle(struct amdsmb_softc *sc)
275{
276	u_short sts;
277
278	sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
279
280	AMDPM_DEBUG(printf("amdpm: busy? STS=0x%x\n", sts));
281
282	return (~(sts & AMDSMB_GS_HST_STS));
283}
284
285/*
286 * Poll the SMBus controller
287 */
288static int
289amdsmb_wait(struct amdsmb_softc *sc)
290{
291	int count = 10000;
292	u_short sts = 0;
293	int error;
294
295	/* Wait for command to complete (SMBus controller is idle) */
296	while(count--) {
297		DELAY(10);
298		sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
299		if (!(sts & AMDSMB_GS_HST_STS))
300			break;
301	}
302
303	AMDPM_DEBUG(printf("amdpm: STS=0x%x (count=%d)\n", sts, count));
304
305	error = SMB_ENOERR;
306
307	if (!count)
308		error |= SMB_ETIMEOUT;
309
310	if (sts & AMDSMB_GS_ABRT_STS)
311		error |= SMB_EABORT;
312
313	if (sts & AMDSMB_GS_COL_STS)
314		error |= SMB_ENOACK;
315
316	if (sts & AMDSMB_GS_PRERR_STS)
317		error |= SMB_EBUSERR;
318
319	if (error != SMB_ENOERR)
320		amdsmb_clear(sc);
321
322	return (error);
323}
324
325static int
326amdsmb_smb_quick(device_t dev, u_char slave, int how)
327{
328	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
329	int error;
330	u_short l;
331
332	amdsmb_clear(sc);
333	if (!amdsmb_idle(sc))
334		return (EBUSY);
335
336	switch (how) {
337	case SMB_QWRITE:
338		AMDPM_DEBUG(printf("amdpm: QWRITE to 0x%x", slave));
339		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
340		break;
341	case SMB_QREAD:
342		AMDPM_DEBUG(printf("amdpm: QREAD to 0x%x", slave));
343		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
344		break;
345	default:
346		panic("%s: unknown QUICK command (%x)!", __FUNCTION__, how);
347	}
348	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
349	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC);
350
351	error = amdsmb_wait(sc);
352
353	AMDPM_DEBUG(printf(", error=0x%x\n", error));
354
355	return (error);
356}
357
358static int
359amdsmb_smb_sendb(device_t dev, u_char slave, char byte)
360{
361	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
362	int error;
363	u_short l;
364
365	amdsmb_clear(sc);
366	if (!amdsmb_idle(sc))
367		return (SMB_EBUSY);
368
369	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
370	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
371	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
372	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
373
374	error = amdsmb_wait(sc);
375
376	AMDPM_DEBUG(printf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
377
378	return (error);
379}
380
381static int
382amdsmb_smb_recvb(device_t dev, u_char slave, char *byte)
383{
384	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
385	int error;
386	u_short l;
387
388	amdsmb_clear(sc);
389	if (!amdsmb_idle(sc))
390		return (SMB_EBUSY);
391
392	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
393	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
394	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
395
396	if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
397		*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
398
399	AMDPM_DEBUG(printf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
400
401	return (error);
402}
403
404static int
405amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
406{
407	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
408	int error;
409	u_short l;
410
411	amdsmb_clear(sc);
412	if (!amdsmb_idle(sc))
413		return (SMB_EBUSY);
414
415	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
416	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
417	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
418	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
419	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
420
421	error = amdsmb_wait(sc);
422
423	AMDPM_DEBUG(printf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
424
425	return (error);
426}
427
428static int
429amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
430{
431	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
432	int error;
433	u_short l;
434
435	amdsmb_clear(sc);
436	if (!amdsmb_idle(sc))
437		return (SMB_EBUSY);
438
439	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
440	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
441	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
442	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
443
444	if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
445		*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
446
447	AMDPM_DEBUG(printf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
448
449	return (error);
450}
451
452static int
453amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
454{
455	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
456	int error;
457	u_short l;
458
459	amdsmb_clear(sc);
460	if (!amdsmb_idle(sc))
461		return (SMB_EBUSY);
462
463	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
464	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word);
465	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
466	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
467	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
468
469	error = amdsmb_wait(sc);
470
471	AMDPM_DEBUG(printf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
472
473	return (error);
474}
475
476static int
477amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
478{
479	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
480	int error;
481	u_short l;
482
483	amdsmb_clear(sc);
484	if (!amdsmb_idle(sc))
485		return (SMB_EBUSY);
486
487	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
488	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
489	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
490	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
491
492	if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
493		*word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
494
495	AMDPM_DEBUG(printf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
496
497	return (error);
498}
499
500static int
501amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
502{
503	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
504	u_char remain, len, i;
505	int error = SMB_ENOERR;
506	u_short l;
507
508	amdsmb_clear(sc);
509	if(!amdsmb_idle(sc))
510		return (SMB_EBUSY);
511
512	remain = count;
513	while (remain) {
514		len = min(remain, 32);
515
516		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
517
518		/*
519		 * Do we have to reset the internal 32-byte buffer?
520		 * Can't see how to do this from the data sheet.
521		 */
522
523		AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, len);
524
525		/* Fill the 32-byte internal buffer */
526		for (i=0; i<len; i++) {
527			AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[count-remain+i]);
528			DELAY(2);
529		}
530		AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
531		l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
532		AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
533
534		if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
535			goto error;
536
537		remain -= len;
538	}
539
540error:
541	AMDPM_DEBUG(printf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
542
543	return (error);
544}
545
546static int
547amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
548{
549	struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
550	u_char remain, len, i;
551	int error = SMB_ENOERR;
552	u_short l;
553
554	amdsmb_clear(sc);
555	if (!amdsmb_idle(sc))
556		return (SMB_EBUSY);
557
558	remain = count;
559	while (remain) {
560		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
561
562		AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
563
564		l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
565		AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
566
567		if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
568			goto error;
569
570		len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
571
572		/* Read the 32-byte internal buffer */
573		for (i=0; i<len; i++) {
574			buf[count-remain+i] = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO);
575			DELAY(2);
576		}
577
578		remain -= len;
579	}
580error:
581	AMDPM_DEBUG(printf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
582
583	return (error);
584}
585
586static devclass_t amdpm_devclass;
587
588static device_method_t amdpm_methods[] = {
589	/* Device interface */
590	DEVMETHOD(device_probe,		amdpm_probe),
591	DEVMETHOD(device_attach,	amdpm_attach),
592
593	{ 0, 0 }
594};
595
596static driver_t amdpm_driver = {
597	"amdpm",
598	amdpm_methods,
599	sizeof(struct amdpm_softc),
600};
601
602static devclass_t amdsmb_devclass;
603
604static device_method_t amdsmb_methods[] = {
605	/* Device interface */
606	DEVMETHOD(device_probe,		amdsmb_probe),
607	DEVMETHOD(device_attach,	amdsmb_attach),
608
609	/* Bus interface */
610	DEVMETHOD(bus_print_child,	bus_generic_print_child),
611
612	/* SMBus interface */
613	DEVMETHOD(smbus_callback,	amdsmb_smb_callback),
614	DEVMETHOD(smbus_quick,		amdsmb_smb_quick),
615	DEVMETHOD(smbus_sendb,		amdsmb_smb_sendb),
616	DEVMETHOD(smbus_recvb,		amdsmb_smb_recvb),
617	DEVMETHOD(smbus_writeb,		amdsmb_smb_writeb),
618	DEVMETHOD(smbus_readb,		amdsmb_smb_readb),
619	DEVMETHOD(smbus_writew,		amdsmb_smb_writew),
620	DEVMETHOD(smbus_readw,		amdsmb_smb_readw),
621	DEVMETHOD(smbus_bwrite,		amdsmb_smb_bwrite),
622	DEVMETHOD(smbus_bread,		amdsmb_smb_bread),
623
624	{ 0, 0 }
625};
626
627static driver_t amdsmb_driver = {
628	"amdsmb",
629	amdsmb_methods,
630	sizeof(struct amdsmb_softc),
631};
632
633DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0);
634DRIVER_MODULE(amdsmb, amdpm, amdsmb_driver, amdsmb_devclass, 0, 0);
635