xref: /dflybsd-src/sys/dev/powermng/amdpm/amdpm.c (revision 2267fd784e8a7d1ca13e6d3541caa91f36c9e9fb)
1a9656fbcSSascha Wildner /*-
2a9656fbcSSascha Wildner  * Copyright (c) 2000 Matthew C. Forman
3a9656fbcSSascha Wildner  *
4a9656fbcSSascha Wildner  * Based (heavily) on alpm.c which is:
5a9656fbcSSascha Wildner  *
6a9656fbcSSascha Wildner  * Copyright (c) 1998, 1999 Nicolas Souchu
7a9656fbcSSascha Wildner  * All rights reserved.
8a9656fbcSSascha Wildner  *
9a9656fbcSSascha Wildner  * Redistribution and use in source and binary forms, with or without
10a9656fbcSSascha Wildner  * modification, are permitted provided that the following conditions
11a9656fbcSSascha Wildner  * are met:
12a9656fbcSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
13a9656fbcSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
14a9656fbcSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
15a9656fbcSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
16a9656fbcSSascha Wildner  *    documentation and/or other materials provided with the distribution.
17a9656fbcSSascha Wildner  *
18a9656fbcSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19a9656fbcSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20a9656fbcSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21a9656fbcSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22a9656fbcSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23a9656fbcSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24a9656fbcSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25a9656fbcSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26a9656fbcSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27a9656fbcSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28a9656fbcSSascha Wildner  * SUCH DAMAGE.
29a9656fbcSSascha Wildner  *
30281aef06SSascha Wildner  * $FreeBSD: src/sys/pci/amdpm.c,v 1.22 2008/06/06 18:29:56 jhb Exp $
31a9656fbcSSascha Wildner  *
32a9656fbcSSascha Wildner  */
33a9656fbcSSascha Wildner 
34a9656fbcSSascha Wildner /*
35a9656fbcSSascha Wildner  * Power management function/SMBus function support for the AMD 756 chip.
36a9656fbcSSascha Wildner  */
37a9656fbcSSascha Wildner 
38a9656fbcSSascha Wildner #include <sys/param.h>
39a9656fbcSSascha Wildner #include <sys/bus.h>
40281aef06SSascha Wildner #include <sys/globaldata.h>
41281aef06SSascha Wildner #include <sys/kernel.h>
42281aef06SSascha Wildner #include <sys/lock.h>
43281aef06SSascha Wildner #include <sys/module.h>
44a9656fbcSSascha Wildner #include <sys/rman.h>
45281aef06SSascha Wildner #include <sys/systm.h>
46a9656fbcSSascha Wildner 
47a9656fbcSSascha Wildner #include <bus/pci/pcivar.h>
48a9656fbcSSascha Wildner #include <bus/pci/pcireg.h>
49a9656fbcSSascha Wildner 
50a9656fbcSSascha Wildner #include <bus/smbus/smbconf.h>
51a9656fbcSSascha Wildner #include "smbus_if.h"
52a9656fbcSSascha Wildner 
53a9656fbcSSascha Wildner #define AMDPM_DEBUG(x)	if (amdpm_debug) (x)
54a9656fbcSSascha Wildner 
55a9656fbcSSascha Wildner #ifdef DEBUG
56a9656fbcSSascha Wildner static int amdpm_debug = 1;
57a9656fbcSSascha Wildner #else
58a9656fbcSSascha Wildner static int amdpm_debug = 0;
59a9656fbcSSascha Wildner #endif
60a9656fbcSSascha Wildner 
61a9656fbcSSascha Wildner #define AMDPM_VENDORID_AMD 0x1022
62a9656fbcSSascha Wildner #define AMDPM_DEVICEID_AMD756PM 0x740b
63a9656fbcSSascha Wildner #define AMDPM_DEVICEID_AMD766PM 0x7413
64a9656fbcSSascha Wildner #define AMDPM_DEVICEID_AMD768PM 0x7443
65281aef06SSascha Wildner #define AMDPM_DEVICEID_AMD8111PM 0x746B
66a9656fbcSSascha Wildner 
67a9656fbcSSascha Wildner /* nVidia nForce chipset */
68a9656fbcSSascha Wildner #define AMDPM_VENDORID_NVIDIA 0x10de
69a9656fbcSSascha Wildner #define AMDPM_DEVICEID_NF_SMB 0x01b4
70a9656fbcSSascha Wildner 
71a9656fbcSSascha Wildner /* PCI Configuration space registers */
72a9656fbcSSascha Wildner #define AMDPCI_PMBASE 0x58
73a9656fbcSSascha Wildner #define NFPCI_PMBASE  0x14
74a9656fbcSSascha Wildner 
75a9656fbcSSascha Wildner #define AMDPCI_GEN_CONFIG_PM 0x41
76a9656fbcSSascha Wildner #define AMDPCI_PMIOEN (1<<7)
77a9656fbcSSascha Wildner 
78a9656fbcSSascha Wildner #define AMDPCI_SCIINT_CONFIG_PM 0x42
79a9656fbcSSascha Wildner #define AMDPCI_SCISEL_IRQ11 11
80a9656fbcSSascha Wildner 
81a9656fbcSSascha Wildner #define AMDPCI_REVID 0x08
82a9656fbcSSascha Wildner 
83a9656fbcSSascha Wildner /*
84a9656fbcSSascha Wildner  * I/O registers.
85a9656fbcSSascha Wildner  * Base address programmed via AMDPCI_PMBASE.
86a9656fbcSSascha Wildner  */
87a9656fbcSSascha Wildner 
88a9656fbcSSascha Wildner #define AMDSMB_GLOBAL_STATUS (0x00)
89a9656fbcSSascha Wildner #define AMDSMB_GS_TO_STS (1<<5)
90a9656fbcSSascha Wildner #define AMDSMB_GS_HCYC_STS (1<<4)
91a9656fbcSSascha Wildner #define AMDSMB_GS_HST_STS (1<<3)
92a9656fbcSSascha Wildner #define AMDSMB_GS_PRERR_STS (1<<2)
93a9656fbcSSascha Wildner #define AMDSMB_GS_COL_STS (1<<1)
94a9656fbcSSascha Wildner #define AMDSMB_GS_ABRT_STS (1<<0)
95a9656fbcSSascha Wildner #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)
96a9656fbcSSascha Wildner 
97a9656fbcSSascha Wildner #define AMDSMB_GLOBAL_ENABLE (0x02)
98a9656fbcSSascha Wildner #define AMDSMB_GE_ABORT (1<<5)
99a9656fbcSSascha Wildner #define AMDSMB_GE_HCYC_EN (1<<4)
100a9656fbcSSascha Wildner #define AMDSMB_GE_HOST_STC (1<<3)
101a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_QUICK 0
102a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_BYTE 1
103a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_BDATA 2
104a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_WDATA 3
105a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_PROCCALL 4
106a9656fbcSSascha Wildner #define AMDSMB_GE_CYC_BLOCK 5
107a9656fbcSSascha Wildner 
108281aef06SSascha Wildner #define	LSB		0x1	/* XXX: Better name: Read/Write? */
109281aef06SSascha Wildner 
110a9656fbcSSascha Wildner #define AMDSMB_HSTADDR  (0x04)
111a9656fbcSSascha Wildner #define AMDSMB_HSTDATA  (0x06)
112a9656fbcSSascha Wildner #define AMDSMB_HSTCMD   (0x08)
113a9656fbcSSascha Wildner #define AMDSMB_HSTDFIFO (0x09)
114a9656fbcSSascha Wildner #define AMDSMB_HSLVDATA (0x0A)
115a9656fbcSSascha Wildner #define AMDSMB_HSLVDA   (0x0C)
116a9656fbcSSascha Wildner #define AMDSMB_HSLVDDR  (0x0E)
117a9656fbcSSascha Wildner #define AMDSMB_SNPADDR  (0x0F)
118a9656fbcSSascha Wildner 
119a9656fbcSSascha Wildner struct amdpm_softc {
120a9656fbcSSascha Wildner 	int base;
121a9656fbcSSascha Wildner 	int rid;
122a9656fbcSSascha Wildner 	struct resource *res;
123a9656fbcSSascha Wildner 	device_t smbus;
124281aef06SSascha Wildner 	struct lock lock;
125a9656fbcSSascha Wildner };
126a9656fbcSSascha Wildner 
127281aef06SSascha Wildner #define	AMDPM_LOCK(amdpm)		lockmgr(&(amdpm)->lock, LK_EXCLUSIVE)
128281aef06SSascha Wildner #define	AMDPM_UNLOCK(amdpm)		lockmgr(&(amdpm)->lock, LK_RELEASE)
129281aef06SSascha Wildner #define	AMDPM_LOCK_ASSERT(amdpm)	KKASSERT(lockstatus(&(amdpm)->lock, curthread) != 0)
130281aef06SSascha Wildner 
131a9656fbcSSascha Wildner #define AMDPM_SMBINB(amdpm,register) \
132281aef06SSascha Wildner 	(bus_read_1(amdpm->res, register))
133a9656fbcSSascha Wildner #define AMDPM_SMBOUTB(amdpm,register,value) \
134281aef06SSascha Wildner 	(bus_write_1(amdpm->res, register, value))
135a9656fbcSSascha Wildner #define AMDPM_SMBINW(amdpm,register) \
136281aef06SSascha Wildner 	(bus_read_2(amdpm->res, register))
137a9656fbcSSascha Wildner #define AMDPM_SMBOUTW(amdpm,register,value) \
138281aef06SSascha Wildner 	(bus_write_2(amdpm->res, register, value))
139281aef06SSascha Wildner 
140281aef06SSascha Wildner static int	amdpm_detach(device_t dev);
141a9656fbcSSascha Wildner 
142a9656fbcSSascha Wildner static int
amdpm_probe(device_t dev)143a9656fbcSSascha Wildner amdpm_probe(device_t dev)
144a9656fbcSSascha Wildner {
145a9656fbcSSascha Wildner 	u_long base;
146a9656fbcSSascha Wildner 	u_int16_t vid;
147a9656fbcSSascha Wildner 	u_int16_t did;
148a9656fbcSSascha Wildner 
149a9656fbcSSascha Wildner 	vid = pci_get_vendor(dev);
150a9656fbcSSascha Wildner 	did = pci_get_device(dev);
151a9656fbcSSascha Wildner 	if ((vid == AMDPM_VENDORID_AMD) &&
152a9656fbcSSascha Wildner 	    ((did == AMDPM_DEVICEID_AMD756PM) ||
153a9656fbcSSascha Wildner 	     (did == AMDPM_DEVICEID_AMD766PM) ||
154281aef06SSascha Wildner 	     (did == AMDPM_DEVICEID_AMD768PM) ||
155281aef06SSascha Wildner 	     (did == AMDPM_DEVICEID_AMD8111PM))) {
156281aef06SSascha Wildner 		device_set_desc(dev, "AMD 756/766/768/8111 Power Management Controller");
157a9656fbcSSascha Wildner 
158a9656fbcSSascha Wildner 		/*
159a9656fbcSSascha Wildner 		 * We have to do this, since the BIOS won't give us the
160a9656fbcSSascha Wildner 		 * resource info (not mine, anyway).
161a9656fbcSSascha Wildner 		 */
162a9656fbcSSascha Wildner 		base = pci_read_config(dev, AMDPCI_PMBASE, 4);
163a9656fbcSSascha Wildner 		base &= 0xff00;
164a9656fbcSSascha Wildner 		bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE,
165b47b3275SSepherosa Ziehau 				 base+0xe0, 32, -1);
166281aef06SSascha Wildner 		return (BUS_PROBE_DEFAULT);
167a9656fbcSSascha Wildner 	}
168a9656fbcSSascha Wildner 
169a9656fbcSSascha Wildner 	if ((vid == AMDPM_VENDORID_NVIDIA) &&
170a9656fbcSSascha Wildner 	    (did == AMDPM_DEVICEID_NF_SMB)) {
171a9656fbcSSascha Wildner 		device_set_desc(dev, "nForce SMBus Controller");
172a9656fbcSSascha Wildner 
173a9656fbcSSascha Wildner 		/*
174a9656fbcSSascha Wildner 		 * We have to do this, since the BIOS won't give us the
175a9656fbcSSascha Wildner 		 * resource info (not mine, anyway).
176a9656fbcSSascha Wildner 		 */
177a9656fbcSSascha Wildner 		base = pci_read_config(dev, NFPCI_PMBASE, 4);
178a9656fbcSSascha Wildner 		base &= 0xff00;
179a9656fbcSSascha Wildner 		bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE,
180b47b3275SSepherosa Ziehau 				 base, 32, -1);
181a9656fbcSSascha Wildner 
182281aef06SSascha Wildner 		return (BUS_PROBE_DEFAULT);
183a9656fbcSSascha Wildner 	}
184a9656fbcSSascha Wildner 
185a9656fbcSSascha Wildner 	return ENXIO;
186a9656fbcSSascha Wildner }
187a9656fbcSSascha Wildner 
188a9656fbcSSascha Wildner static int
amdpm_attach(device_t dev)189a9656fbcSSascha Wildner amdpm_attach(device_t dev)
190a9656fbcSSascha Wildner {
191a9656fbcSSascha Wildner 	struct amdpm_softc *amdpm_sc = device_get_softc(dev);
192a9656fbcSSascha Wildner 	u_char val_b;
193a9656fbcSSascha Wildner 
194a9656fbcSSascha Wildner 	/* Enable I/O block access */
195a9656fbcSSascha Wildner 	val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1);
196a9656fbcSSascha Wildner 	pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1);
197a9656fbcSSascha Wildner 
198a9656fbcSSascha Wildner 	/* Allocate I/O space */
199a9656fbcSSascha Wildner 	if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD)
200a9656fbcSSascha Wildner 		amdpm_sc->rid = AMDPCI_PMBASE;
201a9656fbcSSascha Wildner 	else
202a9656fbcSSascha Wildner 		amdpm_sc->rid = NFPCI_PMBASE;
203281aef06SSascha Wildner 	amdpm_sc->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
204281aef06SSascha Wildner 		&amdpm_sc->rid, RF_ACTIVE);
205a9656fbcSSascha Wildner 
206a9656fbcSSascha Wildner 	if (amdpm_sc->res == NULL) {
207a9656fbcSSascha Wildner 		device_printf(dev, "could not map i/o space\n");
208a9656fbcSSascha Wildner 		return (ENXIO);
209a9656fbcSSascha Wildner 	}
210a9656fbcSSascha Wildner 
211281aef06SSascha Wildner 	lockinit(&amdpm_sc->lock, "amdpm", 0, LK_CANRECURSE);
212a9656fbcSSascha Wildner 
213a9656fbcSSascha Wildner 	/* Allocate a new smbus device */
214a9656fbcSSascha Wildner 	amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
215281aef06SSascha Wildner 	if (!amdpm_sc->smbus) {
216281aef06SSascha Wildner 		amdpm_detach(dev);
217a9656fbcSSascha Wildner 		return (EINVAL);
218281aef06SSascha Wildner 	}
219a9656fbcSSascha Wildner 
220a9656fbcSSascha Wildner 	bus_generic_attach(dev);
221a9656fbcSSascha Wildner 
222a9656fbcSSascha Wildner 	return (0);
223a9656fbcSSascha Wildner }
224a9656fbcSSascha Wildner 
225a9656fbcSSascha Wildner static int
amdpm_detach(device_t dev)226a9656fbcSSascha Wildner amdpm_detach(device_t dev)
227a9656fbcSSascha Wildner {
228a9656fbcSSascha Wildner 	struct amdpm_softc *amdpm_sc = device_get_softc(dev);
229a9656fbcSSascha Wildner 
230a9656fbcSSascha Wildner 	if (amdpm_sc->smbus) {
231a9656fbcSSascha Wildner 		device_delete_child(dev, amdpm_sc->smbus);
232a9656fbcSSascha Wildner 		amdpm_sc->smbus = NULL;
233a9656fbcSSascha Wildner 	}
234a9656fbcSSascha Wildner 
235281aef06SSascha Wildner 	lockuninit(&amdpm_sc->lock);
236a9656fbcSSascha Wildner 	if (amdpm_sc->res)
237a9656fbcSSascha Wildner 		bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid,
238a9656fbcSSascha Wildner 				     amdpm_sc->res);
239a9656fbcSSascha Wildner 
240a9656fbcSSascha Wildner 	return (0);
241a9656fbcSSascha Wildner }
242a9656fbcSSascha Wildner 
243a9656fbcSSascha Wildner static int
amdpm_callback(device_t dev,int index,void * data)244281aef06SSascha Wildner amdpm_callback(device_t dev, int index, void *data)
245a9656fbcSSascha Wildner {
246a9656fbcSSascha Wildner 	int error = 0;
247a9656fbcSSascha Wildner 
248a9656fbcSSascha Wildner 	switch (index) {
249a9656fbcSSascha Wildner 	case SMB_REQUEST_BUS:
250a9656fbcSSascha Wildner 	case SMB_RELEASE_BUS:
251a9656fbcSSascha Wildner 		break;
252a9656fbcSSascha Wildner 	default:
253a9656fbcSSascha Wildner 		error = EINVAL;
254a9656fbcSSascha Wildner 	}
255a9656fbcSSascha Wildner 
256a9656fbcSSascha Wildner 	return (error);
257a9656fbcSSascha Wildner }
258a9656fbcSSascha Wildner 
259a9656fbcSSascha Wildner static int
amdpm_clear(struct amdpm_softc * sc)260a9656fbcSSascha Wildner amdpm_clear(struct amdpm_softc *sc)
261a9656fbcSSascha Wildner {
262281aef06SSascha Wildner 
263281aef06SSascha Wildner 	AMDPM_LOCK_ASSERT(sc);
264a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
265a9656fbcSSascha Wildner 	DELAY(10);
266a9656fbcSSascha Wildner 
267a9656fbcSSascha Wildner 	return (0);
268a9656fbcSSascha Wildner }
269a9656fbcSSascha Wildner 
270a9656fbcSSascha Wildner #if 0
271a9656fbcSSascha Wildner static int
272a9656fbcSSascha Wildner amdpm_abort(struct amdpm_softc *sc)
273a9656fbcSSascha Wildner {
274a9656fbcSSascha Wildner 	u_short l;
275a9656fbcSSascha Wildner 
276a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
277a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT);
278a9656fbcSSascha Wildner 
279a9656fbcSSascha Wildner 	return (0);
280a9656fbcSSascha Wildner }
281a9656fbcSSascha Wildner #endif
282a9656fbcSSascha Wildner 
283a9656fbcSSascha Wildner static int
amdpm_idle(struct amdpm_softc * sc)284a9656fbcSSascha Wildner amdpm_idle(struct amdpm_softc *sc)
285a9656fbcSSascha Wildner {
286a9656fbcSSascha Wildner 	u_short sts;
287a9656fbcSSascha Wildner 
288281aef06SSascha Wildner 	AMDPM_LOCK_ASSERT(sc);
289a9656fbcSSascha Wildner 	sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
290a9656fbcSSascha Wildner 
291a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: busy? STS=0x%x\n", sts));
292a9656fbcSSascha Wildner 
293a9656fbcSSascha Wildner 	return (~(sts & AMDSMB_GS_HST_STS));
294a9656fbcSSascha Wildner }
295a9656fbcSSascha Wildner 
296a9656fbcSSascha Wildner /*
297a9656fbcSSascha Wildner  * Poll the SMBus controller
298a9656fbcSSascha Wildner  */
299a9656fbcSSascha Wildner static int
amdpm_wait(struct amdpm_softc * sc)300a9656fbcSSascha Wildner amdpm_wait(struct amdpm_softc *sc)
301a9656fbcSSascha Wildner {
302a9656fbcSSascha Wildner 	int count = 10000;
303a9656fbcSSascha Wildner 	u_short sts = 0;
304a9656fbcSSascha Wildner 	int error;
305a9656fbcSSascha Wildner 
306281aef06SSascha Wildner 	AMDPM_LOCK_ASSERT(sc);
307a9656fbcSSascha Wildner 	/* Wait for command to complete (SMBus controller is idle) */
308a9656fbcSSascha Wildner 	while(count--) {
309a9656fbcSSascha Wildner 		DELAY(10);
310a9656fbcSSascha Wildner 		sts = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_STATUS);
311a9656fbcSSascha Wildner 		if (!(sts & AMDSMB_GS_HST_STS))
312a9656fbcSSascha Wildner 			break;
313a9656fbcSSascha Wildner 	}
314a9656fbcSSascha Wildner 
315a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: STS=0x%x (count=%d)\n", sts, count));
316a9656fbcSSascha Wildner 
317a9656fbcSSascha Wildner 	error = SMB_ENOERR;
318a9656fbcSSascha Wildner 
319a9656fbcSSascha Wildner 	if (!count)
320a9656fbcSSascha Wildner 		error |= SMB_ETIMEOUT;
321a9656fbcSSascha Wildner 
322a9656fbcSSascha Wildner 	if (sts & AMDSMB_GS_ABRT_STS)
323a9656fbcSSascha Wildner 		error |= SMB_EABORT;
324a9656fbcSSascha Wildner 
325a9656fbcSSascha Wildner 	if (sts & AMDSMB_GS_COL_STS)
326a9656fbcSSascha Wildner 		error |= SMB_ENOACK;
327a9656fbcSSascha Wildner 
328a9656fbcSSascha Wildner 	if (sts & AMDSMB_GS_PRERR_STS)
329a9656fbcSSascha Wildner 		error |= SMB_EBUSERR;
330a9656fbcSSascha Wildner 
331a9656fbcSSascha Wildner 	if (error != SMB_ENOERR)
332a9656fbcSSascha Wildner 		amdpm_clear(sc);
333a9656fbcSSascha Wildner 
334a9656fbcSSascha Wildner 	return (error);
335a9656fbcSSascha Wildner }
336a9656fbcSSascha Wildner 
337a9656fbcSSascha Wildner static int
amdpm_quick(device_t dev,u_char slave,int how)338a9656fbcSSascha Wildner amdpm_quick(device_t dev, u_char slave, int how)
339a9656fbcSSascha Wildner {
340a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
341a9656fbcSSascha Wildner 	int error;
342a9656fbcSSascha Wildner 	u_short l;
343a9656fbcSSascha Wildner 
344281aef06SSascha Wildner 	AMDPM_LOCK(sc);
345a9656fbcSSascha Wildner 	amdpm_clear(sc);
346281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
347281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
348a9656fbcSSascha Wildner 		return (EBUSY);
349281aef06SSascha Wildner 	}
350a9656fbcSSascha Wildner 
351a9656fbcSSascha Wildner 	switch (how) {
352a9656fbcSSascha Wildner 	case SMB_QWRITE:
353a9656fbcSSascha Wildner 		AMDPM_DEBUG(kprintf("amdpm: QWRITE to 0x%x", slave));
354a9656fbcSSascha Wildner 		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
355a9656fbcSSascha Wildner 		break;
356a9656fbcSSascha Wildner 	case SMB_QREAD:
357a9656fbcSSascha Wildner 		AMDPM_DEBUG(kprintf("amdpm: QREAD to 0x%x", slave));
358a9656fbcSSascha Wildner 		AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
359a9656fbcSSascha Wildner 		break;
360a9656fbcSSascha Wildner 	default:
361a9656fbcSSascha Wildner 		panic("%s: unknown QUICK command (%x)!", __func__, how);
362a9656fbcSSascha Wildner 	}
363a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
364a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC);
365a9656fbcSSascha Wildner 
366a9656fbcSSascha Wildner 	error = amdpm_wait(sc);
367a9656fbcSSascha Wildner 
368a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf(", error=0x%x\n", error));
369281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
370a9656fbcSSascha Wildner 
371a9656fbcSSascha Wildner 	return (error);
372a9656fbcSSascha Wildner }
373a9656fbcSSascha Wildner 
374a9656fbcSSascha Wildner static int
amdpm_sendb(device_t dev,u_char slave,char byte)375a9656fbcSSascha Wildner amdpm_sendb(device_t dev, u_char slave, char byte)
376a9656fbcSSascha Wildner {
377a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
378a9656fbcSSascha Wildner 	int error;
379a9656fbcSSascha Wildner 	u_short l;
380a9656fbcSSascha Wildner 
381281aef06SSascha Wildner 	AMDPM_LOCK(sc);
382a9656fbcSSascha Wildner 	amdpm_clear(sc);
383281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
384281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
385a9656fbcSSascha Wildner 		return (SMB_EBUSY);
386281aef06SSascha Wildner 	}
387a9656fbcSSascha Wildner 
388a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
389a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
390a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
391a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
392a9656fbcSSascha Wildner 
393a9656fbcSSascha Wildner 	error = amdpm_wait(sc);
394a9656fbcSSascha Wildner 
395a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
396281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
397a9656fbcSSascha Wildner 
398a9656fbcSSascha Wildner 	return (error);
399a9656fbcSSascha Wildner }
400a9656fbcSSascha Wildner 
401a9656fbcSSascha Wildner static int
amdpm_recvb(device_t dev,u_char slave,char * byte)402a9656fbcSSascha Wildner amdpm_recvb(device_t dev, u_char slave, char *byte)
403a9656fbcSSascha Wildner {
404a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
405a9656fbcSSascha Wildner 	int error;
406a9656fbcSSascha Wildner 	u_short l;
407a9656fbcSSascha Wildner 
408281aef06SSascha Wildner 	AMDPM_LOCK(sc);
409a9656fbcSSascha Wildner 	amdpm_clear(sc);
410281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
411281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
412a9656fbcSSascha Wildner 		return (SMB_EBUSY);
413281aef06SSascha Wildner 	}
414a9656fbcSSascha Wildner 
415a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
416a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
417a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
418a9656fbcSSascha Wildner 
419a9656fbcSSascha Wildner 	if ((error = amdpm_wait(sc)) == SMB_ENOERR)
420a9656fbcSSascha Wildner 		*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
421a9656fbcSSascha Wildner 
422a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
423281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
424a9656fbcSSascha Wildner 
425a9656fbcSSascha Wildner 	return (error);
426a9656fbcSSascha Wildner }
427a9656fbcSSascha Wildner 
428a9656fbcSSascha Wildner static int
amdpm_writeb(device_t dev,u_char slave,char cmd,char byte)429a9656fbcSSascha Wildner amdpm_writeb(device_t dev, u_char slave, char cmd, char byte)
430a9656fbcSSascha Wildner {
431a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
432a9656fbcSSascha Wildner 	int error;
433a9656fbcSSascha Wildner 	u_short l;
434a9656fbcSSascha Wildner 
435281aef06SSascha Wildner 	AMDPM_LOCK(sc);
436a9656fbcSSascha Wildner 	amdpm_clear(sc);
437281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
438281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
439a9656fbcSSascha Wildner 		return (SMB_EBUSY);
440281aef06SSascha Wildner 	}
441a9656fbcSSascha Wildner 
442a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
443a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, byte);
444a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
445a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
446a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
447a9656fbcSSascha Wildner 
448a9656fbcSSascha Wildner 	error = amdpm_wait(sc);
449a9656fbcSSascha Wildner 
450a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
451281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
452a9656fbcSSascha Wildner 
453a9656fbcSSascha Wildner 	return (error);
454a9656fbcSSascha Wildner }
455a9656fbcSSascha Wildner 
456a9656fbcSSascha Wildner static int
amdpm_readb(device_t dev,u_char slave,char cmd,char * byte)457a9656fbcSSascha Wildner amdpm_readb(device_t dev, u_char slave, char cmd, char *byte)
458a9656fbcSSascha Wildner {
459a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
460a9656fbcSSascha Wildner 	int error;
461a9656fbcSSascha Wildner 	u_short l;
462a9656fbcSSascha Wildner 
463281aef06SSascha Wildner 	AMDPM_LOCK(sc);
464a9656fbcSSascha Wildner 	amdpm_clear(sc);
465281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
466281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
467a9656fbcSSascha Wildner 		return (SMB_EBUSY);
468281aef06SSascha Wildner 	}
469a9656fbcSSascha Wildner 
470a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
471a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
472a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
473a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
474a9656fbcSSascha Wildner 
475a9656fbcSSascha Wildner 	if ((error = amdpm_wait(sc)) == SMB_ENOERR)
476a9656fbcSSascha Wildner 		*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
477a9656fbcSSascha Wildner 
478a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
479281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
480a9656fbcSSascha Wildner 
481a9656fbcSSascha Wildner 	return (error);
482a9656fbcSSascha Wildner }
483a9656fbcSSascha Wildner 
484a9656fbcSSascha Wildner static int
amdpm_writew(device_t dev,u_char slave,char cmd,short word)485a9656fbcSSascha Wildner amdpm_writew(device_t dev, u_char slave, char cmd, short word)
486a9656fbcSSascha Wildner {
487a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
488a9656fbcSSascha Wildner 	int error;
489a9656fbcSSascha Wildner 	u_short l;
490a9656fbcSSascha Wildner 
491281aef06SSascha Wildner 	AMDPM_LOCK(sc);
492a9656fbcSSascha Wildner 	amdpm_clear(sc);
493281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
494281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
495a9656fbcSSascha Wildner 		return (SMB_EBUSY);
496281aef06SSascha Wildner 	}
497a9656fbcSSascha Wildner 
498a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
499a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, word);
500a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
501a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
502a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
503a9656fbcSSascha Wildner 
504a9656fbcSSascha Wildner 	error = amdpm_wait(sc);
505a9656fbcSSascha Wildner 
506a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
507281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
508a9656fbcSSascha Wildner 
509a9656fbcSSascha Wildner 	return (error);
510a9656fbcSSascha Wildner }
511a9656fbcSSascha Wildner 
512a9656fbcSSascha Wildner static int
amdpm_readw(device_t dev,u_char slave,char cmd,short * word)513a9656fbcSSascha Wildner amdpm_readw(device_t dev, u_char slave, char cmd, short *word)
514a9656fbcSSascha Wildner {
515a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
516a9656fbcSSascha Wildner 	int error;
517a9656fbcSSascha Wildner 	u_short l;
518a9656fbcSSascha Wildner 
519281aef06SSascha Wildner 	AMDPM_LOCK(sc);
520a9656fbcSSascha Wildner 	amdpm_clear(sc);
521281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
522281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
523a9656fbcSSascha Wildner 		return (SMB_EBUSY);
524281aef06SSascha Wildner 	}
525a9656fbcSSascha Wildner 
526a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
527a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
528a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
529a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
530a9656fbcSSascha Wildner 
531a9656fbcSSascha Wildner 	if ((error = amdpm_wait(sc)) == SMB_ENOERR)
532a9656fbcSSascha Wildner 		*word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
533a9656fbcSSascha Wildner 
534a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
535281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
536a9656fbcSSascha Wildner 
537a9656fbcSSascha Wildner 	return (error);
538a9656fbcSSascha Wildner }
539a9656fbcSSascha Wildner 
540a9656fbcSSascha Wildner static int
amdpm_bwrite(device_t dev,u_char slave,char cmd,u_char count,char * buf)541a9656fbcSSascha Wildner amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
542a9656fbcSSascha Wildner {
543a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
544281aef06SSascha Wildner 	u_char i;
545281aef06SSascha Wildner 	int error;
546a9656fbcSSascha Wildner 	u_short l;
547a9656fbcSSascha Wildner 
548281aef06SSascha Wildner 	if (count < 1 || count > 32)
549281aef06SSascha Wildner 		return (SMB_EINVAL);
550a9656fbcSSascha Wildner 
551281aef06SSascha Wildner 	AMDPM_LOCK(sc);
552281aef06SSascha Wildner 	amdpm_clear(sc);
553281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
554281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
555281aef06SSascha Wildner 		return (SMB_EBUSY);
556281aef06SSascha Wildner 	}
557a9656fbcSSascha Wildner 
558a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
559a9656fbcSSascha Wildner 
560a9656fbcSSascha Wildner 	/*
561a9656fbcSSascha Wildner 	 * Do we have to reset the internal 32-byte buffer?
562a9656fbcSSascha Wildner 	 * Can't see how to do this from the data sheet.
563a9656fbcSSascha Wildner 	 */
564281aef06SSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTDATA, count);
565a9656fbcSSascha Wildner 
566a9656fbcSSascha Wildner 	/* Fill the 32-byte internal buffer */
567281aef06SSascha Wildner 	for (i = 0; i < count; i++) {
568281aef06SSascha Wildner 		AMDPM_SMBOUTB(sc, AMDSMB_HSTDFIFO, buf[i]);
569a9656fbcSSascha Wildner 		DELAY(2);
570a9656fbcSSascha Wildner 	}
571a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
572a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
573281aef06SSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE,
574281aef06SSascha Wildner 	    (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
575a9656fbcSSascha Wildner 
576281aef06SSascha Wildner 	error = amdpm_wait(sc);
577a9656fbcSSascha Wildner 
578a9656fbcSSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
579281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
580a9656fbcSSascha Wildner 
581a9656fbcSSascha Wildner 	return (error);
582a9656fbcSSascha Wildner }
583a9656fbcSSascha Wildner 
584a9656fbcSSascha Wildner static int
amdpm_bread(device_t dev,u_char slave,char cmd,u_char * count,char * buf)585281aef06SSascha Wildner amdpm_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
586a9656fbcSSascha Wildner {
587a9656fbcSSascha Wildner 	struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
588281aef06SSascha Wildner 	u_char data, len, i;
589281aef06SSascha Wildner 	int error;
590a9656fbcSSascha Wildner 	u_short l;
591a9656fbcSSascha Wildner 
592281aef06SSascha Wildner 	if (*count < 1 || *count > 32)
593281aef06SSascha Wildner 		return (SMB_EINVAL);
594a9656fbcSSascha Wildner 
595281aef06SSascha Wildner 	AMDPM_LOCK(sc);
596281aef06SSascha Wildner 	amdpm_clear(sc);
597281aef06SSascha Wildner 	if (!amdpm_idle(sc)) {
598281aef06SSascha Wildner 		AMDPM_UNLOCK(sc);
599281aef06SSascha Wildner 		return (SMB_EBUSY);
600281aef06SSascha Wildner 	}
601281aef06SSascha Wildner 
602a9656fbcSSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
603a9656fbcSSascha Wildner 
604a9656fbcSSascha Wildner 	AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
605a9656fbcSSascha Wildner 
606a9656fbcSSascha Wildner 	l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
607281aef06SSascha Wildner 	AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE,
608281aef06SSascha Wildner 	    (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
609a9656fbcSSascha Wildner 
610a9656fbcSSascha Wildner 	if ((error = amdpm_wait(sc)) != SMB_ENOERR)
611a9656fbcSSascha Wildner 		goto error;
612a9656fbcSSascha Wildner 
613a9656fbcSSascha Wildner 	len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
614a9656fbcSSascha Wildner 
615a9656fbcSSascha Wildner 	/* Read the 32-byte internal buffer */
616a9656fbcSSascha Wildner 	for (i = 0; i < len; i++) {
617281aef06SSascha Wildner 		data = AMDPM_SMBINB(sc, AMDSMB_HSTDFIFO);
618281aef06SSascha Wildner 		if (i < *count)
619281aef06SSascha Wildner 			buf[i] = data;
620a9656fbcSSascha Wildner 		DELAY(2);
621a9656fbcSSascha Wildner 	}
622281aef06SSascha Wildner 	*count = len;
623a9656fbcSSascha Wildner 
624a9656fbcSSascha Wildner error:
625281aef06SSascha Wildner 	AMDPM_DEBUG(kprintf("amdpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
626281aef06SSascha Wildner 	AMDPM_UNLOCK(sc);
627a9656fbcSSascha Wildner 
628a9656fbcSSascha Wildner 	return (error);
629a9656fbcSSascha Wildner }
630a9656fbcSSascha Wildner 
631a9656fbcSSascha Wildner static devclass_t amdpm_devclass;
632a9656fbcSSascha Wildner 
633a9656fbcSSascha Wildner static device_method_t amdpm_methods[] = {
634a9656fbcSSascha Wildner 	/* Device interface */
635a9656fbcSSascha Wildner 	DEVMETHOD(device_probe,		amdpm_probe),
636a9656fbcSSascha Wildner 	DEVMETHOD(device_attach,	amdpm_attach),
637a9656fbcSSascha Wildner 	DEVMETHOD(device_detach,	amdpm_detach),
638a9656fbcSSascha Wildner 
639a9656fbcSSascha Wildner 	/* SMBus interface */
640a9656fbcSSascha Wildner 	DEVMETHOD(smbus_callback,	amdpm_callback),
641a9656fbcSSascha Wildner 	DEVMETHOD(smbus_quick,		amdpm_quick),
642a9656fbcSSascha Wildner 	DEVMETHOD(smbus_sendb,		amdpm_sendb),
643a9656fbcSSascha Wildner 	DEVMETHOD(smbus_recvb,		amdpm_recvb),
644a9656fbcSSascha Wildner 	DEVMETHOD(smbus_writeb,		amdpm_writeb),
645a9656fbcSSascha Wildner 	DEVMETHOD(smbus_readb,		amdpm_readb),
646a9656fbcSSascha Wildner 	DEVMETHOD(smbus_writew,		amdpm_writew),
647a9656fbcSSascha Wildner 	DEVMETHOD(smbus_readw,		amdpm_readw),
648a9656fbcSSascha Wildner 	DEVMETHOD(smbus_bwrite,		amdpm_bwrite),
649a9656fbcSSascha Wildner 	DEVMETHOD(smbus_bread,		amdpm_bread),
650a9656fbcSSascha Wildner 
651*d3c9c58eSSascha Wildner 	DEVMETHOD_END
652a9656fbcSSascha Wildner };
653a9656fbcSSascha Wildner 
654a9656fbcSSascha Wildner static driver_t amdpm_driver = {
655a9656fbcSSascha Wildner 	"amdpm",
656a9656fbcSSascha Wildner 	amdpm_methods,
657a9656fbcSSascha Wildner 	sizeof(struct amdpm_softc),
658a9656fbcSSascha Wildner };
659a9656fbcSSascha Wildner 
660aa2b9d05SSascha Wildner DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, NULL, NULL);
661aa2b9d05SSascha Wildner DRIVER_MODULE(smbus, amdpm, smbus_driver, smbus_devclass, NULL, NULL);
662a9656fbcSSascha Wildner 
663a9656fbcSSascha Wildner MODULE_DEPEND(amdpm, pci, 1, 1, 1);
664a9656fbcSSascha Wildner MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
665a9656fbcSSascha Wildner MODULE_VERSION(amdpm, 1);
666