FreeBSD/Linux Kernel Cross Reference
sys/pci/viapm.c
1 /*-
2 * Copyright (c) 2001 Alcove - 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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/6.3/sys/pci/viapm.c 173886 2007-11-24 19:45:58Z cvs2svn $");
29
30 #include "opt_isa.h"
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/systm.h>
35 #include <sys/module.h>
36 #include <sys/bus.h>
37 #include <sys/uio.h>
38
39 #include <machine/bus.h>
40 #include <machine/clock.h> /* for DELAY */
41 #include <machine/resource.h>
42 #include <sys/rman.h>
43
44 #ifdef DEV_ISA
45 #include <isa/isavar.h>
46 #include <isa/isa_common.h>
47 #endif
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcireg.h>
50
51 #include <dev/iicbus/iiconf.h>
52
53 #include <dev/smbus/smbconf.h>
54
55 #include "iicbb_if.h"
56 #include "smbus_if.h"
57
58 #define VIAPM_DEBUG(x) if (viapm_debug) (x)
59
60 #ifdef DEBUG
61 static int viapm_debug = 1;
62 #else
63 static int viapm_debug = 0;
64 #endif
65
66 #define VIA_586B_PMU_ID 0x30401106
67 #define VIA_596A_PMU_ID 0x30501106
68 #define VIA_596B_PMU_ID 0x30511106
69 #define VIA_686A_PMU_ID 0x30571106
70 #define VIA_8233_PMU_ID 0x30741106
71 #define VIA_8233A_PMU_ID 0x31471106
72 #define VIA_8235_PMU_ID 0x31771106
73
74 #define VIAPM_INB(port) \
75 ((u_char)bus_space_read_1(viapm->st, viapm->sh, port))
76 #define VIAPM_OUTB(port,val) \
77 (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)(val)))
78
79 #define VIAPM_TYP_UNKNOWN 0
80 #define VIAPM_TYP_586B_3040E 1
81 #define VIAPM_TYP_586B_3040F 2
82 #define VIAPM_TYP_596B 3
83 #define VIAPM_TYP_686A 4
84 #define VIAPM_TYP_8233 5
85
86 struct viapm_softc {
87 int type;
88 u_int32_t base;
89 bus_space_tag_t st;
90 bus_space_handle_t sh;
91 int iorid;
92 int irqrid;
93 struct resource *iores;
94 struct resource *irqres;
95 void *irqih;
96
97 device_t iicbb;
98 device_t smbus;
99 };
100
101 static devclass_t viapm_devclass;
102 static devclass_t viapropm_devclass;
103
104 /*
105 * VT82C586B definitions
106 */
107
108 #define VIAPM_586B_REVID 0x08
109
110 #define VIAPM_586B_3040E_BASE 0x20
111 #define VIAPM_586B_3040E_ACTIV 0x4 /* 16 bits */
112
113 #define VIAPM_586B_3040F_BASE 0x48
114 #define VIAPM_586B_3040F_ACTIV 0x41 /* 8 bits */
115
116 #define VIAPM_586B_OEM_REV_E 0x00
117 #define VIAPM_586B_OEM_REV_F 0x01
118 #define VIAPM_586B_PROD_REV_A 0x10
119
120 #define VIAPM_586B_BA_MASK 0x0000ff00
121
122 #define GPIO_DIR 0x40
123 #define GPIO_VAL 0x42
124 #define EXTSMI_VAL 0x44
125
126 #define VIAPM_SCL 0x02 /* GPIO1_VAL */
127 #define VIAPM_SDA 0x04 /* GPIO2_VAL */
128
129 /*
130 * VIAPRO common definitions
131 */
132
133 #define VIAPM_PRO_BA_MASK 0x0000fff0
134 #define VIAPM_PRO_SMBCTRL 0xd2
135 #define VIAPM_PRO_REVID 0xd6
136
137 /*
138 * VT82C686A definitions
139 */
140
141 #define VIAPM_PRO_BASE 0x90
142
143 #define SMBHST 0x0
144 #define SMBHSL 0x1
145 #define SMBHCTRL 0x2
146 #define SMBHCMD 0x3
147 #define SMBHADDR 0x4
148 #define SMBHDATA0 0x5
149 #define SMBHDATA1 0x6
150 #define SMBHBLOCK 0x7
151
152 #define SMBSST 0x1
153 #define SMBSCTRL 0x8
154 #define SMBSSDWCMD 0x9
155 #define SMBSEVENT 0xa
156 #define SMBSDATA 0xc
157
158 #define SMBHST_RESERVED 0xef /* reserved bits */
159 #define SMBHST_FAILED 0x10 /* failed bus transaction */
160 #define SMBHST_COLLID 0x08 /* bus collision */
161 #define SMBHST_ERROR 0x04 /* device error */
162 #define SMBHST_INTR 0x02 /* command completed */
163 #define SMBHST_BUSY 0x01 /* host busy */
164
165 #define SMBHCTRL_START 0x40 /* start command */
166 #define SMBHCTRL_PROTO 0x1c /* command protocol mask */
167 #define SMBHCTRL_QUICK 0x00
168 #define SMBHCTRL_SENDRECV 0x04
169 #define SMBHCTRL_BYTE 0x08
170 #define SMBHCTRL_WORD 0x0c
171 #define SMBHCTRL_BLOCK 0x14
172 #define SMBHCTRL_KILL 0x02 /* stop the current transaction */
173 #define SMBHCTRL_ENABLE 0x01 /* enable interrupts */
174
175 #define SMBSCTRL_ENABLE 0x01 /* enable slave */
176
177
178 /*
179 * VIA8233 definitions
180 */
181
182 #define VIAPM_8233_BASE 0xD0
183
184 static int
185 viapm_586b_probe(device_t dev)
186 {
187 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
188 u_int32_t l;
189 u_int16_t s;
190 u_int8_t c;
191
192 switch (pci_get_devid(dev)) {
193 case VIA_586B_PMU_ID:
194
195 bzero(viapm, sizeof(struct viapm_softc));
196
197 l = pci_read_config(dev, VIAPM_586B_REVID, 1);
198 switch (l) {
199 case VIAPM_586B_OEM_REV_E:
200 viapm->type = VIAPM_TYP_586B_3040E;
201 viapm->iorid = VIAPM_586B_3040E_BASE;
202
203 /* Activate IO block access */
204 s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
205 pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
206 break;
207
208 case VIAPM_586B_OEM_REV_F:
209 case VIAPM_586B_PROD_REV_A:
210 default:
211 viapm->type = VIAPM_TYP_586B_3040F;
212 viapm->iorid = VIAPM_586B_3040F_BASE;
213
214 /* Activate IO block access */
215 c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
216 pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
217 break;
218 }
219
220 viapm->base = pci_read_config(dev, viapm->iorid, 4) &
221 VIAPM_586B_BA_MASK;
222
223 /*
224 * We have to set the I/O resources by hand because it is
225 * described outside the viapmope of the traditional maps
226 */
227 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
228 viapm->base, 256)) {
229 device_printf(dev, "could not set bus resource\n");
230 return ENXIO;
231 }
232 device_set_desc(dev, "VIA VT82C586B Power Management Unit");
233 return (BUS_PROBE_DEFAULT);
234
235 default:
236 break;
237 }
238
239 return ENXIO;
240 }
241
242
243 static int
244 viapm_pro_probe(device_t dev)
245 {
246 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
247 #ifdef VIAPM_BASE_ADDR
248 u_int32_t l;
249 #endif
250 u_int32_t base_cfgreg;
251 char *desc;
252
253 switch (pci_get_devid(dev)) {
254 case VIA_596A_PMU_ID:
255 desc = "VIA VT82C596A Power Management Unit";
256 viapm->type = VIAPM_TYP_596B;
257 base_cfgreg = VIAPM_PRO_BASE;
258 goto viapro;
259
260 case VIA_596B_PMU_ID:
261 desc = "VIA VT82C596B Power Management Unit";
262 viapm->type = VIAPM_TYP_596B;
263 base_cfgreg = VIAPM_PRO_BASE;
264 goto viapro;
265
266 case VIA_686A_PMU_ID:
267 desc = "VIA VT82C686A Power Management Unit";
268 viapm->type = VIAPM_TYP_686A;
269 base_cfgreg = VIAPM_PRO_BASE;
270 goto viapro;
271
272 case VIA_8233_PMU_ID:
273 case VIA_8233A_PMU_ID:
274 desc = "VIA VT8233 Power Management Unit";
275 viapm->type = VIAPM_TYP_UNKNOWN;
276 base_cfgreg = VIAPM_8233_BASE;
277 goto viapro;
278
279 case VIA_8235_PMU_ID:
280 desc = "VIA VT8235 Power Management Unit";
281 viapm->type = VIAPM_TYP_UNKNOWN;
282 base_cfgreg = VIAPM_8233_BASE;
283 goto viapro;
284
285 viapro:
286
287 #ifdef VIAPM_BASE_ADDR
288 /* force VIAPM I/O base address */
289
290 /* enable the SMBus controller function */
291 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
292 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
293
294 /* write the base address */
295 pci_write_config(dev, base_cfgreg,
296 VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
297 #endif
298
299 viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
300
301 /*
302 * We have to set the I/O resources by hand because it is
303 * described outside the viapmope of the traditional maps
304 */
305 viapm->iorid = base_cfgreg;
306 if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
307 viapm->base, 16)) {
308 device_printf(dev, "could not set bus resource 0x%x\n",
309 viapm->base);
310 return ENXIO;
311 }
312
313 if (1 || bootverbose) {
314 device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
315 }
316
317 device_set_desc(dev, desc);
318 return (BUS_PROBE_DEFAULT);
319
320 default:
321 break;
322 }
323
324 return ENXIO;
325 }
326
327 static int
328 viapm_pro_attach(device_t dev)
329 {
330 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
331 u_int32_t l;
332
333 if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
334 &viapm->iorid, RF_ACTIVE))) {
335 device_printf(dev, "could not allocate bus space\n");
336 goto error;
337 }
338 viapm->st = rman_get_bustag(viapm->iores);
339 viapm->sh = rman_get_bushandle(viapm->iores);
340
341 #if notyet
342 /* force irq 9 */
343 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
344 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
345
346 viapm->irqrid = 0;
347 if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
348 &viapm->irqrid, 9, 9, 1,
349 RF_SHAREABLE | RF_ACTIVE))) {
350 device_printf(dev, "could not allocate irq\n");
351 goto error;
352 }
353
354 if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC,
355 (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
356 device_printf(dev, "could not setup irq\n");
357 goto error;
358 }
359 #endif
360
361 if (1 | bootverbose) {
362 l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
363 device_printf(dev, "SMBus revision code 0x%x\n", l);
364 }
365
366 viapm->smbus = device_add_child(dev, "smbus", -1);
367
368 /* probe and attach the smbus */
369 bus_generic_attach(dev);
370
371 /* disable slave function */
372 VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
373
374 /* enable the SMBus controller function */
375 l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
376 pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
377
378 #if notyet
379 /* enable interrupts */
380 VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
381 #endif
382
383 #ifdef DEV_ISA
384 /* If this device is a PCI-ISA bridge, then attach an ISA bus. */
385 if ((pci_get_class(dev) == PCIC_BRIDGE) &&
386 (pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
387 isab_attach(dev);
388 #endif
389 return 0;
390
391 error:
392 if (viapm->iores)
393 bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
394 #if notyet
395 if (viapm->irqres)
396 bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
397 #endif
398
399 return ENXIO;
400 }
401
402 static int
403 viapm_586b_attach(device_t dev)
404 {
405 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
406
407 if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
408 &viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
409 device_printf(dev, "could not allocate bus resource\n");
410 return ENXIO;
411 }
412 viapm->st = rman_get_bustag(viapm->iores);
413 viapm->sh = rman_get_bushandle(viapm->iores);
414
415 VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
416
417 /* add generic bit-banging code */
418 if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
419 goto error;
420
421 bus_generic_attach(dev);
422
423 return 0;
424
425 error:
426 if (viapm->iores)
427 bus_release_resource(dev, SYS_RES_IOPORT,
428 viapm->iorid, viapm->iores);
429 return ENXIO;
430 }
431
432 static int
433 viapm_586b_detach(device_t dev)
434 {
435 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
436 int error;
437
438 bus_generic_detach(dev);
439 if (viapm->iicbb) {
440 device_delete_child(dev, viapm->iicbb);
441 }
442
443 if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT,
444 viapm->iorid, viapm->iores)))
445 return (error);
446
447 return 0;
448 }
449
450 static int
451 viapm_pro_detach(device_t dev)
452 {
453 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
454 int error;
455
456 bus_generic_detach(dev);
457 if (viapm->smbus) {
458 device_delete_child(dev, viapm->smbus);
459 }
460
461 if ((error = bus_release_resource(dev, SYS_RES_IOPORT,
462 viapm->iorid, viapm->iores)))
463 return (error);
464
465 #if notyet
466 if ((error = bus_release_resource(dev, SYS_RES_IRQ,
467 viapm->irqrid, viapm->irqres))
468 return (error);
469 #endif
470
471 return 0;
472 }
473
474 static int
475 viabb_callback(device_t dev, int index, caddr_t *data)
476 {
477 return 0;
478 }
479
480 static void
481 viabb_setscl(device_t dev, int ctrl)
482 {
483 struct viapm_softc *viapm = device_get_softc(dev);
484 u_char val;
485
486 val = VIAPM_INB(GPIO_VAL);
487
488 if (ctrl)
489 val |= VIAPM_SCL;
490 else
491 val &= ~VIAPM_SCL;
492
493 VIAPM_OUTB(GPIO_VAL, val);
494
495 return;
496 }
497
498 static void
499 viabb_setsda(device_t dev, int data)
500 {
501 struct viapm_softc *viapm = device_get_softc(dev);
502 u_char val;
503
504 val = VIAPM_INB(GPIO_VAL);
505
506 if (data)
507 val |= VIAPM_SDA;
508 else
509 val &= ~VIAPM_SDA;
510
511 VIAPM_OUTB(GPIO_VAL, val);
512
513 return;
514 }
515
516 static int
517 viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
518 {
519 /* reset bus */
520 viabb_setsda(dev, 1);
521 viabb_setscl(dev, 1);
522
523 return (IIC_ENOADDR);
524 }
525
526 static int
527 viabb_getscl(device_t dev)
528 {
529 struct viapm_softc *viapm = device_get_softc(dev);
530
531 return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
532 }
533
534 static int
535 viabb_getsda(device_t dev)
536 {
537 struct viapm_softc *viapm = device_get_softc(dev);
538
539 return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
540 }
541
542 static int
543 viapm_abort(struct viapm_softc *viapm)
544 {
545 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
546 DELAY(10);
547
548 return (0);
549 }
550
551 static int
552 viapm_clear(struct viapm_softc *viapm)
553 {
554 VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
555 SMBHST_ERROR | SMBHST_INTR);
556 DELAY(10);
557
558 return (0);
559 }
560
561 static int
562 viapm_busy(struct viapm_softc *viapm)
563 {
564 u_char sts;
565
566 sts = VIAPM_INB(SMBHST);
567
568 VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
569
570 return (sts & SMBHST_BUSY);
571 }
572
573 /*
574 * Poll the SMBus controller
575 */
576 static int
577 viapm_wait(struct viapm_softc *viapm)
578 {
579 int count = 10000;
580 u_char sts = 0;
581 int error;
582
583 /* wait for command to complete and SMBus controller is idle */
584 while(count--) {
585 DELAY(10);
586 sts = VIAPM_INB(SMBHST);
587
588 /* check if the controller is processing a command */
589 if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
590 break;
591 }
592
593 VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
594
595 error = SMB_ENOERR;
596
597 if (!count)
598 error |= SMB_ETIMEOUT;
599
600 if (sts & SMBHST_FAILED)
601 error |= SMB_EABORT;
602
603 if (sts & SMBHST_COLLID)
604 error |= SMB_ENOACK;
605
606 if (sts & SMBHST_ERROR)
607 error |= SMB_EBUSERR;
608
609 if (error != SMB_ENOERR)
610 viapm_abort(viapm);
611
612 viapm_clear(viapm);
613
614 return (error);
615 }
616
617 static int
618 viasmb_callback(device_t dev, int index, caddr_t *data)
619 {
620 int error = 0;
621
622 switch (index) {
623 case SMB_REQUEST_BUS:
624 case SMB_RELEASE_BUS:
625 /* ok, bus allocation accepted */
626 break;
627 default:
628 error = EINVAL;
629 }
630
631 return (error);
632 }
633
634 static int
635 viasmb_quick(device_t dev, u_char slave, int how)
636 {
637 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
638 int error;
639
640 viapm_clear(viapm);
641 if (viapm_busy(viapm))
642 return (SMB_EBUSY);
643
644 switch (how) {
645 case SMB_QWRITE:
646 VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
647 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
648 break;
649 case SMB_QREAD:
650 VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
651 VIAPM_OUTB(SMBHADDR, slave | LSB);
652 break;
653 default:
654 panic("%s: unknown QUICK command (%x)!", __func__, how);
655 }
656
657 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
658
659 error = viapm_wait(viapm);
660
661 return (error);
662 }
663
664 static int
665 viasmb_sendb(device_t dev, u_char slave, char byte)
666 {
667 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
668 int error;
669
670 viapm_clear(viapm);
671 if (viapm_busy(viapm))
672 return (SMB_EBUSY);
673
674 VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
675 VIAPM_OUTB(SMBHCMD, byte);
676
677 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
678
679 error = viapm_wait(viapm);
680
681 VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
682
683 return (error);
684 }
685
686 static int
687 viasmb_recvb(device_t dev, u_char slave, char *byte)
688 {
689 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
690 int error;
691
692 viapm_clear(viapm);
693 if (viapm_busy(viapm))
694 return (SMB_EBUSY);
695
696 VIAPM_OUTB(SMBHADDR, slave | LSB);
697
698 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
699
700 if ((error = viapm_wait(viapm)) == SMB_ENOERR)
701 *byte = VIAPM_INB(SMBHDATA0);
702
703 VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
704
705 return (error);
706 }
707
708 static int
709 viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
710 {
711 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
712 int error;
713
714 viapm_clear(viapm);
715 if (viapm_busy(viapm))
716 return (SMB_EBUSY);
717
718 VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
719 VIAPM_OUTB(SMBHCMD, cmd);
720 VIAPM_OUTB(SMBHDATA0, byte);
721
722 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
723
724 error = viapm_wait(viapm);
725
726 VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
727
728 return (error);
729 }
730
731 static int
732 viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
733 {
734 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
735 int error;
736
737 viapm_clear(viapm);
738 if (viapm_busy(viapm))
739 return (SMB_EBUSY);
740
741 VIAPM_OUTB(SMBHADDR, slave | LSB);
742 VIAPM_OUTB(SMBHCMD, cmd);
743
744 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
745
746 if ((error = viapm_wait(viapm)) == SMB_ENOERR)
747 *byte = VIAPM_INB(SMBHDATA0);
748
749 VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
750
751 return (error);
752 }
753
754 static int
755 viasmb_writew(device_t dev, u_char slave, char cmd, short word)
756 {
757 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
758 int error;
759
760 viapm_clear(viapm);
761 if (viapm_busy(viapm))
762 return (SMB_EBUSY);
763
764 VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
765 VIAPM_OUTB(SMBHCMD, cmd);
766 VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
767 VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
768
769 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
770
771 error = viapm_wait(viapm);
772
773 VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
774
775 return (error);
776 }
777
778 static int
779 viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
780 {
781 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
782 int error;
783 u_char high, low;
784
785 viapm_clear(viapm);
786 if (viapm_busy(viapm))
787 return (SMB_EBUSY);
788
789 VIAPM_OUTB(SMBHADDR, slave | LSB);
790 VIAPM_OUTB(SMBHCMD, cmd);
791
792 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
793
794 if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
795 low = VIAPM_INB(SMBHDATA0);
796 high = VIAPM_INB(SMBHDATA1);
797
798 *word = ((high & 0xff) << 8) | (low & 0xff);
799 }
800
801 VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
802
803 return (error);
804 }
805
806 static int
807 viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
808 {
809 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
810 u_char i;
811 int error;
812
813 if (count < 1 || count > 32)
814 return (SMB_EINVAL);
815
816 viapm_clear(viapm);
817 if (viapm_busy(viapm))
818 return (SMB_EBUSY);
819
820 VIAPM_OUTB(SMBHADDR, slave & ~LSB);
821 VIAPM_OUTB(SMBHCMD, cmd);
822 VIAPM_OUTB(SMBHDATA0, count);
823 i = VIAPM_INB(SMBHCTRL);
824
825 /* fill the 32-byte internal buffer */
826 for (i = 0; i < count; i++) {
827 VIAPM_OUTB(SMBHBLOCK, buf[i]);
828 DELAY(2);
829 }
830 VIAPM_OUTB(SMBHCMD, cmd);
831 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
832
833 error = viapm_wait(viapm);
834
835 VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
836
837 return (error);
838
839 }
840
841 static int
842 viasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
843 {
844 struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
845 u_char data, len, i;
846 int error;
847
848 if (*count < 1 || *count > 32)
849 return (SMB_EINVAL);
850
851 viapm_clear(viapm);
852 if (viapm_busy(viapm))
853 return (SMB_EBUSY);
854
855 VIAPM_OUTB(SMBHADDR, slave | LSB);
856 VIAPM_OUTB(SMBHCMD, cmd);
857 VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
858
859 if ((error = viapm_wait(viapm)) != SMB_ENOERR)
860 goto error;
861
862 len = VIAPM_INB(SMBHDATA0);
863 i = VIAPM_INB(SMBHCTRL); /* reset counter */
864
865 /* read the 32-byte internal buffer */
866 for (i = 0; i < len; i++) {
867 data = VIAPM_INB(SMBHBLOCK);
868 if (i < *count)
869 buf[i] = data;
870 DELAY(2);
871 }
872 *count = len;
873
874 error:
875 VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
876
877 return (error);
878 }
879
880 static device_method_t viapm_methods[] = {
881 /* device interface */
882 DEVMETHOD(device_probe, viapm_586b_probe),
883 DEVMETHOD(device_attach, viapm_586b_attach),
884 DEVMETHOD(device_detach, viapm_586b_detach),
885
886 /* iicbb interface */
887 DEVMETHOD(iicbb_callback, viabb_callback),
888 DEVMETHOD(iicbb_setscl, viabb_setscl),
889 DEVMETHOD(iicbb_setsda, viabb_setsda),
890 DEVMETHOD(iicbb_getscl, viabb_getscl),
891 DEVMETHOD(iicbb_getsda, viabb_getsda),
892 DEVMETHOD(iicbb_reset, viabb_reset),
893
894 /* Bus interface */
895 DEVMETHOD(bus_print_child, bus_generic_print_child),
896 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
897 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
898 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
899 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
900 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
901 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
902
903 { 0, 0 }
904 };
905
906 static driver_t viapm_driver = {
907 "viapm",
908 viapm_methods,
909 sizeof(struct viapm_softc),
910 };
911
912 static device_method_t viapropm_methods[] = {
913 /* device interface */
914 DEVMETHOD(device_probe, viapm_pro_probe),
915 DEVMETHOD(device_attach, viapm_pro_attach),
916 DEVMETHOD(device_detach, viapm_pro_detach),
917
918 /* smbus interface */
919 DEVMETHOD(smbus_callback, viasmb_callback),
920 DEVMETHOD(smbus_quick, viasmb_quick),
921 DEVMETHOD(smbus_sendb, viasmb_sendb),
922 DEVMETHOD(smbus_recvb, viasmb_recvb),
923 DEVMETHOD(smbus_writeb, viasmb_writeb),
924 DEVMETHOD(smbus_readb, viasmb_readb),
925 DEVMETHOD(smbus_writew, viasmb_writew),
926 DEVMETHOD(smbus_readw, viasmb_readw),
927 DEVMETHOD(smbus_bwrite, viasmb_bwrite),
928 DEVMETHOD(smbus_bread, viasmb_bread),
929
930 /* Bus interface */
931 DEVMETHOD(bus_print_child, bus_generic_print_child),
932 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
933 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
934 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
935 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
936 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
937 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
938
939 { 0, 0 }
940 };
941
942 static driver_t viapropm_driver = {
943 "viapropm",
944 viapropm_methods,
945 sizeof(struct viapm_softc),
946 };
947
948 DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
949 DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
950 DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
951
952 MODULE_DEPEND(viapm, pci, 1, 1, 1);
953 MODULE_DEPEND(viapropm, pci, 1, 1, 1);
954 MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
955 MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
956 MODULE_VERSION(viapm, 1);
957
958 #ifdef DEV_ISA
959 DRIVER_MODULE(isa, viapm, isa_driver, isa_devclass, 0, 0);
960 DRIVER_MODULE(isa, viapropm, isa_driver, isa_devclass, 0, 0);
961 MODULE_DEPEND(viapm, isa, 1, 1, 1);
962 MODULE_DEPEND(viapropm, isa, 1, 1, 1);
963 #endif
Cache object: 4279b0d8b7590b368e876815244debed
|