xref: /dflybsd-src/sys/dev/powermng/alpm/alpm.c (revision a9656fbcd49c376aba5e04370d8b0f1fa96e063c)
1 /*-
2  * Copyright (c) 1998, 1999, 2001 Nicolas Souchu
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/pci/alpm.c,v 1.24 2005/05/29 04:42:29 nyan Exp $
27  *
28  */
29 
30 /*
31  * Power Management support for the Acer M15x3 chipsets
32  */
33 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
36 #include <sys/module.h>
37 #include <sys/bus.h>
38 #include <sys/uio.h>
39 #include <sys/rman.h>
40 
41 #include <bus/pci/pcivar.h>
42 #include <bus/pci/pcireg.h>
43 
44 #include <bus/iicbus/iiconf.h>
45 #include <bus/smbus/smbconf.h>
46 #include "smbus_if.h"
47 
48 #define ALPM_DEBUG(x)	if (alpm_debug) (x)
49 
50 #ifdef DEBUG
51 static int alpm_debug = 1;
52 #else
53 static int alpm_debug = 0;
54 #endif
55 
56 #define ACER_M1543_PMU_ID	0x710110b9
57 
58 /* Uncomment this line to force another I/O base address for SMB */
59 /* #define ALPM_SMBIO_BASE_ADDR	0x3a80 */
60 
61 /* I/O registers offsets - the base address is programmed via the
62  * SMBBA PCI configuration register
63  */
64 #define SMBSTS		0x0	/* SMBus host/slave status register */
65 #define SMBCMD		0x1	/* SMBus host/slave command register */
66 #define SMBSTART	0x2	/* start to generate programmed cycle */
67 #define SMBHADDR	0x3	/* host address register */
68 #define SMBHDATA	0x4	/* data A register for host controller */
69 #define SMBHDATB	0x5	/* data B register for host controller */
70 #define SMBHBLOCK	0x6	/* block register for host controller */
71 #define SMBHCMD		0x7	/* command register for host controller */
72 
73 /* SMBSTS masks */
74 #define TERMINATE	0x80
75 #define BUS_COLLI	0x40
76 #define DEVICE_ERR	0x20
77 #define SMI_I_STS	0x10
78 #define HST_BSY		0x08
79 #define IDL_STS		0x04
80 #define HSTSLV_STS	0x02
81 #define HSTSLV_BSY	0x01
82 
83 /* SMBCMD masks */
84 #define SMB_BLK_CLR	0x80
85 #define T_OUT_CMD	0x08
86 #define ABORT_HOST	0x04
87 
88 /* SMBus commands */
89 #define SMBQUICK	0x00
90 #define SMBSRBYTE	0x10		/* send/receive byte */
91 #define SMBWRBYTE	0x20		/* write/read byte */
92 #define SMBWRWORD	0x30		/* write/read word */
93 #define SMBWRBLOCK	0x40		/* write/read block */
94 
95 /* PCI configuration registers and masks
96  */
97 #define COM		0x4
98 #define COM_ENABLE_IO	0x1
99 
100 #define SMBBA		0x14
101 
102 #define ATPC		0x5b
103 #define ATPC_SMBCTRL	0x04		/* XX linux has this as 0x6 */
104 
105 #define SMBHSI		0xe0
106 #define SMBHSI_SLAVE	0x2
107 #define SMBHSI_HOST	0x1
108 
109 #define SMBHCBC		0xe2
110 #define SMBHCBC_CLOCK	0x70
111 
112 #define SMBCLOCK_149K	0x0
113 #define SMBCLOCK_74K	0x20
114 #define SMBCLOCK_37K	0x40
115 #define SMBCLOCK_223K	0x80
116 #define SMBCLOCK_111K	0xa0
117 #define SMBCLOCK_55K	0xc0
118 
119 struct alpm_softc {
120 	int base;
121 	struct resource *res;
122         bus_space_tag_t smbst;
123         bus_space_handle_t smbsh;
124 	device_t smbus;
125 };
126 
127 #define ALPM_SMBINB(alpm,register) \
128 	(bus_space_read_1(alpm->smbst, alpm->smbsh, register))
129 #define ALPM_SMBOUTB(alpm,register,value) \
130 	(bus_space_write_1(alpm->smbst, alpm->smbsh, register, value))
131 
132 static int
133 alpm_probe(device_t dev)
134 {
135 #ifdef ALPM_SMBIO_BASE_ADDR
136 	u_int32_t l;
137 #endif
138 
139 	if(pci_get_devid(dev) == ACER_M1543_PMU_ID) {
140 		device_set_desc(dev, "AcerLabs M15x3 Power Management Unit");
141 
142 #ifdef ALPM_SMBIO_BASE_ADDR
143 		if (bootverbose || alpm_debug)
144 			device_printf(dev, "forcing base I/O at 0x%x\n",
145 					ALPM_SMBIO_BASE_ADDR);
146 
147 		/* disable I/O */
148 		l = pci_read_config(dev, COM, 2);
149 		pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2);
150 
151 		/* set the I/O base address */
152 		pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4);
153 
154 		/* enable I/O */
155 		pci_write_config(dev, COM, l | COM_ENABLE_IO, 2);
156 
157 		if (bus_set_resource(dev, SYS_RES_IOPORT, SMBBA,
158 					ALPM_SMBIO_BASE_ADDR, 256)) {
159 			device_printf(dev, "could not set bus resource\n");
160 			return (ENXIO);
161 		}
162 #endif
163 		return (BUS_PROBE_DEFAULT);
164 	}
165 
166 	return (ENXIO);
167 }
168 
169 static int
170 alpm_attach(device_t dev)
171 {
172 	int rid;
173 	u_int32_t l;
174 	struct alpm_softc *alpm;
175 
176 	alpm = device_get_softc(dev);
177 
178 	/* Unlock SMBIO base register access */
179 	l = pci_read_config(dev, ATPC, 1);
180 	pci_write_config(dev, ATPC, l & ~ATPC_SMBCTRL, 1);
181 
182 	/*
183 	 * XX linux sets clock to 74k, should we?
184 	l = pci_read_config(dev, SMBHCBC, 1);
185 	l &= 0x1f;
186 	l |= SMBCLOCK_74K;
187 	pci_write_config(dev, SMBHCBC, l, 1)
188 	 */
189 
190 	if (bootverbose || alpm_debug) {
191 		l = pci_read_config(dev, SMBHSI, 1);
192 		device_printf(dev, "%s/%s",
193 			(l & SMBHSI_HOST) ? "host":"nohost",
194 			(l & SMBHSI_SLAVE) ? "slave":"noslave");
195 
196 		l = pci_read_config(dev, SMBHCBC, 1);
197 		switch (l & SMBHCBC_CLOCK) {
198 		case SMBCLOCK_149K:
199 			kprintf(" 149K");
200 			break;
201 		case SMBCLOCK_74K:
202 			kprintf(" 74K");
203 			break;
204 		case SMBCLOCK_37K:
205 			kprintf(" 37K");
206 			break;
207 		case SMBCLOCK_223K:
208 			kprintf(" 223K");
209 			break;
210 		case SMBCLOCK_111K:
211 			kprintf(" 111K");
212 			break;
213 		case SMBCLOCK_55K:
214 			kprintf(" 55K");
215 			break;
216 		default:
217 			kprintf("unkown");
218 			break;
219 		}
220 		kprintf("\n");
221 	}
222 
223 	rid = SMBBA;
224 	alpm->res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
225 	    RF_ACTIVE);
226 
227 	if (alpm->res == NULL) {
228 		device_printf(dev, "Could not allocate Bus space\n");
229 		return (ENXIO);
230 	}
231 	alpm->smbst = rman_get_bustag(alpm->res);
232 	alpm->smbsh = rman_get_bushandle(alpm->res);
233 
234 	/* attach the smbus */
235 	alpm->smbus = device_add_child(dev, "smbus", -1);
236 	bus_generic_attach(dev);
237 
238 	return (0);
239 }
240 
241 static int
242 alpm_detach(device_t dev)
243 {
244 	struct alpm_softc *alpm = device_get_softc(dev);
245 
246 	if (alpm->smbus) {
247 		device_delete_child(dev, alpm->smbus);
248 		alpm->smbus = NULL;
249 	}
250 
251 	if (alpm->res)
252 		bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res);
253 
254 	return (0);
255 }
256 
257 static int
258 alpm_callback(device_t dev, int index, caddr_t *data)
259 {
260 	int error = 0;
261 
262 	switch (index) {
263 	case SMB_REQUEST_BUS:
264 	case SMB_RELEASE_BUS:
265 		/* ok, bus allocation accepted */
266 		break;
267 	default:
268 		error = EINVAL;
269 	}
270 
271 	return (error);
272 }
273 
274 static int
275 alpm_clear(struct alpm_softc *sc)
276 {
277 	ALPM_SMBOUTB(sc, SMBSTS, 0xff);
278 	DELAY(10);
279 
280 	return (0);
281 }
282 
283 #if 0
284 static int
285 alpm_abort(struct alpm_softc *sc)
286 {
287 	ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST);
288 
289 	return (0);
290 }
291 #endif
292 
293 static int
294 alpm_idle(struct alpm_softc *sc)
295 {
296 	u_char sts;
297 
298 	sts = ALPM_SMBINB(sc, SMBSTS);
299 
300 	ALPM_DEBUG(kprintf("alpm: idle? STS=0x%x\n", sts));
301 
302 	return (sts & IDL_STS);
303 }
304 
305 /*
306  * Poll the SMBus controller
307  */
308 static int
309 alpm_wait(struct alpm_softc *sc)
310 {
311 	int count = 10000;
312 	u_char sts = 0;
313 	int error;
314 
315 	/* wait for command to complete and SMBus controller is idle */
316 	while(count--) {
317 		DELAY(10);
318 		sts = ALPM_SMBINB(sc, SMBSTS);
319 		if (sts & SMI_I_STS)
320 			break;
321 	}
322 
323 	ALPM_DEBUG(kprintf("alpm: STS=0x%x\n", sts));
324 
325 	error = SMB_ENOERR;
326 
327 	if (!count)
328 		error |= SMB_ETIMEOUT;
329 
330 	if (sts & TERMINATE)
331 		error |= SMB_EABORT;
332 
333 	if (sts & BUS_COLLI)
334 		error |= SMB_ENOACK;
335 
336 	if (sts & DEVICE_ERR)
337 		error |= SMB_EBUSERR;
338 
339 	if (error != SMB_ENOERR)
340 		alpm_clear(sc);
341 
342 	return (error);
343 }
344 
345 static int
346 alpm_quick(device_t dev, u_char slave, int how)
347 {
348 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
349 	int error;
350 
351 	alpm_clear(sc);
352 	if (!alpm_idle(sc))
353 		return (EBUSY);
354 
355 	switch (how) {
356 	case SMB_QWRITE:
357 		ALPM_DEBUG(kprintf("alpm: QWRITE to 0x%x", slave));
358 		ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
359 		break;
360 	case SMB_QREAD:
361 		ALPM_DEBUG(kprintf("alpm: QREAD to 0x%x", slave));
362 		ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
363 		break;
364 	default:
365 		panic("%s: unknown QUICK command (%x)!", __func__, how);
366 	}
367 	ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK);
368 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
369 
370 	error = alpm_wait(sc);
371 
372 	ALPM_DEBUG(kprintf(", error=0x%x\n", error));
373 
374 	return (error);
375 }
376 
377 static int
378 alpm_sendb(device_t dev, u_char slave, char byte)
379 {
380 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
381 	int error;
382 
383 	alpm_clear(sc);
384 	if (!alpm_idle(sc))
385 		return (SMB_EBUSY);
386 
387 	ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
388 	ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
389 	ALPM_SMBOUTB(sc, SMBHDATA, byte);
390 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
391 
392 	error = alpm_wait(sc);
393 
394 	ALPM_DEBUG(kprintf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
395 
396 	return (error);
397 }
398 
399 static int
400 alpm_recvb(device_t dev, u_char slave, char *byte)
401 {
402 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
403 	int error;
404 
405 	alpm_clear(sc);
406 	if (!alpm_idle(sc))
407 		return (SMB_EBUSY);
408 
409 	ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
410 	ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
411 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
412 
413 	if ((error = alpm_wait(sc)) == SMB_ENOERR)
414 		*byte = ALPM_SMBINB(sc, SMBHDATA);
415 
416 	ALPM_DEBUG(kprintf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
417 
418 	return (error);
419 }
420 
421 static int
422 alpm_writeb(device_t dev, u_char slave, char cmd, char byte)
423 {
424 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
425 	int error;
426 
427 	alpm_clear(sc);
428 	if (!alpm_idle(sc))
429 		return (SMB_EBUSY);
430 
431 	ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
432 	ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
433 	ALPM_SMBOUTB(sc, SMBHDATA, byte);
434 	ALPM_SMBOUTB(sc, SMBHCMD, cmd);
435 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
436 
437 	error = alpm_wait(sc);
438 
439 	ALPM_DEBUG(kprintf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
440 
441 	return (error);
442 }
443 
444 static int
445 alpm_readb(device_t dev, u_char slave, char cmd, char *byte)
446 {
447 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
448 	int error;
449 
450 	alpm_clear(sc);
451 	if (!alpm_idle(sc))
452 		return (SMB_EBUSY);
453 
454 	ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
455 	ALPM_SMBOUTB(sc, SMBCMD, SMBWRBYTE);
456 	ALPM_SMBOUTB(sc, SMBHCMD, cmd);
457 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
458 
459 	if ((error = alpm_wait(sc)) == SMB_ENOERR)
460 		*byte = ALPM_SMBINB(sc, SMBHDATA);
461 
462 	ALPM_DEBUG(kprintf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
463 
464 	return (error);
465 }
466 
467 static int
468 alpm_writew(device_t dev, u_char slave, char cmd, short word)
469 {
470 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
471 	int error;
472 
473 	alpm_clear(sc);
474 	if (!alpm_idle(sc))
475 		return (SMB_EBUSY);
476 
477 	ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
478 	ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
479 	ALPM_SMBOUTB(sc, SMBHDATA, word & 0x00ff);
480 	ALPM_SMBOUTB(sc, SMBHDATB, (word & 0xff00) >> 8);
481 	ALPM_SMBOUTB(sc, SMBHCMD, cmd);
482 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
483 
484 	error = alpm_wait(sc);
485 
486 	ALPM_DEBUG(kprintf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
487 
488 	return (error);
489 }
490 
491 static int
492 alpm_readw(device_t dev, u_char slave, char cmd, short *word)
493 {
494 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
495 	int error;
496 	u_char high, low;
497 
498 	alpm_clear(sc);
499 	if (!alpm_idle(sc))
500 		return (SMB_EBUSY);
501 
502 	ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
503 	ALPM_SMBOUTB(sc, SMBCMD, SMBWRWORD);
504 	ALPM_SMBOUTB(sc, SMBHCMD, cmd);
505 	ALPM_SMBOUTB(sc, SMBSTART, 0xff);
506 
507 	if ((error = alpm_wait(sc)) == SMB_ENOERR) {
508 		low = ALPM_SMBINB(sc, SMBHDATA);
509 		high = ALPM_SMBINB(sc, SMBHDATB);
510 
511 		*word = ((high & 0xff) << 8) | (low & 0xff);
512 	}
513 
514 	ALPM_DEBUG(kprintf("alpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
515 
516 	return (error);
517 }
518 
519 static int
520 alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
521 {
522 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
523 	u_char remain, len, i;
524 	int error = SMB_ENOERR;
525 
526 	alpm_clear(sc);
527 	if(!alpm_idle(sc))
528 		return (SMB_EBUSY);
529 
530 	remain = count;
531 	while (remain) {
532 		len = min(remain, 32);
533 
534 		ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
535 
536 		/* set the cmd and reset the
537 		 * 32-byte long internal buffer */
538 		ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
539 
540 		ALPM_SMBOUTB(sc, SMBHDATA, len);
541 
542 		/* fill the 32-byte internal buffer */
543 		for (i=0; i<len; i++) {
544 			ALPM_SMBOUTB(sc, SMBHBLOCK, buf[count-remain+i]);
545 			DELAY(2);
546 		}
547 		ALPM_SMBOUTB(sc, SMBHCMD, cmd);
548 		ALPM_SMBOUTB(sc, SMBSTART, 0xff);
549 
550 		if ((error = alpm_wait(sc)) != SMB_ENOERR)
551 			goto error;
552 
553 		remain -= len;
554 	}
555 
556 error:
557 	ALPM_DEBUG(kprintf("alpm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
558 
559 	return (error);
560 }
561 
562 static int
563 alpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
564 {
565 	struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
566 	u_char remain, len, i;
567 	int error = SMB_ENOERR;
568 
569 	alpm_clear(sc);
570 	if (!alpm_idle(sc))
571 		return (SMB_EBUSY);
572 
573 	remain = count;
574 	while (remain) {
575 		ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
576 
577 		/* set the cmd and reset the
578 		 * 32-byte long internal buffer */
579 		ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
580 
581 		ALPM_SMBOUTB(sc, SMBHCMD, cmd);
582 		ALPM_SMBOUTB(sc, SMBSTART, 0xff);
583 
584 		if ((error = alpm_wait(sc)) != SMB_ENOERR)
585 			goto error;
586 
587 		len = ALPM_SMBINB(sc, SMBHDATA);
588 
589 		/* read the 32-byte internal buffer */
590 		for (i=0; i<len; i++) {
591 			buf[count-remain+i] = ALPM_SMBINB(sc, SMBHBLOCK);
592 			DELAY(2);
593 		}
594 
595 		remain -= len;
596 	}
597 error:
598 	ALPM_DEBUG(kprintf("alpm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
599 
600 	return (error);
601 }
602 
603 static devclass_t alpm_devclass;
604 
605 static device_method_t alpm_methods[] = {
606 	/* device interface */
607 	DEVMETHOD(device_probe,		alpm_probe),
608 	DEVMETHOD(device_attach,	alpm_attach),
609 	DEVMETHOD(device_detach,	alpm_detach),
610 
611 	/* smbus interface */
612 	DEVMETHOD(smbus_callback,	alpm_callback),
613 	DEVMETHOD(smbus_quick,		alpm_quick),
614 	DEVMETHOD(smbus_sendb,		alpm_sendb),
615 	DEVMETHOD(smbus_recvb,		alpm_recvb),
616 	DEVMETHOD(smbus_writeb,		alpm_writeb),
617 	DEVMETHOD(smbus_readb,		alpm_readb),
618 	DEVMETHOD(smbus_writew,		alpm_writew),
619 	DEVMETHOD(smbus_readw,		alpm_readw),
620 	DEVMETHOD(smbus_bwrite,		alpm_bwrite),
621 	DEVMETHOD(smbus_bread,		alpm_bread),
622 
623 	{ 0, 0 }
624 };
625 
626 static driver_t alpm_driver = {
627 	"alpm",
628 	alpm_methods,
629 	sizeof(struct alpm_softc)
630 };
631 
632 DRIVER_MODULE(alpm, pci, alpm_driver, alpm_devclass, 0, 0);
633 MODULE_DEPEND(alpm, pci, 1, 1, 1);
634 MODULE_DEPEND(alpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
635 MODULE_VERSION(alpm, 1);
636