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