Thu Oct 2 00:47:51 2008 UTC ()
Add new driver for dbCool(tm) family of Thermal Monitor and Fan Controller.
Supported chips: ADM1027, ADM1030, ADT7463, ADT7466, ADT7467, ADT7468,
ADT7473, ADT7475, and ADT7476. Notably missing is the ADT7490, and fan
controller support on the ADT7466 is still on the to-do list.
Tested by myself and njoly@
Reviewed by garbled@
Commit approved by christos@, bouyer@, cube@, and matt@
(pgoyette)
diff -r1.475 -r1.476 src/share/man/man4/Makefile
diff -r0 -r1.1 src/share/man/man4/dbcool.4
diff -r0 -r1.1 src/sys/dev/i2c/dbcool.c
diff -r0 -r1.1 src/sys/dev/i2c/dbcool_reg.h
diff -r0 -r1.1 src/sys/dev/i2c/dbcool_var.h
diff -r1.18 -r1.19 src/sys/dev/i2c/files.i2c
--- src/share/man/man4/Makefile 2008/09/30 16:48:39 1.475
+++ src/share/man/man4/Makefile 2008/10/02 00:47:51 1.476
| @@ -1,195 +1,205 @@ | | | @@ -1,195 +1,205 @@ |
1 | # $NetBSD: Makefile,v 1.475 2008/09/30 16:48:39 jmcneill Exp $ | | 1 | # $NetBSD: Makefile,v 1.476 2008/10/02 00:47:51 pgoyette Exp $ |
2 | # @(#)Makefile 8.1 (Berkeley) 6/18/93 | | 2 | # @(#)Makefile 8.1 (Berkeley) 6/18/93 |
3 | | | 3 | |
4 | MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \ | | 4 | MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \ |
5 | adbbt.4 adbkbd.4 adbms.4 \ | | 5 | adbbt.4 adbkbd.4 adbms.4 \ |
6 | adc.4 adt7467c.4 adv.4 adw.4 agp.4 agr.4 ahb.4 ahc.4 ahcisata.4 ahd.4 \ | | 6 | adc.4 adt7467c.4 adv.4 adw.4 agp.4 agr.4 ahb.4 ahc.4 ahcisata.4 ahd.4 \ |
7 | aiboost.4 amdpm.4 amdtemp.4 amhphy.4 amr.4 aps.4 \ | | 7 | aiboost.4 amdpm.4 amdtemp.4 amhphy.4 amr.4 aps.4 \ |
8 | an.4 arcmsr.4 aria.4 artsata.4 ata.4 atalk.4 ataraid.4 \ | | 8 | an.4 arcmsr.4 aria.4 artsata.4 ata.4 atalk.4 ataraid.4 \ |
9 | ath.4 atppc.4 attimer.4 atw.4 \ | | 9 | ath.4 atppc.4 attimer.4 atw.4 \ |
10 | auacer.4 audio.4 audiocs.4 auich.4 \ | | 10 | auacer.4 audio.4 audiocs.4 auich.4 \ |
11 | auixp.4 autri.4 auvia.4 awi.4 azalia.4 \ | | 11 | auixp.4 autri.4 auvia.4 awi.4 azalia.4 \ |
12 | battery_pmu.4 bba.4 bce.4 bcsp.4 be.4 bge.4 bnx.4 bha.4 \ | | 12 | battery_pmu.4 bba.4 bce.4 bcsp.4 be.4 bge.4 bnx.4 bha.4 \ |
13 | bio.4 bktr.4 bluetooth.4 bmtphy.4 bpf.4 \ | | 13 | bio.4 bktr.4 bluetooth.4 bmtphy.4 bpf.4 \ |
14 | brgphy.4 bridge.4 bthidev.4 bthub.4 btkbd.4 btms.4 btsco.4 btuart.4 \ | | 14 | brgphy.4 bridge.4 bthidev.4 bthub.4 btkbd.4 btms.4 btsco.4 btuart.4 \ |
15 | cac.4 cardbus.4 carp.4 ccd.4 cd.4 \ | | 15 | cac.4 cardbus.4 carp.4 ccd.4 cd.4 \ |
16 | cec.4 cgd.4 cfb.4 ch.4 chipsfb.4 ciphy.4 ciss.4 clcs.4 clct.4 clnp.4 \ | | 16 | cec.4 cgd.4 cfb.4 ch.4 chipsfb.4 ciphy.4 ciss.4 clcs.4 clct.4 clnp.4 \ |
17 | clockctl.4 cltp.4 cmdide.4 cmpci.4 cms.4 cnw.4 \ | | 17 | clockctl.4 cltp.4 cmdide.4 cmpci.4 cms.4 cnw.4 \ |
18 | com.4 coretemp.4 crypto.4 cs80bus.4 cuda.4 cypide.4 \ | | 18 | com.4 coretemp.4 crypto.4 cs80bus.4 cuda.4 cypide.4 \ |
19 | ddb.4 ddc.4 de.4 dge.4 dk.4 dmoverio.4 \ | | 19 | ddb.4 ddc.4 de.4 dge.4 dk.4 dmoverio.4 \ |
20 | dmphy.4 dpt.4 dpti.4 drm.4 drum.4 \ | | 20 | dmphy.4 dpt.4 dpti.4 drm.4 drum.4 \ |
21 | eap.4 ebus.4 edc.4 elmc.4 emuxki.4 en.4 envsys.4 ep.4 esh.4 esis.4 \ | | 21 | eap.4 ebus.4 edc.4 elmc.4 emuxki.4 en.4 envsys.4 ep.4 esh.4 esis.4 \ |
22 | esa.4 esiop.4 esm.4 eso.4 etherip.4 exphy.4 \ | | 22 | esa.4 esiop.4 esm.4 eso.4 etherip.4 exphy.4 \ |
23 | fast_ipsec.4 fd.4 finsio.4 fpa.4 fms.4 fss.4 fxp.4 \ | | 23 | fast_ipsec.4 fd.4 finsio.4 fpa.4 fms.4 fss.4 fxp.4 \ |
24 | gem.4 genfb.4 gentbi.4 geodeide.4 \ | | 24 | gem.4 genfb.4 gentbi.4 geodeide.4 \ |
25 | glxtphy.4 gpib.4 gpio.4 gre.4 gphyter.4 gsip.4 hifn.4 hme.4 \ | | 25 | glxtphy.4 gpib.4 gpio.4 gre.4 gphyter.4 gsip.4 hifn.4 hme.4 \ |
26 | hpqlb.4 hptide.4 \ | | 26 | hpqlb.4 hptide.4 \ |
27 | ichlpcib.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \ | | 27 | ichlpcib.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \ |
28 | ifmedia.4 igsfb.4 iha.4 inet.4 ikphy.4 inphy.4 intersil7170.4 \ | | 28 | ifmedia.4 igsfb.4 iha.4 inet.4 ikphy.4 inphy.4 intersil7170.4 \ |
29 | ioasic.4 ioat.4 iop.4 iophy.4 iopsp.4 ip.4 ipkdb.4 ipmi.4 ipw.4 \ | | 29 | ioasic.4 ioat.4 iop.4 iophy.4 iopsp.4 ip.4 ipkdb.4 ipmi.4 ipw.4 \ |
30 | iso.4 isp.4 isv.4 itesio.4 iteide.4 iwi.4 iwn.4 ixpide.4 \ | | 30 | iso.4 isp.4 isv.4 itesio.4 iteide.4 iwi.4 iwn.4 ixpide.4 \ |
31 | jmide.4 joy.4 \ | | 31 | jmide.4 joy.4 \ |
32 | kloader.4 kse.4 ksyms.4 kttcp.4 \ | | 32 | kloader.4 kse.4 ksyms.4 kttcp.4 \ |
33 | lc.4 ld.4 lii.4 lkm.4 lo.4 lxtphy.4 \ | | 33 | lc.4 ld.4 lii.4 lkm.4 lo.4 lxtphy.4 \ |
34 | mainbus.4 makphy.4 mbe.4 mca.4 mcclock.4 md.4 mfb.4 mfi.4 mhzc.4 \ | | 34 | mainbus.4 makphy.4 mbe.4 mca.4 mcclock.4 md.4 mfb.4 mfi.4 mhzc.4 \ |
35 | midi.4 mii.4 mk48txx.4 mlx.4 mly.4 mpt.4 mpu.4 mtd.4 mtio.4 \ | | 35 | midi.4 mii.4 mk48txx.4 mlx.4 mly.4 mpt.4 mpu.4 mtd.4 mtio.4 \ |
36 | multicast.4 \ | | 36 | multicast.4 \ |
37 | nadb.4 ne.4 neo.4 netintro.4 nfe.4 nfsmb.4 njata.4 njs.4 \ | | 37 | nadb.4 ne.4 neo.4 netintro.4 nfe.4 nfsmb.4 njata.4 njs.4 \ |
38 | nsclpcsio.4 nsphy.4 nsphyter.4 ntwoc.4 null.4 nsmb.4 \ | | 38 | nsclpcsio.4 nsphy.4 nsphyter.4 ntwoc.4 null.4 nsmb.4 \ |
39 | oak.4 oosiop.4 opl.4 options.4 optiide.4 osiop.4 \ | | 39 | oak.4 oosiop.4 opl.4 options.4 optiide.4 osiop.4 \ |
40 | pad.4 pas.4 pcdisplay.4 pciide.4 pckbc.4 pckbd.4 pcn.4 pcppi.4 \ | | 40 | pad.4 pas.4 pcdisplay.4 pciide.4 pckbc.4 pckbd.4 pcn.4 pcppi.4 \ |
41 | pcscp.4 pcweasel.4 pdcide.4 pdcsata.4 piixide.4 piixpcib.4 piixpm.4 \ | | 41 | pcscp.4 pcweasel.4 pdcide.4 pdcsata.4 piixide.4 piixpcib.4 piixpm.4 \ |
42 | pim.4 plip.4 pms.4 pmu.4 pnaphy.4 ppbus.4 ppp.4 pppoe.4 pseye.4 \ | | 42 | pim.4 plip.4 pms.4 pmu.4 pnaphy.4 ppbus.4 ppp.4 pppoe.4 pseye.4 \ |
43 | ptm.4 pty.4 puc.4 pud.4 puffs.4 px.4 pxg.4 \ | | 43 | ptm.4 pty.4 puc.4 pud.4 puffs.4 px.4 pxg.4 \ |
44 | qe.4 qec.4 qsphy.4 \ | | 44 | qe.4 qec.4 qsphy.4 \ |
45 | raid.4 ral.4 ray.4 rcons.4 re.4 rgephy.4 rlphy.4 rnd.4 route.4 \ | | 45 | raid.4 ral.4 ray.4 rcons.4 re.4 rgephy.4 rlphy.4 rnd.4 route.4 \ |
46 | rs5c372rtc.4 rtk.4 rtw.4 rum.4 \ | | 46 | rs5c372rtc.4 rtk.4 rtw.4 rum.4 \ |
47 | satalink.4 sbus.4 scc.4 scsi.4 sd.4 se.4 seeprom.4 sem.4 \ | | 47 | satalink.4 sbus.4 scc.4 scsi.4 sd.4 se.4 seeprom.4 sem.4 \ |
48 | ses.4 sf.4 sfb.4 sgsmix.4 shb.4 \ | | 48 | ses.4 sf.4 sfb.4 sgsmix.4 shb.4 \ |
49 | shpcic.4 siisata.4 siop.4 sip.4 siside.4 sk.4 sl.4 slide.4 \ | | 49 | shpcic.4 siisata.4 siop.4 sip.4 siside.4 sk.4 sl.4 slide.4 \ |
50 | sm.4 sn.4 sony.4 spc.4 speaker.4 spif.4 sqphy.4 ss.4 \ | | 50 | sm.4 sn.4 sony.4 spc.4 speaker.4 spif.4 sqphy.4 ss.4 \ |
51 | st.4 ste.4 stge.4 sti.4 stpcide.4 sv.4 strip.4 \ | | 51 | st.4 ste.4 stge.4 sti.4 stpcide.4 sv.4 strip.4 \ |
52 | svwsata.4 swwdog.4 \ | | 52 | svwsata.4 swwdog.4 \ |
53 | tap.4 tc.4 tcds.4 tcp.4 termios.4 tfb.4 ti.4 tl.4 tlp.4 tlphy.4 \ | | 53 | tap.4 tc.4 tcds.4 tcp.4 termios.4 tfb.4 ti.4 tl.4 tlp.4 tlphy.4 \ |
54 | tp.4 tr.4 tra.4 trm.4 tty.4 tun.4 tqphy.4 twa.4 twe.4 txp.4 \ | | 54 | tp.4 tr.4 tra.4 trm.4 tty.4 tun.4 tqphy.4 twa.4 twe.4 txp.4 \ |
55 | ubsec.4 udp.4 uep.4 ug.4 uha.4 uk.4 ukphy.4 unix.4 userconf.4 \ | | 55 | ubsec.4 udp.4 uep.4 ug.4 uha.4 uk.4 ukphy.4 unix.4 userconf.4 \ |
56 | veriexec.4 vga.4 vge.4 viaide.4 video.4 vlan.4 vmmon.4 vmnet.4 \ | | 56 | veriexec.4 vga.4 vge.4 viaide.4 video.4 vlan.4 vmmon.4 vmnet.4 \ |
57 | vnd.4 vr.4 \ | | 57 | vnd.4 vr.4 \ |
58 | wapbl.4 wd.4 wdc.4 wi.4 wm.4 wpi.4 wscons.4 wsdisplay.4 wsfont.4 \ | | 58 | wapbl.4 wd.4 wdc.4 wi.4 wm.4 wpi.4 wscons.4 wsdisplay.4 wsfont.4 \ |
59 | wskbd.4 wsmouse.4 wsmux.4 \ | | 59 | wskbd.4 wsmouse.4 wsmux.4 \ |
60 | xbox.4 xge.4 \ | | 60 | xbox.4 xge.4 \ |
61 | yds.4 ym.4 \ | | 61 | yds.4 ym.4 \ |
62 | zero.4 zstty.4 zyd.4 | | 62 | zero.4 zstty.4 zyd.4 |
63 | | | 63 | |
64 | # USB devices | | 64 | # USB devices |
65 | MAN+= stuirda.4 uaudio.4 uberry.4 ubsa.4 ubt.4 uchcom.4 ucom.4 ucycom.4 \ | | 65 | MAN+= stuirda.4 uaudio.4 uberry.4 ubsa.4 ubt.4 uchcom.4 ucom.4 ucycom.4 \ |
66 | udsbr.4 uftdi.4 ugen.4 ugensa.4 uhid.4 \ | | 66 | udsbr.4 uftdi.4 ugen.4 ugensa.4 uhid.4 \ |
67 | uhidev.4 uhmodem.4 uipaq.4 uirda.4 ukbd.4 ukyopon.4 ulpt.4 \ | | 67 | uhidev.4 uhmodem.4 uipaq.4 uirda.4 ukbd.4 ukyopon.4 ulpt.4 \ |
68 | umass.4 umct.4 umidi.4 umodem.4 ums.4 uplcom.4 urio.4 usb.4 \ | | 68 | umass.4 umct.4 umidi.4 umodem.4 ums.4 uplcom.4 urio.4 usb.4 \ |
69 | uscanner.4 uslsa.4 usscanner.4 ustir.4 uvisor.4 uvscom.4 uyap.4 \ | | 69 | uscanner.4 uslsa.4 usscanner.4 ustir.4 uvisor.4 uvscom.4 uyap.4 \ |
70 | aue.4 atu.4 axe.4 cdce.4 cue.4 kue.4 upl.4 url.4 udav.4 \ | | 70 | aue.4 atu.4 axe.4 cdce.4 cue.4 kue.4 upl.4 url.4 udav.4 \ |
71 | ehci.4 ohci.4 slhci.4 uhci.4 utoppy.4 uvideo.4 | | 71 | ehci.4 ohci.4 slhci.4 uhci.4 utoppy.4 uvideo.4 |
72 | | | 72 | |
73 | # Ir devices | | 73 | # Ir devices |
74 | MAN+= irframe.4 cir.4 irframetty.4 oboe.4 | | 74 | MAN+= irframe.4 cir.4 irframetty.4 oboe.4 |
75 | # smccir.4 | | 75 | # smccir.4 |
76 | | | 76 | |
77 | # ACPI devices | | 77 | # ACPI devices |
78 | MAN+= acpi.4 acpiacad.4 acpibat.4 acpibut.4 acpiec.4 acpilid.4 \ | | 78 | MAN+= acpi.4 acpiacad.4 acpibat.4 acpibut.4 acpiec.4 acpilid.4 \ |
79 | acpitz.4 | | 79 | acpitz.4 |
80 | | | 80 | |
81 | # Radio devices | | 81 | # Radio devices |
82 | MAN+= radio.4 az.4 mr.4 rt.4 rtii.4 sf2r.4 | | 82 | MAN+= radio.4 az.4 mr.4 rt.4 rtii.4 sf2r.4 |
83 | | | 83 | |
84 | # machine-independent busses | | 84 | # machine-independent busses |
85 | MAN+= eisa.4 isa.4 isapnp.4 ofisa.4 pci.4 pcmcia.4 | | 85 | MAN+= eisa.4 isa.4 isapnp.4 ofisa.4 pci.4 pcmcia.4 |
86 | MAN+= podulebus.4 ieee1394if.4 spi.4 | | 86 | MAN+= podulebus.4 ieee1394if.4 spi.4 |
87 | | | 87 | |
88 | # machine-independent PCI devices | | 88 | # machine-independent PCI devices |
89 | MAN+= cz.4 epic.4 lmc.4 viaenv.4 | | 89 | MAN+= cz.4 epic.4 lmc.4 viaenv.4 |
90 | | | 90 | |
91 | # machine-independent ISA devices | | 91 | # machine-independent ISA devices |
92 | MAN+= aha.4 ai.4 aic.4 ast.4 ate.4 boca.4 cs.4 cy.4 ec.4 ef.4 \ | | 92 | MAN+= aha.4 ai.4 aic.4 ast.4 ate.4 boca.4 cs.4 cy.4 ec.4 ef.4 \ |
93 | eg.4 el.4 esp.4 ess.4 ex.4 fmv.4 gus.4 guspnp.4 ix.4 iy.4 \ | | 93 | eg.4 el.4 esp.4 ess.4 ex.4 fmv.4 gus.4 guspnp.4 ix.4 iy.4 \ |
94 | le.4 lm.4 mcd.4 nca.4 rtfps.4 sb.4 sea.4 smsc.4 tcom.4 \ | | 94 | le.4 lm.4 mcd.4 nca.4 rtfps.4 sb.4 sea.4 smsc.4 tcom.4 \ |
95 | wds.4 we.4 wss.4 wt.4 | | 95 | wds.4 we.4 wss.4 wt.4 |
96 | | | 96 | |
97 | # machine-independent PCMCIA devices | | 97 | # machine-independent PCMCIA devices |
98 | MAN+= bt3c.4 btbc.4 pcic.4 tcic.4 pcmcom.4 xi.4 xirc.4 | | 98 | MAN+= bt3c.4 btbc.4 pcic.4 tcic.4 pcmcom.4 xi.4 xirc.4 |
99 | | | 99 | |
100 | # machine-independent obio (mac68k and macppc) devices | | 100 | # machine-independent obio (mac68k and macppc) devices |
101 | MAN+= adb.4 akbd.4 ams.4 mc.4 | | 101 | MAN+= adb.4 akbd.4 ams.4 mc.4 |
102 | | | 102 | |
103 | # machine-independent podulebus devices | | 103 | # machine-independent podulebus devices |
104 | MAN+= dtide.4 ea.4 eb.4 ei.4 hcide.4 sec.4 | | 104 | MAN+= dtide.4 ea.4 eb.4 ei.4 hcide.4 sec.4 |
105 | | | 105 | |
106 | # machine-independent VME devices | | 106 | # machine-independent VME devices |
107 | MAN+= sc.4 si.4 | | 107 | MAN+= sc.4 si.4 |
108 | | | 108 | |
109 | # machine-independent IEEE1394 devices | | 109 | # machine-independent IEEE1394 devices |
110 | MAN+= fwohci.4 fwip.4 sbp.4 | | 110 | MAN+= fwohci.4 fwip.4 sbp.4 |
111 | | | 111 | |
112 | # machine-independent I2C devices | | 112 | # machine-independent I2C devices |
113 | MAN+= lmtemp.4 spdmem.4 | | 113 | MAN+= dbcool.4 lmtemp.4 sdtemp.4 spdmem.4 |
114 | | | 114 | |
115 | # machine-independent SPI devices | | 115 | # machine-independent SPI devices |
116 | MAN += m25p.4 tm121temp.4 | | 116 | MAN += m25p.4 tm121temp.4 |
117 | | | 117 | |
118 | # IPv6/IPsec | | 118 | # IPv6/IPsec |
119 | MAN+= faith.4 gif.4 inet6.4 icmp6.4 ip6.4 ipsec.4 stf.4 | | 119 | MAN+= faith.4 gif.4 inet6.4 icmp6.4 ip6.4 ipsec.4 stf.4 |
120 | | | 120 | |
121 | # ISDN devices | | 121 | # ISDN devices |
122 | MAN+= daic.4 isdntrc.4 isdntel.4 isdnbchan.4 ippp.4 irip.4 isdnctl.4 isdn.4 \ | | 122 | MAN+= daic.4 isdntrc.4 isdntel.4 isdnbchan.4 ippp.4 irip.4 isdnctl.4 isdn.4 \ |
123 | ifpci.4 isic.4 iwic.4 isdncapi.4 iavc.4 | | 123 | ifpci.4 isic.4 iwic.4 isdncapi.4 iavc.4 |
124 | | | 124 | |
125 | # onewire bus and devices | | 125 | # onewire bus and devices |
126 | MAN+= gpioow.4 onewire.4 owtemp.4 | | 126 | MAN+= gpioow.4 onewire.4 owtemp.4 |
127 | | | 127 | |
128 | # DRM devices | | 128 | # DRM devices |
129 | MLINKS+=drm.4 i915drm.4 | | 129 | MLINKS+=drm.4 i915drm.4 |
130 | MLINKS+=drm.4 mach64drm.4 | | 130 | MLINKS+=drm.4 mach64drm.4 |
131 | MLINKS+=drm.4 mgadrm.4 | | 131 | MLINKS+=drm.4 mgadrm.4 |
132 | MLINKS+=drm.4 r128drm.4 | | 132 | MLINKS+=drm.4 r128drm.4 |
133 | MLINKS+=drm.4 radeondrm.4 | | 133 | MLINKS+=drm.4 radeondrm.4 |
134 | MLINKS+=drm.4 savagedrm.4 | | 134 | MLINKS+=drm.4 savagedrm.4 |
135 | MLINKS+=drm.4 sisdrm.4 | | 135 | MLINKS+=drm.4 sisdrm.4 |
136 | MLINKS+=drm.4 tdfxdrm.4 | | 136 | MLINKS+=drm.4 tdfxdrm.4 |
137 | MLINKS+=drm.4 viadrm.4 | | 137 | MLINKS+=drm.4 viadrm.4 |
138 | | | 138 | |
139 | MLINKS+=ata.4 atabus.4 | | 139 | MLINKS+=ata.4 atabus.4 |
140 | MLINKS+=audio.4 audioctl.4 | | 140 | MLINKS+=audio.4 audioctl.4 |
141 | MLINKS+=audio.4 mixer.4 | | 141 | MLINKS+=audio.4 mixer.4 |
142 | MLINKS+=audio.4 sound.4 | | 142 | MLINKS+=audio.4 sound.4 |
143 | MLINKS+=bha.4 bt.4 | | 143 | MLINKS+=bha.4 bt.4 |
144 | MLINKS+=bktr.4 tuner.4 | | 144 | MLINKS+=bktr.4 tuner.4 |
145 | MLINKS+=bktr.4 vbi.4 | | 145 | MLINKS+=bktr.4 vbi.4 |
146 | MLINKS+=cardbus.4 cardslot.4 | | 146 | MLINKS+=cardbus.4 cardslot.4 |
147 | MLINKS+=cardbus.4 cbb.4 | | 147 | MLINKS+=cardbus.4 cbb.4 |
148 | MLINKS+=crypto.4 swcrypto.4 | | 148 | MLINKS+=crypto.4 swcrypto.4 |
| | | 149 | MLINKS+=dbcool.4 dbCool.4 |
| | | 150 | MLINKS+=dbcool.4 adm1027.4 |
| | | 151 | MLINKS+=dbcool.4 adm1030.4 |
| | | 152 | MLINKS+=dbcool.4 adt7463.4 |
| | | 153 | MLINKS+=dbcool.4 adt7466.4 |
| | | 154 | MLINKS+=dbcool.4 adt7467.4 |
| | | 155 | MLINKS+=dbcool.4 adt7468.4 |
| | | 156 | MLINKS+=dbcool.4 adt7473.4 |
| | | 157 | MLINKS+=dbcool.4 adt7475.4 |
| | | 158 | MLINKS+=dbcool.4 adt7476.4 |
149 | MLINKS+=fd.4 stderr.4 fd.4 stdin.4 fd.4 stdout.4 | | 159 | MLINKS+=fd.4 stderr.4 fd.4 stdin.4 fd.4 stdout.4 |
150 | MLINKS+=fpa.4 fea.4 fpa.4 fta.4 | | 160 | MLINKS+=fpa.4 fea.4 fpa.4 fta.4 |
151 | MLINKS+=icp.4 icpsp.4 | | 161 | MLINKS+=icp.4 icpsp.4 |
152 | MLINKS+=irframe.4 irda.4 | | 162 | MLINKS+=irframe.4 irda.4 |
153 | MLINKS+=le.4 bicc.4 le.4 nele.4 le.4 depca.4 | | 163 | MLINKS+=le.4 bicc.4 le.4 nele.4 le.4 depca.4 |
154 | MLINKS+=midi.4 music.4 | | 164 | MLINKS+=midi.4 music.4 |
155 | MLINKS+=midi.4 rmidi.4 | | 165 | MLINKS+=midi.4 rmidi.4 |
156 | MLINKS+=midi.4 sequencer.4 | | 166 | MLINKS+=midi.4 sequencer.4 |
157 | MLINKS+=mii.4 phy.4 | | 167 | MLINKS+=mii.4 phy.4 |
158 | MLINKS+=netintro.4 networking.4 | | 168 | MLINKS+=netintro.4 networking.4 |
159 | MLINKS+=nfsmb.4 nfsmbc.4 | | 169 | MLINKS+=nfsmb.4 nfsmbc.4 |
160 | MLINKS+=nsmb.4 netsmb.4 | | 170 | MLINKS+=nsmb.4 netsmb.4 |
161 | MLINKS+=ntwoc.4 ntwo.4 | | 171 | MLINKS+=ntwoc.4 ntwo.4 |
162 | MLINKS+=pci.4 pchb.4 | | 172 | MLINKS+=pci.4 pchb.4 |
163 | MLINKS+=pci.4 ppb.4 | | 173 | MLINKS+=pci.4 ppb.4 |
164 | MLINKS+=pcppi.4 isabeep.4 | | 174 | MLINKS+=pcppi.4 isabeep.4 |
165 | MLINKS+=pcppi.4 sysbeep.4 | | 175 | MLINKS+=pcppi.4 sysbeep.4 |
166 | MLINKS+=pms.4 pmsi.4 | | 176 | MLINKS+=pms.4 pmsi.4 |
167 | MLINKS+=rcons.4 rasterconsole.4 | | 177 | MLINKS+=rcons.4 rasterconsole.4 |
168 | MLINKS+=rnd.4 random.4 | | 178 | MLINKS+=rnd.4 random.4 |
169 | MLINKS+=rnd.4 urandom.4 | | 179 | MLINKS+=rnd.4 urandom.4 |
170 | MLINKS+=scsi.4 atapi.4 | | 180 | MLINKS+=scsi.4 atapi.4 |
171 | MLINKS+=scsi.4 atapibus.4 | | 181 | MLINKS+=scsi.4 atapibus.4 |
172 | MLINKS+=scsi.4 scsibus.4 | | 182 | MLINKS+=scsi.4 scsibus.4 |
173 | MLINKS+=si.4 sw.4 | | 183 | MLINKS+=si.4 sw.4 |
174 | MLINKS+=sk.4 skc.4 sk.4 msk.4 sk.4 mskc.4 | | 184 | MLINKS+=sk.4 skc.4 sk.4 msk.4 sk.4 mskc.4 |
175 | MLINKS+=sl.4 slip.4 | | 185 | MLINKS+=sl.4 slip.4 |
176 | MLINKS+=speaker.4 spkr.4 | | 186 | MLINKS+=speaker.4 spkr.4 |
177 | MLINKS+=tty.4 dty.4 | | 187 | MLINKS+=tty.4 dty.4 |
178 | MLINKS+=url.4 urlphy.4 | | 188 | MLINKS+=url.4 urlphy.4 |
179 | MLINKS+=usb.4 uhub.4 | | 189 | MLINKS+=usb.4 uhub.4 |
180 | MLINKS+=usb.4 usbtask.4 | | 190 | MLINKS+=usb.4 usbtask.4 |
181 | MLINKS+=wsmux.4 wsmuxctl.4 | | 191 | MLINKS+=wsmux.4 wsmuxctl.4 |
182 | MLINKS+=zstty.4 zs.4 zstty.4 zsc.4 | | 192 | MLINKS+=zstty.4 zs.4 zstty.4 zsc.4 |
183 | | | 193 | |
184 | # This is a hack | | 194 | # This is a hack |
185 | MLINKS+=edc.4 i386/ed.4 | | 195 | MLINKS+=edc.4 i386/ed.4 |
186 | | | 196 | |
187 | SUBDIR= man4.acorn26 man4.acorn32 man4.alpha man4.amiga man4.arc man4.atari \ | | 197 | SUBDIR= man4.acorn26 man4.acorn32 man4.alpha man4.amiga man4.arc man4.atari \ |
188 | man4.cobalt man4.dreamcast man4.evbarm man4.evbmips man4.evbppc \ | | 198 | man4.cobalt man4.dreamcast man4.evbarm man4.evbmips man4.evbppc \ |
189 | man4.hp300 man4.hp700 man4.hpcarm man4.hpcmips man4.hpcsh man4.i386 \ | | 199 | man4.hp300 man4.hp700 man4.hpcarm man4.hpcmips man4.hpcsh man4.i386 \ |
190 | man4.mac68k man4.macppc man4.mvme68k man4.pmax man4.prep \ | | 200 | man4.mac68k man4.macppc man4.mvme68k man4.pmax man4.prep \ |
191 | man4.sgimips man4.sparc man4.sparc64 man4.sun2 man4.sun3 man4.vax \ | | 201 | man4.sgimips man4.sparc man4.sparc64 man4.sun2 man4.sun3 man4.vax \ |
192 | man4.x68k | | 202 | man4.x68k |
193 | | | 203 | |
194 | .include <bsd.man.mk> | | 204 | .include <bsd.man.mk> |
195 | .include <bsd.subdir.mk> | | 205 | .include <bsd.subdir.mk> |
.\" $NetBSD: dbcool.4,v 1.1 2008/10/02 00:47:51 pgoyette Exp $
.\"
.\" Copyright (c) 2008 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Paul Goyette.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd September 28, 2008
.Dt dbCool 4
.Os
.Sh NAME
.Nm dbcool ,
.Nm adm1027 ,
.Nm adt7463 ,
.Nm adt7466 ,
.Nm adt7467 ,
.Nm adt7468 ,
.Nm adt7473 ,
.Nm adt7475 ,
.Nm adt7476
.Nd dbCool(tm) family of environmental monitors and fan controllers
.Sh SYNOPSIS
.Cd "dbcool* at ki2c?"
.Cd "dbcool* at iic? addr 0x2e"
.Sh DESCRIPTION
The
.Nm
driver provides support for the
.Tn Analog Devices
dbCool environmental monitor chips to be used with the
.Xr envsys 4
API.
.Pp
These chips support up to twelve sensors. Not all of the following sensors
are supported on all chips.
.Bl -column "Sensor" "Units" "Typical" -offset indent
.It Sy "Sensor" Ta Sy "Units" Ta Sy "Typical Use"
.It Li "l_temp" Ta "uK" Ta "local chip temperature"
.It Li "r1_temp" Ta "uK" Ta "CPU temperature"
.It Li "r2_temp" Ta "uK" Ta "GPU temperature"
.It Li "Vccp" Ta "uV DC" Ta "CPU Vcore"
.It Li "Vcc" Ta "uV DC" Ta "Chip's supply voltage"
.It Li "2.5V" Ta "uV DC" Ta "2.5V supply"
.It Li "5V" Ta "uV DC" Ta "5V supply"
.It Li "12V" Ta "uV DC" Ta "12V supply"
.It Li "AIN1" Ta "uV DC" Ta "Analog In (2.25V ref, ADT7466 only)"
.It Li "AIN2" Ta "uV DC" Ta "Analog In (2.25V ref, ADT7466 only)"
.It Li "fan1" Ta "RPM" Ta "Chassis Fan"
.It Li "fan2" Ta "RPM" Ta "Chassis Fan"
.It Li "fan3" Ta "RPM" Ta "Chassis Fan"
.It Li "fan4" Ta "RPM" Ta "Chassis Fan"
.El
.Pp
Except on the ADT7466, each temperature and voltage sensor has a
programmable high- and low-limit; fan sensors have only a low-limit. The
user can set the threshold values using
.Xr sysctl 8
.Bd -literal -offset indent
hw.dbcool0.l_temp.low_lim = 35 degrees C
hw.dbcool0.l_temp.hi_lim = 75 degrees C
hw.dbcool0.fan1.low_lim = 300 RPM
hw.dbcool0.Vcc.low_lim = 2250 milliVolts
hw.dbcool0.Vcc.hi_lim = 2750 milliVolts
.Ed
.Pp
Temperature sensors also have
.Em Tmin ,
.Em Thyst ,
and
.Em Ttherm
.Xr sysctl 8
variables; these values are used by the fan speed controllers.
.Pp
All
.Xr sysctl 8
variables associated with temperature sensors are in units of degC, since
this is the unit which is programmed into the device registers. Limit
values for voltage sensors are in millivolts. The low limit value for
fan sensors is measured in RPM; due to the manner in which fan speed is
measured, the lowest possible value for a fan limit is 83 RPM.
.Pp
All members of the dbCool family support Pulse-Width Modulated (PWM)
fan speed control based on temperature thresholds - the fan will spin up
when one or more thermal sensors exceeds its configured
.Em Tmin
value. The fan will go faster as the temperature rises, and will slow
down as the temperature falls. If the temperature exceeds the sensor's
.Em Ttherm
value, the THERM signal will be asserted, and if enabled the fan will
run at full speed. The fan will be turned
off when the sensor(s) that triggered it reports a temperature which is
at least
.Em Thyst
degrees below its
.Em Tmin
threshold.
.Pp
Each fan controller is programmable using the following
.Xr sysctl 8
variables.
.Bd -literal -offset indent
hw.dbcool0.fan_ctl_0.behavior
hw.dbcool0.fan_ctl_0.range
hw.dbcool0.fan_ctl_0.min_duty
hw.dbcool0.fan_ctl_0.max_duty
hw.dbcool0.fan_ctl_0.cur_duty
.Ed
(On the ADM1030, the
.Em range
variable is associated with each individual temperature sensor rather
than with the fan controller.)
.Pp
The
.Em behavior
variable controls the selection of temperature sensors associated with
the fan controller. When the associated temperature sensor reaches its
.Em Tmin
value, the fan controller starts the fan at its minimum duty cycle;
when the associated temperature sensor reaches its
.Em Ttherm
value and asserts the THERM signal (or if an external THERM signal is
asserted), the fan controller sets the fan speed to a 100% duty cycle.
Between these two settings, each temperature sensor is used to calculate
a duty cycle linearly based on the slope defined by the temperature sensor's
.Em range
variable. When the associated temperature falls at least
.Em Thyst
degress below its
.Em Tmin
value, the fan controller will turn off the fan. (On the ADM1030, the
value for
.Em Thyst
is fixed at 5 degrees C.)
.Pp
Valid values for the
.Em behavior
variable are:
.Bd -literal -offset indent
local (not available on ADM1030)
remote1
remote2 (not available on ADM1030)
local+remote2 (not available on ADM1030)
all-temps
full-speed (not available on ADM1030)
manual
disabled
.Ed
.Pp
When the
.Em behavior
variable is set to "manual", the
.Em cur-duty
variable becomes user-writeable and can be set to any value between 0 and
100 inclusive to control the fan's duty cycle manually. In all other
.Em behavior
modes, the
.Em cur-duty
variable is read-only and updates are ignored.
.Pp
The
.Em min-duty
and
.Em max-duty
variables define the range over which the fan controller will manage the
fan's duty cycle. On the ADM1030, these values are not separately
controllable. The
.Em max-duty
is fixed at 100%, and the
.Em cur-duty
variable is used to specify the minimum duty cycle when the fan
controller is running in automatic mode.
.Pp
Note that the duty-cycle value does not directly correspond to the fan's
speed. That is, a 33% duty cycle does not mean that the fan runs at 33%
of its maximum speed; in actuality, a 33% duty cycle drives the fan at
a speed close to 50% of its maximum. Fan speed correlates approximately
to the square root of the duty cycle.
.Sh EXAMPLES
The
.Xr envstat 8
utility can be used to determine the sensors supported:
.Bd -literal -offset indent
Current CritMax CritMin CritCap Unit
l_temp: 44.250 degC
r1_temp: 41.250 degC
r2_temp: N/A
Vccp: 0.002 V
Vcc: 3.351 V
fan1: N/A
fan2: N/A
fan3: N/A
fan4: N/A
.Ed
.Pp
Using this information, the following commands in /etc/envsys.conf will
set appropriate limits for CPU temperature and chip supply voltage, and
powerd will be notified if the limits are exceeded:
.Bd -literal -offset indent
dbcool0 {
sensor0 {
warning-max = 60C;
critical-max = 65C;
}
sensor4 {
critical-min = 3.1;
warning-min = 3.2;
critical-max = 3.5;
}
}
.Ed
.Pp
Alternatively, set the following commands in /etc/sysctl.conf to perform
limit checking in the hardware:
.Bd -literal -offset indent
hw.dbcool0.l_temp.hi_lim = 65
hw.dbcool0.Vcc.low_lim = 3200
hw.dbcool0.Vcc.hi_lim = 3500
.Ed
.Sh SEE ALSO
.Xr envsys 4 ,
.Xr envstat 8 ,
.Xr powerd 8 ,
.Xr sysctl 8
.Sh HISTORY
The
.Nm
device appeared in
.Nx 5.0 .
.Sh BUGS
Although the sensor limit registers can be programmed, there is currently
no use of the dbCool chips' ability to generate an SMBus interrupt when the
limits are exceeded. Limit checking is only performed when the sensor
values are polled and refreshed.
.Pp
The ADT7466 chip, although officially a member of the dbCool family, is
programmed quite differently. The fan controllers and sensor limits on
this chip are not currently implemented.
/* $NetBSD: dbcool.c,v 1.1 2008/10/02 00:47:51 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Goyette
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* a driver for the dbCool(tm) family of environmental controllers
*
* Data sheets for the various supported chips are available at
*
* http://www.onsemi.com/pub/Collateral/ADM1027-D.PDF
* http://www.onsemi.com/pub/Collateral/ADM1030-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7463-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7466.PDF
* http://www.onsemi.com/pub/Collateral/ADT7467-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7468-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7473-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7475-D.PDF
* http://www.onsemi.com/pub/Collateral/ADT7476-D.PDF
*
* (URLs are correct as of September 27, 2008)
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dbcool.c,v 1.1 2008/10/02 00:47:51 pgoyette Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
#include <uvm/uvm_extern.h>
#include <dev/i2c/dbcool_var.h>
#include <dev/i2c/dbcool_reg.h>
/* Config interface */
static int dbcool_match(device_t, cfdata_t, void *);
static void dbcool_attach(device_t, device_t, void *);
static int dbcool_detach(device_t, int);
/* Device attributes */
static int dbcool_supply_voltage(struct dbcool_softc *);
static uint8_t dbcool_islocked(struct dbcool_softc *);
/* Sensor read functions */
static void dbcool_refresh(struct sysmon_envsys *, envsys_data_t *);
static int dbcool_read_rpm(struct dbcool_softc *, uint8_t);
static int dbcool_read_temp(struct dbcool_softc *, uint8_t, bool);
static int dbcool_read_volt(struct dbcool_softc *, uint8_t, bool);
/* SYSCTL Helpers */
static uint8_t sysctl_dbcool_chipreg(struct dbcool_softc *, int);
static int sysctl_dbcool_tmin(SYSCTLFN_PROTO);
static int sysctl_adm1030_tmin(SYSCTLFN_PROTO);
static int sysctl_adm1030_trange(SYSCTLFN_PROTO);
static int sysctl_dbcool_duty(SYSCTLFN_PROTO);
static int sysctl_dbcool_behavior(SYSCTLFN_PROTO);
static int sysctl_dbcool_range(SYSCTLFN_PROTO);
static int sysctl_dbcool_volt_limit(SYSCTLFN_PROTO);
static int sysctl_dbcool_temp_limit(SYSCTLFN_PROTO);
static int sysctl_dbcool_fan_limit(SYSCTLFN_PROTO);
static int sysctl_dbcool_thyst(SYSCTLFN_PROTO);
static int sysctl_dbcool_vid(SYSCTLFN_PROTO);
#ifdef DBCOOL_DEBUG
static int sysctl_dbcool_reg_select(SYSCTLFN_PROTO);
static int sysctl_dbcool_reg_access(SYSCTLFN_PROTO);
#endif /* DBCOOL_DEBUG */
/*
* Descriptions for SYSCTL entries
*/
struct dbc_names {
const char *name;
const char *desc;
int (*helper)(SYSCTLFN_PROTO);
};
/*
* The first several entries must remain in the same order as the
* corresponding entries in enum dbc_pwm_params
*/
static struct dbc_names dbc_sysctl_table[] = {
{ "behavior", "operating behavior and temp selector",
sysctl_dbcool_behavior },
{ "range", "fan controller PWM slope or temp range",
sysctl_dbcool_range },
{ "min_duty", "minimum fan controller PWM duty cycle",
sysctl_dbcool_duty },
{ "max_duty", "maximum fan controller PWM duty cycle",
sysctl_dbcool_duty },
{ "cur_duty", "current fan controller PWM duty cycle",
sysctl_dbcool_duty },
{ "Tmin", "temp at which to start fan controller",
sysctl_dbcool_tmin },
{ "Ttherm", "temp at which THERM is asserted",
sysctl_dbcool_tmin },
{ "Thyst", "temp hysteresis for stopping fan controller",
sysctl_dbcool_thyst },
{ "Tmin", "temp at which to start fan controller",
sysctl_adm1030_tmin },
{ "Trange", "temp range to reach 100% duty cycle",
sysctl_adm1030_trange },
};
static const char *dbc_sensor_names[] = {
"l_temp", "r1_temp", "r2_temp", "Vccp", "Vcc",
"fan1", "fan2", "fan3", "fan4", "AIN1",
"AIN2", "2.5V", "5V", "12V"
};
struct dbcool_sensor ADT7475_sensor_table[] = {
{ DBC_TEMP, { DBCOOL_LOCAL_TEMP,
DBCOOL_LOCAL_HIGHLIM,
DBCOOL_LOCAL_LOWLIM }, 0, 0 },
{ DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
DBCOOL_REMOTE1_HIGHLIM,
DBCOOL_REMOTE1_LOWLIM }, 1, 0 },
{ DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
DBCOOL_REMOTE2_HIGHLIM,
DBCOOL_REMOTE2_LOWLIM }, 2, 0 },
{ DBC_VOLT, { DBCOOL_CPU_VOLTAGE,
DBCOOL_VCCP_HIGHLIM,
DBCOOL_VCCP_LOWLIM }, 3, 0 },
{ DBC_VOLT, { DBCOOL_SUPPLY_VOLTAGE,
DBCOOL_VCC_HIGHLIM,
DBCOOL_VCC_LOWLIM }, 4, 0 },
{ DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH1_MIN_LSB }, 5, 0 },
{ DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH2_MIN_LSB }, 6, 0 },
{ DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH3_MIN_LSB }, 7, 0 },
{ DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH4_MIN_LSB }, 8, 0 },
{ DBC_CTL, { DBCOOL_LOCAL_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 5 },
{ DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 6 },
{ DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 7 },
{ DBC_CTL, { DBCOOL_REMOTE1_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 5 },
{ DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 6 },
{ DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 7 },
{ DBC_CTL, { DBCOOL_REMOTE2_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 5 },
{ DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 6 },
{ DBC_CTL, { DBCOOL_R2_TMIN_HYST,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 7 },
{ DBC_EOF, { 0, 0, 0 }, 0, 0 }
};
/*
* The members of dbcool_power_control must be in the same order as
* in enum dbc_pwm_params
*/
struct dbcool_power_control ADT7475_power_table[] = {
{ DBCOOL_PWM1_CTL, DBCOOL_PWM1_TRANGE, DBCOOL_PWM1_MINDUTY,
DBCOOL_PWM1_MAXDUTY, DBCOOL_PWM1_CURDUTY,
"fan_control_1" },
{ DBCOOL_PWM2_CTL, DBCOOL_PWM2_TRANGE, DBCOOL_PWM2_MINDUTY,
DBCOOL_PWM2_MAXDUTY, DBCOOL_PWM2_CURDUTY,
"fan_control_2" },
{ DBCOOL_PWM3_CTL, DBCOOL_PWM3_TRANGE, DBCOOL_PWM3_MINDUTY,
DBCOOL_PWM3_MAXDUTY, DBCOOL_PWM3_CURDUTY,
"fan_control_3" },
{ 0, 0, 0, 0, 0, NULL }
};
struct dbcool_sensor ADT7466_sensor_table[] = {
{ DBC_TEMP, { DBCOOL_ADT7466_LCL_TEMP_MSB,
DBCOOL_ADT7466_LCL_TEMP_HILIM,
DBCOOL_ADT7466_LCL_TEMP_LOLIM }, 0, 0 },
{ DBC_TEMP, { DBCOOL_ADT7466_REM_TEMP_MSB,
DBCOOL_ADT7466_REM_TEMP_HILIM,
DBCOOL_ADT7466_REM_TEMP_LOLIM }, 1, 0 },
{ DBC_VOLT, { DBCOOL_ADT7466_VCC,
DBCOOL_ADT7466_VCC_HILIM,
DBCOOL_ADT7466_VCC_LOLIM }, 4, 0 },
{ DBC_VOLT, { DBCOOL_ADT7466_AIN1,
DBCOOL_ADT7466_AIN1_HILIM,
DBCOOL_ADT7466_AIN1_LOLIM }, 9, 0 },
{ DBC_VOLT, { DBCOOL_ADT7466_AIN2,
DBCOOL_ADT7466_AIN2_HILIM,
DBCOOL_ADT7466_AIN2_LOLIM }, 10, 0 },
{ DBC_FAN, { DBCOOL_ADT7466_FANA_LSB,
DBCOOL_NO_REG,
DBCOOL_ADT7466_FANA_LOLIM_LSB }, 5, 0 },
{ DBC_FAN, { DBCOOL_ADT7466_FANB_LSB,
DBCOOL_NO_REG,
DBCOOL_ADT7466_FANB_LOLIM_LSB }, 6, 0 },
{ DBC_EOF, { 0, 0, 0 }, 0, 0 }
};
struct dbcool_sensor ADM1027_sensor_table[] = {
{ DBC_TEMP, { DBCOOL_LOCAL_TEMP,
DBCOOL_LOCAL_HIGHLIM,
DBCOOL_LOCAL_LOWLIM }, 0, 0 },
{ DBC_TEMP, { DBCOOL_REMOTE1_TEMP,
DBCOOL_REMOTE1_HIGHLIM,
DBCOOL_REMOTE1_LOWLIM }, 1, 0 },
{ DBC_TEMP, { DBCOOL_REMOTE2_TEMP,
DBCOOL_REMOTE2_HIGHLIM,
DBCOOL_REMOTE2_LOWLIM }, 2, 0 },
{ DBC_VOLT, { DBCOOL_CPU_VOLTAGE,
DBCOOL_VCCP_HIGHLIM,
DBCOOL_VCCP_LOWLIM }, 3, 0 },
{ DBC_VOLT, { DBCOOL_SUPPLY_VOLTAGE,
DBCOOL_VCC_HIGHLIM,
DBCOOL_VCC_LOWLIM }, 4, 0 },
{ DBC_VOLT, { DBCOOL_25VIN,
DBCOOL_25VIN_HIGHLIM,
DBCOOL_25VIN_LOWLIM }, 4, 0 },
{ DBC_VOLT, { DBCOOL_5VIN,
DBCOOL_5VIN_HIGHLIM,
DBCOOL_5VIN_LOWLIM }, 4, 0 },
{ DBC_VOLT, { DBCOOL_12VIN,
DBCOOL_12VIN_HIGHLIM,
DBCOOL_12VIN_LOWLIM }, 4, 0 },
{ DBC_FAN, { DBCOOL_FAN1_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH1_MIN_LSB }, 5, 0 },
{ DBC_FAN, { DBCOOL_FAN2_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH2_MIN_LSB }, 6, 0 },
{ DBC_FAN, { DBCOOL_FAN3_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH3_MIN_LSB }, 7, 0 },
{ DBC_FAN, { DBCOOL_FAN4_TACH_LSB,
DBCOOL_NO_REG,
DBCOOL_TACH4_MIN_LSB }, 8, 0 },
{ DBC_CTL, { DBCOOL_LOCAL_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 5 },
{ DBC_CTL, { DBCOOL_LOCAL_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 6 },
{ DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST | 0x80,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 7 },
{ DBC_CTL, { DBCOOL_REMOTE1_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 5 },
{ DBC_CTL, { DBCOOL_REMOTE1_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 6 },
{ DBC_CTL, { DBCOOL_R1_LCL_TMIN_HYST,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 7 },
{ DBC_CTL, { DBCOOL_REMOTE2_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 5 },
{ DBC_CTL, { DBCOOL_REMOTE2_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 6 },
{ DBC_CTL, { DBCOOL_R2_TMIN_HYST,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 2, 7 },
{ DBC_EOF, { 0, 0, 0 }, 0, 0 }
};
struct dbcool_sensor ADM1030_sensor_table[] = {
{ DBC_TEMP, { DBCOOL_ADM1030_L_TEMP,
DBCOOL_ADM1030_L_HI_LIM,
DBCOOL_ADM1030_L_LO_LIM }, 0, 0 },
{ DBC_TEMP, { DBCOOL_ADM1030_R_TEMP,
DBCOOL_ADM1030_R_HI_LIM,
DBCOOL_ADM1030_R_LO_LIM }, 1, 0 },
{ DBC_FAN, { DBCOOL_ADM1030_FAN_TACH,
DBCOOL_NO_REG,
DBCOOL_ADM1030_FAN_LO_LIM }, 5, 0 },
{ DBC_CTL, { DBCOOL_ADM1030_L_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 8 },
{ DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 9 },
{ DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 0, 6 },
{ DBC_CTL, { DBCOOL_ADM1030_R_TMIN,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 8 },
{ DBC_CTL, { DBCOOL_ADM1030_L_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 9 },
{ DBC_CTL, { DBCOOL_ADM1030_R_TTHRESH,
DBCOOL_NO_REG,
DBCOOL_NO_REG }, 1, 6 },
{ DBC_EOF, {0, 0, 0 }, 0, 0 }
};
struct dbcool_power_control ADM1030_power_table[] = {
{ DBCOOL_ADM1030_CFG1, 0, 0, 0, DBCOOL_ADM1030_FAN_SPEED_CFG,
"fan_control_1" },
{ 0, 0, 0, 0, 0, NULL }
};
struct chip_id chip_table[] = {
{ DBCOOL_COMPANYID, ADT7476_DEVICEID, 0xff,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_VID,
90000 * 60, "ADT7476" },
{ DBCOOL_COMPANYID, ADT7475_DEVICEID, 0xff,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
90000 * 60, "ADT7475" },
{ DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_REV_ID,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
90000 * 60, "ADT7463" },
{ DBCOOL_COMPANYID, ADT7473_DEVICEID, ADT7473_1_REV_ID,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_MAXDUTY | DBCFLAG_HAS_SHDN,
90000 * 60, "ADT7463-1" },
{ DBCOOL_COMPANYID, ADT7468_DEVICEID, 0xff,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_MULTI_VCC | DBCFLAG_HAS_MAXDUTY |
DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN | DBCFLAG_HAS_VID,
90000 * 60, "ADT7468" },
{ DBCOOL_COMPANYID, ADT7467_DEVICEID, 0xff,
ADT7475_sensor_table, ADT7475_power_table,
DBCFLAG_TEMPOFFSET | DBCFLAG_MULTI_VCC | DBCFLAG_HAS_MAXDUTY |
DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN,
90000 * 60, "ADT7467" },
{ DBCOOL_COMPANYID, ADT7466_DEVICEID, 0xff,
ADT7466_sensor_table, NULL,
DBCFLAG_ADT7466 | DBCFLAG_TEMPOFFSET | DBCFLAG_HAS_SHDN,
82000 * 60, "ADT7466" },
{ DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID1,
ADM1027_sensor_table, ADT7475_power_table,
DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN |
DBCFLAG_ADM1027 | DBCFLAG_HAS_VID,
90000 * 60, "ADT7463" },
{ DBCOOL_COMPANYID, ADT7463_DEVICEID, ADT7463_REV_ID2,
ADM1027_sensor_table, ADT7475_power_table,
DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER | DBCFLAG_HAS_SHDN |
DBCFLAG_HAS_VID,
90000 * 60, "ADT7463" },
{ DBCOOL_COMPANYID, ADM1027_DEVICEID, ADM1027_REV_ID,
ADM1027_sensor_table, ADT7475_power_table,
DBCFLAG_MULTI_VCC | DBCFLAG_4BIT_VER,
90000 * 60, "ADM1027" },
{ DBCOOL_COMPANYID, ADM1030_DEVICEID, 0xff,
ADM1030_sensor_table, ADM1030_power_table,
DBCFLAG_ADM1030,
11250 * 60, "ADM1030" },
{ 0, 0, 0, NULL, NULL, 0, 0, NULL }
};
static const char *behavior[] = {
"remote1", "local", "remote2", "full-speed",
"disabled", "local+remote2","all-temps", "manual"
};
static char dbcool_cur_behav[16];
CFATTACH_DECL_NEW(dbcool, sizeof(struct dbcool_softc),
dbcool_match, dbcool_attach, dbcool_detach, NULL);
int
dbcool_match(device_t parent, cfdata_t cf, void *aux)
{
struct i2c_attach_args *ia = aux;
struct dbcool_softc sc;
sc.sc_tag = ia->ia_tag;
sc.sc_addr = ia->ia_addr;
/* no probing if we attach to iic, but verify chip id */
if (dbcool_chip_ident(&sc) >= 0)
return 1;
return 0;
}
void
dbcool_attach(device_t parent, device_t self, void *aux)
{
struct dbcool_softc *sc = device_private(self);
struct i2c_attach_args *args = aux;
uint8_t ver;
sc->sc_addr = args->ia_addr;
sc->sc_tag = args->ia_tag;
(void)dbcool_chip_ident(sc);
aprint_naive("\n");
aprint_normal("\n");
ver = dbcool_readreg(sc, DBCOOL_REVISION_REG);
if (sc->sc_chip->flags & DBCFLAG_4BIT_VER)
aprint_normal_dev(self, "%s dBCool(tm) Controller "
"(rev 0x%02x, stepping 0x%02x)\n", sc->sc_chip->name,
ver >> 4, ver & 0x0f);
else
aprint_normal_dev(self, "%s dBCool(tm) Controller "
"(rev 0x%04x)\n", sc->sc_chip->name, ver);
dbcool_setup(self);
if (!pmf_device_register(self, dbcool_pmf_suspend, dbcool_pmf_resume))
aprint_error_dev(self, "couldn't establish power handler\n");
}
static int
dbcool_detach(device_t self, int flags)
{
struct dbcool_softc *sc = device_private(self);
sysmon_envsys_unregister(sc->sc_sme);
sysmon_envsys_destroy(sc->sc_sme);
sc->sc_sme = NULL;
return 0;
}
/* On suspend, we save the state of the SHDN bit, then set it */
bool dbcool_pmf_suspend(device_t dev PMF_FN_ARGS)
{
struct dbcool_softc *sc = device_private(dev);
uint8_t reg, bit, cfg;
if ((sc->sc_chip->flags && DBCFLAG_HAS_SHDN) == 0)
return true;
if (sc->sc_chip->flags && DBCFLAG_ADT7466) {
reg = DBCOOL_ADT7466_CONFIG2;
bit = DBCOOL_ADT7466_CFG2_SHDN;
} else {
reg = DBCOOL_CONFIG2_REG;
bit = DBCOOL_CFG2_SHDN;
}
cfg = dbcool_readreg(sc, reg);
sc->sc_suspend = cfg & bit;
cfg |= bit;
dbcool_writereg(sc, reg, cfg);
return true;
}
/* On resume, we restore the previous state of the SHDN bit */
bool dbcool_pmf_resume(device_t dev PMF_FN_ARGS)
{
struct dbcool_softc *sc = device_private(dev);
uint8_t reg, bit, cfg;
if ((sc->sc_chip->flags && DBCFLAG_HAS_SHDN) == 0)
return true;
if (sc->sc_chip->flags && DBCFLAG_ADT7466) {
reg = DBCOOL_ADT7466_CONFIG2;
bit = DBCOOL_ADT7466_CFG2_SHDN;
} else {
reg = DBCOOL_CONFIG2_REG;
bit = DBCOOL_CFG2_SHDN;
}
cfg = dbcool_readreg(sc, reg);
cfg &= ~sc->sc_suspend;
dbcool_writereg(sc, reg, cfg);
return true;
}
uint8_t
dbcool_readreg(struct dbcool_softc *sc, uint8_t reg)
{
uint8_t data = 0;
if (iic_acquire_bus(sc->sc_tag, 0) != 0)
goto bad;
if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
sc->sc_addr, NULL, 0, ®, 1, 0) != 0)
goto bad;
iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
sc->sc_addr, NULL, 0, &data, 1, 0);
bad:
iic_release_bus(sc->sc_tag, 0);
return data;
}
void
dbcool_writereg(struct dbcool_softc *sc, uint8_t reg, uint8_t val)
{
if (iic_acquire_bus(sc->sc_tag, 0) != 0)
return;
iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
sc->sc_addr, ®, 1, &val, 1, 0);
iic_release_bus(sc->sc_tag, 0);
return;
}
static uint8_t
dbcool_islocked(struct dbcool_softc *sc)
{
uint8_t cfg_reg;
if (sc->sc_chip->flags & DBCFLAG_ADM1030)
return 0;
if (sc->sc_chip->flags & DBCFLAG_ADT7466)
cfg_reg = DBCOOL_ADT7466_CONFIG1;
else
cfg_reg = DBCOOL_CONFIG1_REG;
if (dbcool_readreg(sc, cfg_reg) & DBCOOL_CFG1_LOCK)
return 1;
else
return 0;
}
static int
dbcool_read_temp(struct dbcool_softc *sc, uint8_t reg, bool extres)
{
uint8_t t1, t2, t3, val, ext = 0;
uint8_t offset;
int temp;
offset = sc->sc_temp_offset;
if (sc->sc_chip->flags & DBCFLAG_ADT7466) {
/*
* ADT7466 temps are in strange location
*/
ext = dbcool_readreg(sc, DBCOOL_ADT7466_CONFIG1);
val = dbcool_readreg(sc, reg);
if (extres)
ext = dbcool_readreg(sc, reg + 1);
} else if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
/*
* ADM1030 temps are in their own special place, too
*/
if (extres) {
ext = dbcool_readreg(sc, DBCOOL_ADM1030_TEMP_EXTRES);
if (reg == DBCOOL_ADM1030_L_TEMP)
ext >>= 6;
else
ext >>= 1;
ext &= 0x03;
}
val = dbcool_readreg(sc, reg);
} else {
if (extres) {
ext = dbcool_readreg(sc, DBCOOL_EXTRES2_REG);
/* Read all msb regs to unlatch them */
t1 = dbcool_readreg(sc, DBCOOL_12VIN);
t1 = dbcool_readreg(sc, DBCOOL_REMOTE1_TEMP);
t2 = dbcool_readreg(sc, DBCOOL_REMOTE2_TEMP);
t3 = dbcool_readreg(sc, DBCOOL_LOCAL_TEMP);
switch (reg) {
case DBCOOL_REMOTE1_TEMP:
val = t1;
ext >>= 2;
break;
case DBCOOL_LOCAL_TEMP:
val = t3;
ext >>= 4;
break;
case DBCOOL_REMOTE2_TEMP:
val = t2;
ext >>= 6;
break;
default:
val = 0;
break;
}
ext &= 0x03;
}
else
val = dbcool_readreg(sc, reg);
}
/* Check for invalid temp values */
if ((offset == 0 && val == 0x80) || (offset != 0 && val == 0))
return 0;
/* If using offset mode, adjust, else treat as signed */
if (offset) {
temp = val;
temp -= offset;
} else
temp = (int8_t)val;
/* Convert degC to uK and include extended precision bits */
temp *= 1000000;
temp += 250000 * (int)ext;
temp += 273150000U;
return temp;
}
static int
dbcool_read_rpm(struct dbcool_softc *sc, uint8_t reg)
{
int rpm;
uint8_t rpm_lo, rpm_hi;
rpm_lo = dbcool_readreg(sc, reg);
if (sc->sc_chip->flags & DBCFLAG_ADM1030)
rpm_hi = (rpm_lo == 0xff)?0xff:0x0;
else
rpm_hi = dbcool_readreg(sc, reg + 1);
rpm = (rpm_hi << 8) | rpm_lo;
if (rpm == 0xffff)
return 0; /* 0xffff indicates stalled/failed fan */
return (sc->sc_chip->rpm_dividend / rpm);
}
/* Provide chip's supply voltage, in millivolts */
static int
dbcool_supply_voltage(struct dbcool_softc *sc)
{
if (sc->sc_chip->flags & DBCFLAG_MULTI_VCC) {
if (dbcool_readreg(sc, DBCOOL_CONFIG1_REG) & DBCOOL_CFG1_Vcc)
return 5000;
else
return 3300;
} else if (sc->sc_chip->flags & DBCFLAG_ADT7466) {
if (dbcool_readreg(sc, DBCOOL_ADT7466_CONFIG1) &
DBCOOL_ADT7466_CFG1_Vcc)
return 5000;
else
return 3300;
} else
return 3300;
}
static int
dbcool_read_volt(struct dbcool_softc *sc, uint8_t reg, bool extres)
{
uint8_t ext = 0, v1, v2, v3, v4, val;
int ret, nom;
/* ADT7466 voltages are in strange locations with only 8-bits */
if (sc->sc_chip->flags & DBCFLAG_ADT7466) {
val = dbcool_readreg(sc, reg);
if (reg == DBCOOL_ADT7466_VCC)
nom = 3300;
else
nom = 1687; /* Full-scale is 2.25V */
} else if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
/*
* There are no voltage sensors on the ADM1030
*/
return 0;
} else if (reg == DBCOOL_12VIN || reg == DBCOOL_12VIN_LOWLIM ||
reg == DBCOOL_12VIN_HIGHLIM) {
/* It's a "normal" dbCool chip */
if (extres)
ext = dbcool_readreg(sc, DBCOOL_EXTRES2_REG) && 0x03;
val = dbcool_readreg(sc, reg);
nom = 12000;
/*
* Must read the temps associated with the same extres
* register in order to unlatch it!
*/
if (extres)
(void)dbcool_read_temp(sc, DBCOOL_LOCAL_TEMP, true);
} else {
if (extres) {
ext = dbcool_readreg(sc, DBCOOL_EXTRES1_REG);
v1 = dbcool_readreg(sc, DBCOOL_25VIN);
v2 = dbcool_readreg(sc, DBCOOL_CPU_VOLTAGE);
v3 = dbcool_readreg(sc, DBCOOL_SUPPLY_VOLTAGE);
v4 = dbcool_readreg(sc, DBCOOL_5VIN);
} else
v1 = v2 = v3 = v4 = dbcool_readreg(sc, reg);
switch (reg) {
case DBCOOL_25VIN:
case DBCOOL_25VIN_LOWLIM:
case DBCOOL_25VIN_HIGHLIM:
val = v1;
nom = 2500;
break;
case DBCOOL_CPU_VOLTAGE:
case DBCOOL_VCCP_LOWLIM:
case DBCOOL_VCCP_HIGHLIM:
/* All known chips use a 2.25V reference */
val = v2;
nom = 2250;
ext >>= 2;
break;
case DBCOOL_SUPPLY_VOLTAGE:
case DBCOOL_VCC_LOWLIM:
case DBCOOL_VCC_HIGHLIM:
val = v3;
nom = dbcool_supply_voltage(sc);
ext >>= 4;
break;
case DBCOOL_5VIN:
case DBCOOL_5VIN_LOWLIM:
case DBCOOL_5VIN_HIGHLIM:
val = v4;
nom = 5000;
ext >>= 6;
break;
default:
val = nom = 0;
}
ext &= 0x03;
}
/*
* Scale the nominal value by the 10-bit fraction
* To avoid overflows, the nominal value is specified in millivolts!
* Returned value is in microvolts.
*/
ret = (uint16_t)val << 2 | ext;
ret = (ret * nom) / 0x300;
ret *= 1000;
return ret;
}
SYSCTL_SETUP(sysctl_dbcoolsetup, "sysctl dBCool subtree setup")
{
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "hw", NULL,
NULL, 0, NULL, 0,
CTL_HW, CTL_EOL);
}
/*
* Select the appropriate register based on fan controller index
* and attribute
*/
static uint8_t
sysctl_dbcool_chipreg(struct dbcool_softc *sc, int num)
{
uint8_t reg;
int idx;
if (num & 0x10000) {
idx =(num >> 8) & 0xff;
switch (num & 0xff) {
case DBC_PWM_BEHAVIOR:
reg = sc->sc_chip->power[idx].behavior;
break;
case DBC_PWM_RANGE:
reg = sc->sc_chip->power[idx].range;
break;
case DBC_PWM_MIN_DUTY:
reg = sc->sc_chip->power[idx].min;
break;
case DBC_PWM_MAX_DUTY:
reg = sc->sc_chip->power[idx].max;
break;
case DBC_PWM_CUR_DUTY:
reg = sc->sc_chip->power[idx].cur;
break;
default:
reg = 0xff;
break;
}
}
else
reg = sc->sc_chip->table[num].reg.val_reg;
return reg;
}
static int
sysctl_dbcool_tmin(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg;
uint8_t newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
if (sc->sc_temp_offset) {
reg = dbcool_readreg(sc, chipreg);
reg -= sc->sc_temp_offset;
} else
reg = (int8_t)dbcool_readreg(sc, chipreg);
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
if (*(int *)node.sysctl_data < -64 ||
*(int *)node.sysctl_data > 127 + sc->sc_temp_offset)
return EINVAL;
newreg = *(int *)node.sysctl_data;
newreg += sc->sc_temp_offset;
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_adm1030_tmin(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg, oldreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
oldreg = (int8_t)dbcool_readreg(sc, chipreg);
reg = (oldreg >> 1) & ~0x03;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 127)
return EINVAL;
newreg = *(int *)node.sysctl_data;
newreg &= ~0x03;
newreg <<= 1;
newreg |= (oldreg & 0x07);
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_adm1030_trange(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error, newval;
uint8_t chipreg, oldreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
oldreg = (int8_t)dbcool_readreg(sc, chipreg);
reg = oldreg & 0x07;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
newval = *(int *)node.sysctl_data;
if (newval == 5)
newreg = 0;
else if (newval == 10)
newreg = 1;
else if (newval == 20)
newreg = 2;
else if (newval == 40)
newreg = 3;
else if (newval == 80)
newreg = 4;
else
return EINVAL;
newreg |= (oldreg & ~0x07);
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_dbcool_duty(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg, oldreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
oldreg = dbcool_readreg(sc, chipreg);
reg = (uint32_t)oldreg;
if (sc->sc_chip->flags & DBCFLAG_ADM1030)
reg = ((reg & 0x0f) * 100) / 15;
else
reg = (reg * 100) / 255;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 100)
return EINVAL;
if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
newreg = *(uint8_t *)(node.sysctl_data) * 15 / 100;
newreg |= oldreg & 0xf0;
} else
newreg = *(uint8_t *)(node.sysctl_data) * 255 / 100;
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_dbcool_behavior(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int i, reg, error;
uint8_t chipreg, oldreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
oldreg = dbcool_readreg(sc, chipreg);
if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
if ((dbcool_readreg(sc, DBCOOL_ADM1030_CFG2) & 1) == 0)
reg = 4;
else if ((oldreg & 0x80) == 0)
reg = 7;
else if ((oldreg & 0x60) == 0)
reg = 4;
else
reg = 6;
} else
reg = (oldreg >> 5) & 0x07;
strlcpy(dbcool_cur_behav, behavior[reg], sizeof(dbcool_cur_behav));
node.sysctl_data = dbcool_cur_behav;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - convert string to value */
newreg = __arraycount(behavior);
for (i = 0; i < __arraycount(behavior); i++)
if (strcmp(node.sysctl_data, behavior[i]) == 0)
break;
if (i >= __arraycount(behavior))
return EINVAL;
if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
/*
* ADM1030 splits fan controller behavior across two
* registers. We also do not support Auto-Filter mode
* nor do we support Manual-RPM-feedback.
*/
if (newreg == 4) {
oldreg = dbcool_readreg(sc, DBCOOL_ADM1030_CFG2);
oldreg &= ~0x01;
dbcool_writereg(sc, DBCOOL_ADM1030_CFG2, oldreg);
} else {
if (newreg == 0)
newreg = 4;
else if (newreg == 6)
newreg = 7;
else if (newreg == 7)
newreg = 0;
else
return EINVAL;
newreg <<= 5;
newreg |= (oldreg & 0x1f);
dbcool_writereg(sc, chipreg, newreg);
oldreg = dbcool_readreg(sc, DBCOOL_ADM1030_CFG2) | 1;
dbcool_writereg(sc, DBCOOL_ADM1030_CFG2, oldreg);
}
} else {
newreg = (dbcool_readreg(sc, chipreg) & 0x1f) | (i << 5);
dbcool_writereg(sc, chipreg, newreg);
}
return 0;
}
static int
sysctl_dbcool_range(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg;
uint8_t newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sysctl_dbcool_chipreg(sc, node.sysctl_num);
reg = (dbcool_readreg(sc, chipreg) >> 4) & 0x0f;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
if (*(int *)node.sysctl_data < 0 || *(int *)node.sysctl_data > 0x0f)
return EINVAL;
newreg = (dbcool_readreg(sc, chipreg) & 0x0f) |
(*(int *)node.sysctl_data << 4);
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_dbcool_volt_limit(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
int nom, newval;
uint8_t chipreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = node.sysctl_num;
/*
* Determine the nominal voltage for this sysctl node
* Values are maintained in milliVolts so we can use
* integer rather than floating point arithmetic
*/
if (sc->sc_chip->flags & DBCFLAG_ADT7466)
switch ((chipreg - DBCOOL_ADT7466_AIN1_LOLIM) / 2) {
case 0: /* AIN1 */
case 1: /* AIN2 */
nom = 1687; /* XXX Full-scale is 2.250V? */
break;
case 2: /* Vcc */
nom = 3300;
break;
default:
nom = 0;
break;
}
else if (sc->sc_chip->flags & DBCFLAG_ADM1030) {
/*
* There are no voltage sensors on the ADM1030
*/
return EINVAL;
} else
/*
* It's a "normal" dbCool chip
*/
switch ((chipreg - DBCOOL_25VIN_LOWLIM) / 2) {
case 0: /* 2.5V */
nom = 2500;
break;
case 1: /* Vccp */
nom = 2250;
break;
case 2: /* Vcc */
nom = dbcool_supply_voltage(sc);
break;
case 3: /* 5V */
nom = 5000;
break;
case 4: /* 12V */
nom = 12000;
break;
default:
nom = 0;
break;
}
reg = dbcool_readreg(sc, chipreg);
reg *= nom;
reg /= 0xc0; /* values are scaled so 0xc0 == nominal voltage */
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/*
* We were asked to update the value, so scale it and sanity
* check before writing
*/
if (nom == 0)
return EINVAL;
newval = *(int *)node.sysctl_data;
newval *= 0xc0;
newval /= nom;
if (newval < 0 || newval > 0xff)
return EINVAL;
newreg = newval;
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
static int
sysctl_dbcool_temp_limit(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error, newtemp;
uint8_t chipreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = node.sysctl_num;
/* If using offset mode, adjust, else treat as signed */
if (sc->sc_temp_offset) {
reg = dbcool_readreg(sc, chipreg);
reg -= sc->sc_temp_offset;
} else
reg = (int8_t)dbcool_readreg(sc, chipreg);
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
newtemp = *(int *)node.sysctl_data + sc->sc_temp_offset;
if (newtemp < 0 || newtemp > 0xff)
return EINVAL;
dbcool_writereg(sc, chipreg, newtemp);
return 0;
}
static int
sysctl_dbcool_fan_limit(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error, newrpm, dividend;
uint8_t chipreg;
uint8_t newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = node.sysctl_num;
/* retrieve two-byte limit */
reg = dbcool_read_rpm(sc, chipreg);
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/*
* We were asked to update the value. Calculate the two-byte
* limit and validate it. Due to the way fan RPM is calculated,
* the new value must be at least 83 RPM (331 RPM for ADM1030)!
* Allow a value of -1 or 0 to indicate no limit.
*/
newrpm = *(int *)node.sysctl_data;
if (newrpm == 0 || newrpm == -1)
newrpm = 0xffff;
else {
if (sc->sc_chip->flags & DBCFLAG_ADM1030)
dividend = 11250 * 60;
else
dividend = 90000 * 60;
newrpm = dividend / newrpm;
if (newrpm & ~0xffff)
return EINVAL;
}
/* Update the on-chip registers with new value */
newreg = newrpm & 0xff;
dbcool_writereg(sc, chipreg, newreg);
newreg = (newrpm >> 8) & 0xff;
dbcool_writereg(sc, chipreg + 1, newreg);
return 0;
}
static int
sysctl_dbcool_vid(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg, newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = node.sysctl_num;
/* retrieve 5- or 6-bit value */
newreg = dbcool_readreg(sc, chipreg);
if ((sc->sc_chip->flags & DBCFLAG_HAS_VID_SEL) &&
(reg & 0x80))
reg = newreg & 0x3f;
else
reg = newreg & 0x1f;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error == 0 && newp != NULL)
error = EINVAL;
return error;
}
static int
sysctl_dbcool_thyst(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg;
uint8_t newreg, newhyst;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = node.sysctl_num & 0x7f;
/* retrieve 4-bit value */
newreg = dbcool_readreg(sc, chipreg);
if ((node.sysctl_num & 0x80) == 0)
reg = newreg >> 4;
else
reg = newreg;
reg = reg & 0x0f;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
/* We were asked to update the value - sanity check before writing */
newhyst = *(int *)node.sysctl_data;
if (newhyst > 0x0f)
return EINVAL;
/* Insert new value into field and update register */
if ((node.sysctl_num & 0x80) == 0) {
newreg &= 0x0f;
newreg |= (newhyst << 4);
} else {
newreg &= 0xf0;
newreg |= newhyst;
}
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
#ifdef DBCOOL_DEBUG
/*
* These routines can be used for debugging. reg_select is used to
* select any arbitrary register in the device. reg_access is used
* to read (and optionally update) the selected register.
*
* No attempt is made to validate the data passed. If you use these
* routines, you are assumed to know what you're doing!
*
* Caveat user
*/
static int
sysctl_dbcool_reg_select(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
reg = sc->sc_user_reg;
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
sc->sc_user_reg = *(int *)node.sysctl_data;
return 0;
}
static int
sysctl_dbcool_reg_access(SYSCTLFN_ARGS)
{
struct sysctlnode node;
struct dbcool_softc *sc;
int reg, error;
uint8_t chipreg;
uint8_t newreg;
node = *rnode;
sc = (struct dbcool_softc *)node.sysctl_data;
chipreg = sc->sc_user_reg;
reg = dbcool_readreg(sc, chipreg);
node.sysctl_data = ®
error = sysctl_lookup(SYSCTLFN_CALL(&node));
if (error || newp == NULL)
return error;
newreg = *(int *)node.sysctl_data;
dbcool_writereg(sc, chipreg, newreg);
return 0;
}
#endif /* DBCOOL_DEBUG */
/*
* Encode the PWM controller number and attribute into the sysctl_num
* so we can select the correct device register later. (We could place
* the register number itself here, but that would lose control over
* the sequencing of the sysctl tree entries.)
*/
#define DBC_PWM_SYSCTL(idx, seq) ( 0x10000 | (idx << 8) | seq)
void
dbcool_setup(device_t self)
{
struct dbcool_softc *sc = device_private(self);
const struct sysctlnode *me = NULL;
const struct sysctlnode *me2 = NULL;
struct sysctlnode *node = NULL;
uint8_t cfg_val, cfg_reg;
int (*helper)(SYSCTLFN_PROTO);
int i, j, rw_flag;
int name_index, sysctl_index, sysctl_num;
int ret, error;
char name[SYSCTL_NAMELEN];
/*
* Some chips are capable of reporting an extended temperature range
* by default. On these models, config register 5 bit 0 can be set
* to 1 for compatability with other chips that report 2s complement.
*/
if (sc->sc_chip->flags & DBCFLAG_ADT7466) {
if (dbcool_readreg(sc, DBCOOL_ADT7466_CONFIG1) & 0x80)
sc->sc_temp_offset = 64;
else
sc->sc_temp_offset = 0;
} else if (sc->sc_chip->flags & DBCFLAG_TEMPOFFSET) {
if (dbcool_readreg(sc, DBCOOL_CONFIG5_REG) &
DBCOOL_CFG5_TWOSCOMP)
sc->sc_temp_offset = 0;
else
sc->sc_temp_offset = 64;
} else
sc->sc_temp_offset = 0;
sc->sc_sme = sysmon_envsys_create();
rw_flag = dbcool_islocked(sc)?CTLFLAG_READONLY:CTLFLAG_READWRITE;
rw_flag |= CTLFLAG_OWNDESC;
ret = sysctl_createv(NULL, 0, NULL, &me,
rw_flag,
CTLTYPE_NODE, device_xname(self), NULL,
NULL, 0, NULL, 0,
CTL_HW, CTL_CREATE, CTL_EOL);
if (sc->sc_chip->flags & DBCFLAG_HAS_VID) {
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READONLY, CTLTYPE_INT, "CPU VID bits", NULL,
sysctl_dbcool_vid,
0, sc, sizeof(int),
CTL_HW, me->sysctl_num, DBCOOL_VID_REG, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
}
#ifdef DBCOOL_DEBUG
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE, CTLTYPE_INT, "reg_select", NULL,
sysctl_dbcool_reg_select,
0, sc, sizeof(int),
CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE, CTLTYPE_INT, "reg_access", NULL,
sysctl_dbcool_reg_access,
0, sc, sizeof(int),
CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
#endif /* DBCOOL_DEBUG */
/* create sensors / controllers */
for (i=0; sc->sc_chip->table[i].type != DBC_EOF; i++) {
if (i >= DBCOOL_MAXSENSORS &&
sc->sc_chip->table[i].type != DBC_CTL) {
aprint_normal_dev(self, "chip table too large!\n");
break;
}
name_index = sc->sc_chip->table[i].name_index;
switch (sc->sc_chip->table[i].type) {
case DBC_TEMP:
sc->sc_sensor[i].units = ENVSYS_STEMP;
helper = sysctl_dbcool_temp_limit;
break;
case DBC_VOLT:
sc->sc_sensor[i].units = ENVSYS_SVOLTS_DC;
helper = sysctl_dbcool_volt_limit;
break;
case DBC_FAN:
sc->sc_sensor[i].units = ENVSYS_SFANRPM;
helper = sysctl_dbcool_fan_limit;
break;
case DBC_CTL:
helper = NULL;
/*
* Search for the corresponding temp sensor
* (temp sensors need to be created first!)
*/
sysctl_num = -1;
for (j = 0; j < i; j++) {
if (j > DBCOOL_MAXSENSORS ||
sc->sc_chip->table[j].type != DBC_TEMP)
continue;
if (sc->sc_chip->table[j].name_index !=
sc->sc_chip->table[i].name_index)
continue;
sysctl_num = sc->sc_sysctl_num[j];
break;
}
if (sysctl_num == -1)
break;
sysctl_index = sc->sc_chip->table[i].sysctl_index;
strlcpy(name, dbc_sysctl_table[sysctl_index].name,
sizeof(name));
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
rw_flag, CTLTYPE_INT, name,
dbc_sysctl_table[sysctl_index].desc,
dbc_sysctl_table[sysctl_index].helper,
0, sc, sizeof(int),
CTL_HW, me->sysctl_num, sysctl_num,
CTL_CREATE, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
break;
default:
helper = NULL;
aprint_error_dev(self, "sensor_table index %d has bad"
" type %d\n", i, sc->sc_chip->table[i].type);
break;
}
if (sc->sc_chip->table[i].type == DBC_CTL)
continue;
strlcpy(sc->sc_sensor[i].desc,
dbc_sensor_names[name_index],
sizeof(sc->sc_sensor[i].desc));
sc->sc_regs[i] = &sc->sc_chip->table[i].reg;
sc->sc_sensor[i].flags |= ENVSYS_FMONCRITUNDER;
if (sc->sc_chip->table[i].type != DBC_FAN)
sc->sc_sensor[i].flags |= ENVSYS_FMONCRITOVER;
if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[i]))
goto out;
/* create sysctl node for the sensor */
ret = sysctl_createv(NULL, 0, NULL, &me2, CTLFLAG_READWRITE,
CTLTYPE_NODE, sc->sc_sensor[i].desc, NULL,
NULL, 0, NULL, 0,
CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
if (me2 == NULL)
continue;
sc->sc_sysctl_num[i] = me2->sysctl_num;
/* create sysctl node for the low limit */
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE,
CTLTYPE_INT, "low_lim", NULL, helper, 0, sc, 0,
CTL_HW, me->sysctl_num, me2->sysctl_num,
sc->sc_regs[i]->lo_lim_reg, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
/* Fans do not have a high limit */
if (sc->sc_chip->table[i].type == DBC_FAN)
continue;
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE,
CTLTYPE_INT, "hi_lim", NULL, helper, 0, sc, 0,
CTL_HW, me->sysctl_num, me2->sysctl_num,
sc->sc_regs[i]->hi_lim_reg, CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
}
/* If supported, create sysctl tree for fan PWM controllers */
if (sc->sc_chip->power != NULL)
for (i = 0; sc->sc_chip->power[i].desc != NULL; i++) {
snprintf(name, sizeof(name), "fan_ctl_%d", i);
ret = sysctl_createv(NULL, 0, NULL, &me2,
rw_flag,
CTLTYPE_NODE, name, NULL,
NULL, 0, NULL, 0,
CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
for (j = 0; j < DBC_PWM_LAST_PARAM; j++) {
if (j == DBC_PWM_RANGE &&
(sc->sc_chip->flags & DBCFLAG_ADM1027) != 0)
continue;
if (j == DBC_PWM_MAX_DUTY &&
(sc->sc_chip->flags & DBCFLAG_HAS_MAXDUTY)
== 0)
continue;
strlcpy(name, dbc_sysctl_table[j].name,
sizeof(name));
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
rw_flag,
(j == 0)?CTLTYPE_STRING:CTLTYPE_INT,
name,
dbc_sysctl_table[j].desc,
dbc_sysctl_table[j].helper,
0, sc,
( j == 0)?sizeof(dbcool_cur_behav):
sizeof(int),
CTL_HW, me->sysctl_num, me2->sysctl_num,
DBC_PWM_SYSCTL(i, j), CTL_EOL);
if (node != NULL)
node->sysctl_data = sc;
}
}
/*
* Read and rewrite config register to activate device
*/
if (sc->sc_chip->flags & DBCFLAG_ADM1030)
cfg_reg = DBCOOL_ADM1030_CFG1;
else if (sc->sc_chip->flags & DBCFLAG_ADT7466)
cfg_reg = DBCOOL_ADT7466_CONFIG1;
else
cfg_reg = DBCOOL_CONFIG1_REG;
cfg_val = dbcool_readreg(sc, DBCOOL_CONFIG1_REG);
if ((cfg_val & DBCOOL_CFG1_START) == 0) {
cfg_val |= DBCOOL_CFG1_START;
dbcool_writereg(sc, cfg_reg, cfg_val);
}
if (dbcool_islocked(sc))
aprint_normal_dev(self, "configuration locked\n");
sc->sc_sme->sme_name = device_xname(self);
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_refresh = dbcool_refresh;
if ((error = sysmon_envsys_register(sc->sc_sme)) != 0) {
aprint_error_dev(self,
"unable to register with sysmon (%d)\n", error);
goto out;
}
return;
out:
sysmon_envsys_destroy(sc->sc_sme);
}
static void
dbcool_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct dbcool_softc *sc=sme->sme_cookie;
int i;
int cur, hi, low;
struct reg_list *reg;
i = edata->sensor;
reg = sc->sc_regs[i];
switch (edata->units)
{
case ENVSYS_STEMP:
cur = dbcool_read_temp(sc, reg->val_reg, true);
low = dbcool_read_temp(sc, reg->lo_lim_reg, false);
hi = dbcool_read_temp(sc, reg->hi_lim_reg, false);
break;
case ENVSYS_SVOLTS_DC:
cur = dbcool_read_volt(sc, reg->val_reg, true);
low = dbcool_read_volt(sc, reg->lo_lim_reg, false);
hi = dbcool_read_volt(sc, reg->hi_lim_reg, false);
break;
case ENVSYS_SFANRPM:
cur = dbcool_read_rpm(sc, reg->val_reg);
low = dbcool_read_rpm(sc, reg->lo_lim_reg);
hi = 1 << 16;
break;
default:
edata->state = ENVSYS_SINVALID;
return;
}
if (cur == 0 && edata->units != ENVSYS_SFANRPM)
edata->state = ENVSYS_SINVALID;
/* Make sure limits are sensible */
else if (hi <= low)
edata->state = ENVSYS_SVALID;
/*
* If fan is "stalled" but has no low limit, treat
* it as though the fan is not installed.
*/
else if (edata->units == ENVSYS_SFANRPM && cur == 0 &&
(low == 0 || low == -1))
edata->state = ENVSYS_SINVALID;
/*
* Compare current value against the limits
*/
else if (cur < low)
edata->state = ENVSYS_SCRITUNDER;
else if (cur > hi)
edata->state = ENVSYS_SCRITOVER;
else
edata->state = ENVSYS_SVALID;
edata->value_cur = cur;
}
int
dbcool_chip_ident(struct dbcool_softc *sc)
{
/* verify this is a supported dbCool chip */
uint8_t c_id, d_id, r_id;
int i;
c_id = dbcool_readreg(sc, DBCOOL_COMPANYID_REG);
d_id = dbcool_readreg(sc, DBCOOL_DEVICEID_REG);
r_id = dbcool_readreg(sc, DBCOOL_REVISION_REG);
for (i = 0; chip_table[i].company != 0; i++)
if ((c_id == chip_table[i].company) &&
(d_id == chip_table[i].device ||
chip_table[i].device == 0xff) &&
(r_id == chip_table[i].rev ||
chip_table[i].rev == 0xff)) {
sc->sc_chip = &chip_table[i];
return i;
}
aprint_verbose("dbcool_chip_ident: addr 0x%02x c_id 0x%02x d_id 0x%02x"
" r_id 0x%02x: No match.\n", sc->sc_addr, c_id, d_id,
r_id);
return -1;
}
/* $NetBSD: dbcool_reg.h,v 1.1 2008/10/02 00:47:51 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Goyette
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* a driver for the dbCool(tm) family of environmental controllers
*/
#ifndef DBCOOLREG_H
#define DBCOOLREG_H
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dbcool_reg.h,v 1.1 2008/10/02 00:47:51 pgoyette Exp $");
#define DBCOOL_ADDRMASK 0x7f
#define DBCOOL_ADDR 0x2e /* Some chips have multiple addrs */
/* The dBCool chip family register set */
/* Not all registers are available on all chips! */
#define DBCOOL_CONFIG5A_REG 0x04
#define DBCOOL_CONFIG6_REG 0x10
#define DBCOOL_CONFIG7_REG 0x11
#define DBCOOL_INTERNAL_TRIP 0x13
#define DBCOOL_EXTERNAL_TRIP 0x14
#define DBCOOL_TEST 0x15
#define DBCOOL_CHANNEL_MODE 0x16
#define DBCOOL_INT_TRIP_FIXED 0x17
#define DBCOOL_EXT_TRIP_FIXED 0x18
#define DBCOOL_ANALOG_OUT 0x19
#define DBCOOL_PECI1 0x1A
#define DBCOOL_PECI2 0x1B
#define DBCOOL_PECI3 0x1C
#define DBCOOL_IMON 0x1D
#define DBCOOL_VTT 0x1E
#define DBCOOL_EXTRES 0x1F
#define DBCOOL_OFFSET 0x1F
#define DBCOOL_25VIN 0x20
#define DBCOOL_CPU_VOLTAGE 0x21
#define DBCOOL_SUPPLY_VOLTAGE 0x22
#define DBCOOL_5VIN 0x23
#define DBCOOL_12VIN 0x24
#define DBCOOL_CPU_VOLTAGE2 0x25
#define DBCOOL_REMOTE1_TEMP 0x25
#define DBCOOL_LOCAL_TEMP 0x26
#define DBCOOL_REMOTE2_TEMP 0x27
#define DBCOOL_FAN1_TACH_LSB 0x28
#define DBCOOL_FAN1_TACH_MSB 0x29
#define DBCOOL_FAN2_TACH_LSB 0x2A
#define DBCOOL_FAN2_TACH_MSB 0x2B
#define DBCOOL_FAN3_TACH_LSB 0x2C
#define DBCOOL_FAN3_TACH_MSB 0x2D
#define DBCOOL_FAN4_TACH_LSB 0x2E
#define DBCOOL_FAN4_TACH_MSB 0x2F
#define DBCOOL_PWM1_CURDUTY 0x30
#define DBCOOL_DAC0_START 0x30
#define DBCOOL_PWM2_CURDUTY 0x31
#define DBCOOL_DAC1_START 0x31
#define DBCOOL_PWM3_CURDUTY 0x32
#define DBCOOL_DAC0_MIN 0x32
#define DBCOOL_PECI0 0x33
#define DBCOOL_DAC1_MIN 0x33
#define DBCOOL_PECI_LOWLIM 0x34
#define DBCOOL_DAC0_MAX 0x34
#define DBCOOL_PECI_HIGHLIM 0x35
#define DBCOOL_DAC1_MAX 0x35
#define DBCOOL_PECI_CFG1 0x36
#define DBCOOL_DYNTMIN_CNTRL1 0x36
#define DBCOOL_DYNTMIN_CNTRL2 0x37
#define DBCOOL_PWM1_MAXDUTY 0x38
#define DBCOOL_PWM2_MAXDUTY 0x39
#define DBCOOL_PWM3_MAXDUTY 0x3A
/*
* Note: ADT7490 reused the Device_ID register for PECI Tcontrol limit
*/
#define DBCOOL_DEVICEID_REG 0x3D
#define DBCOOL_PECI_TCRTL_LIM 0x3D
#define DBCOOL_COMPANYID_REG 0x3E
#define DBCOOL_REVISION_REG 0x3F
#define DBCOOL_CONFIG1_REG 0x40
#define DBCOOL_DAC0_OUT 0x40
#define DBCOOL_ISR1_REG 0x41
#define DBCOOL_DAC1_OUT 0x41
#define DBCOOL_ISR2_REG 0x42
#define DBCOOL_ISR3_REG 0x43
#define DBCOOL_VID_REG 0x43
#define DBCOOL_25VIN_LOWLIM 0x44
#define DBCOOL_25VIN_HIGHLIM 0x45
#define DBCOOL_VCCP_LOWLIM 0x46
#define DBCOOL_VCCP_HIGHLIM 0x47
#define DBCOOL_VIDB 0x47
#define DBCOOL_VCC_LOWLIM 0x48
#define DBCOOL_VCC_HIGHLIM 0x49
#define DBCOOL_VID4 0x49
#define DBCOOL_5VIN_LOWLIM 0x4A
#define DBCOOL_5VIN_HIGHLIM 0x4B
#define DBCOOL_12VIN_LOWLIM 0x4C
#define DBCOOL_12VIN_HIGHLIM 0x4D
#define DBCOOL_REMOTE1_LOWLIM 0x4E
#define DBCOOL_REMOTE1_HIGHLIM 0x4F
#define DBCOOL_LOCAL_LOWLIM 0x50
#define DBCOOL_LOCAL_HIGHLIM 0x51
#define DBCOOL_REMOTE2_LOWLIM 0x52
#define DBCOOL_REMOTE2_HIGHLIM 0x53
#define DBCOOL_TACH1_MIN_LSB 0x54
#define DBCOOL_TACH1_MIN_MSB 0x55
#define DBCOOL_TACH2_MIN_LSB 0x56
#define DBCOOL_TACH2_MIN_MSB 0x57
#define DBCOOL_TACH3_MIN_LSB 0x58
#define DBCOOL_TACH3_MIN_MSB 0x59
#define DBCOOL_TACH4_MIN_LSB 0x5A
#define DBCOOL_TACH4_MIN_MSB 0x5B
#define DBCOOL_PWM1_CTL 0x5C
#define DBCOOL_PWM2_CTL 0x5D
#define DBCOOL_PWM3_CTL 0x5E
#define DBCOOL_PWM1_TRANGE 0x5F
#define DBCOOL_PWM2_TRANGE 0x60
#define DBCOOL_PWM3_TRANGE 0x61
#define DBCOOL_ENH_ACOUST_1 0x62
#define DBCOOL_ENH_ACOUST_2 0x63
#define DBCOOL_PWM1_MINDUTY 0x64
#define DBCOOL_PWM2_MINDUTY 0x65
#define DBCOOL_PWM3_MINDUTY 0x66
#define DBCOOL_REMOTE1_TMIN 0x67
#define DBCOOL_LOCAL_TMIN 0x68
#define DBCOOL_REMOTE2_TMIN 0x69
#define DBCOOL_REMOTE1_TTHRESH 0x6A
#define DBCOOL_LOCAL_TTHRESH 0x6B
#define DBCOOL_REMOTE2_TTHRESH 0x6C
#define DBCOOL_R1_LCL_TMIN_HYST 0x6D
#define DBCOOL_R2_TMIN_HYST 0x6E
#define DBCOOL_XNOR_ENABLE 0x6F
#define DBCOOL_REMOTE1_TEMPOFF 0x70
#define DBCOOL_LOCAL_TEMPOFF 0x71
#define DBCOOL_REMOTE2_TEMPOFF 0x72
#define DBCOOL_CONFIG2_REG 0x73
#define DBCOOL_IMASK1_REG 0x74
#define DBCOOL_IMASK2_REG 0x75
#define DBCOOL_EXTRES1_REG 0x76
#define DBCOOL_EXTRES2_REG 0x77
#define DBCOOL_CONFIG3_REG 0x78
#define DBCOOL_THERM_TIMERSTATUS_REG 0x79
#define DBCOOL_THERM_TIMERLIMIT_REG 0x7A
#define DBCOOL_TACHPULSE_REG 0x7B
#define DBCOOL_CONFIG5_REG 0x7C
#define DBCOOL_CONFIG4_REG 0x7D
#define DBCOOL_TEST1_REG 0x7E
#define DBCOOL_TEST2_REG 0x7F
#define DBCOOL_GPIO_CONFIG 0x80
#define DBCOOL_ISR4_REG 0x81
#define DBCOOL_IMASK3_REG 0x82
#define DBCOOL_IMASK4_REG 0x83
#define DBCOOL_VTT_LOWLIM 0x84
#define DBCOOL_IMON_LOWLIM 0x85
#define DBCOOL_VTT_HIGHLIM 0x86
#define DBCOOL_IMON_HIGHLIM 0x87
#define DBCOOL_PECI_CFG2 0x88
#define DBCOOL_TEST3_REG 0x89
#define DBCOOL_PECI_OP_PT 0x8A
#define DBCOOL_REMOTE1_OP_PT 0x8B
#define DBCOOL_LOCAL_OP_PT 0x8C
#define DBCOOL_REMOTE2_OP_PT 0x8D
#define DBCOOL_DYNTMIN_CTL1 0x8E
#define DBCOOL_DYNTMIN_CTL2 0x8F
#define DBCOOL_DYNTMIN_CTL3 0x90
#define DBCOOL_PECI0_TEMPOFF 0x94
#define DBCOOL_PECI1_TEMPOFF 0x95
#define DBCOOL_PECI2_TEMPOFF 0x96
#define DBCOOL_PECI3_TEMPOFF 0x97
#define DBCOOL_NO_REG 0xff
/* Config register bit definitions */
#define DBCOOL_CFG1_START 0x01
#define DBCOOL_CFG1_LOCK 0x02
#define DBCOOL_CFG1_RDY 0x04
#define DBCOOL_CFG1_FSPD 0x08
#define DBCOOL_CFG1_VxI 0x10
#define DBCOOL_CFG1_RESET 0x10
#define DBCOOL_CFG1_FSPDIS 0x20
#define DBCOOL_CFG1_12VVID4_SEL 0x20
#define DBCOOL_CFG1_TODIS 0x40
#define DBCOOL_CFG1_Vcc 0x80
#define DBCOOL_CFG1_RESET_LATCH 0x80
#define DBCOOL_CFG2_AIN1 0x01
#define DBCOOL_CFG2_AIN2 0x02
#define DBCOOL_CFG2_AIN3 0x04
#define DBCOOL_CFG2_AIN4 0x08
#define DBCOOL_CFG2_AVG 0x10
#define DBCOOL_CFG2_ATTN 0x20
#define DBCOOL_CFG2_CONV 0x40
#define DBCOOL_CFG2_SHDN 0x80
#define DBCOOL_CFG3_ALERT 0x01
#define DBCOOL_CFG3_THERM 0x02
#define DBCOOL_CFG3_BOOST 0x04
#define DBCOOL_CFG3_FAST 0x08
#define DBCOOL_CFG3_DC1 0x10
#define DBCOOL_CFG3_DC2 0x20
#define DBCOOL_CFG3_DC3 0x40
#define DBCOOL_CFG3_DC4 0x80
#define DBCOOL_CFG4_PIN9FUNC 0x03
#define DBCOOL_CFG4_AINL 0x0C
#define DBCOOL_CFG4_BYPASS_ATTN 0x20
#define DBCOOL_CFG5_TWOSCOMP 0x01
#define DBCOOL_CFG5_FREQ 0x02
#define DBCOOL_CFG5_GPIOD 0x04
#define DBCOOL_CFG5_GPIOP 0x08
#define DBCOOL_CFG6_SLOW_REM1 0x01
#define DBCOOL_CFG6_SLOW_LOCAL 0x02
#define DBCOOL_CFG6_SLOW_REM2 0x04
#define DBCOOL_CFG6_THERM_MAN 0x08
#define DBCOOL_CFG6_VCCP_LOW 0x40
#define DBCOOL_CFG6_EXTRASLOW 0x80
#define DBCOOL_CFG7_DIS_THERM_HYST 0x10
/*
* The ADT7466 is an orphan stepchild in the dbCool family
*/
#define DBCOOL_ADT7466_CONFIG1 0x00
#define DBCOOL_ADT7466_CONFIG2 0x01
#define DBCOOL_ADT7466_CONFIG3 0x02
#define DBCOOL_ADT7466_CONFIG4 0x03
#define DBCOOL_ADT7466_CONFIG5 0x04
#define DBCOOL_ADT7466_AFC1 0x05
#define DBCOOL_ADT7466_AFC2 0x06
#define DBCOOL_ADT7466_REM_TEMP_LSB 0x08
#define DBCOOL_ADT7466_LCL_TEMP_LSB 0x09
#define DBCOOL_ADT7466_AIN1 0x0A
#define DBCOOL_ADT7466_AIN2 0x0B
#define DBCOOL_ADT7466_VCC 0x0C
#define DBCOOL_ADT7466_REM_TEMP_MSB 0x0D
#define DBCOOL_ADT7466_LCL_TEMP_MSB 0x0E
#define DBCOOL_ADT7466_PROCHOT 0x0F
#define DBCOOL_ADT7466_INTRPT1 0x10
#define DBCOOL_ADT7466_INTRPT2 0x11
#define DBCOOL_ADT7466_INTMSK1 0x12
#define DBCOOL_ADT7466_INTMSK2 0x13
#define DBCOOL_ADT7466_AIN1_LOLIM 0x14
#define DBCOOL_ADT7466_AIN1_HILIM 0x15
#define DBCOOL_ADT7466_AIN2_LOLIM 0x16
#define DBCOOL_ADT7466_AIN2_HILIM 0x17
#define DBCOOL_ADT7466_VCC_LOLIM 0x18
#define DBCOOL_ADT7466_VCC_HILIM 0x19
#define DBCOOL_ADT7466_REM_TEMP_LOLIM 0x1A
#define DBCOOL_ADT7466_REM_TEMP_HILIM 0x1B
#define DBCOOL_ADT7466_LCL_TEMP_LOLIM 0x1C
#define DBCOOL_ADT7466_LCL_TEMP_HILIM 0x1D
#define DBCOOL_ADT7466_PROCHOT_LIM 0x1E
#define DBCOOL_ADT7466_AIN1_THERM 0x1F
#define DBCOOL_ADT7466_AIN2_THREM 0x20
#define DBCOOL_ADT7466_REM_THERM 0x21
#define DBCOOL_ADT7466_LCL_THERM 0x22
#define DBCOOL_ADT7466_AIN1_OFFSET 0x24
#define DBCOOL_ADT7466_AIN2_OFFSET 0x25
#define DBCOOL_ADT7466_REM_OFFSET 0x26
#define DBCOOL_ADT7466_LCL_OFFSET 0x27
#define DBCOOL_ADT7466_AIN1_TMIN 0x28
#define DBCOOL_ADT7466_AIN2_TMIN 0x29
#define DBCOOL_ADT7466_REM_TMIN 0x2A
#define DBCOOL_ADT7466_LCL_TMIN 0x2B
#define DBCOOL_ADT7466_AIN_RANGES 0x2C
#define DBCOOL_ADT7466_LCL_REM_RANGES 0x2D
#define DBCOOL_ADT7466_AIN_HYSTS 0x2E
#define DBCOOL_ADT7466_LCL_REM_HYSTS 0x2F
#define DBCOOL_ADT7466_FANA_STARTV 0x30
#define DBCOOL_ADT7466_FANB_STARTV 0x31
#define DBCOOL_ADT7466_FANA_MINV 0x32
#define DBCOOL_ADT7466_FANB_MINV 0x33
#define DBCOOL_ADT7466_FANA_MAXRPM_MSB 0x34
#define DBCOOL_ADT7466_FANB_MAXRPM_MSB 0x35
#define DBCOOL_ADT7466_ENH_ACOUSTICS 0x36
#define DBCOOL_ADT7466_FAULT_INCR 0x37
#define DBCOOL_ADT7466_TIMEOUT 0x38
#define DBCOOL_ADT7466_PULSES 0x39
#define DBCOOL_ADT7466_DRIVE1 0x40
#define DBCOOL_ADT7466_DRIVE2 0x41
#define DBCOOL_ADT7466_XOR_TEST 0x42
#define DBCOOL_ADT7466_FANA_LSB 0x48
#define DBCOOL_ADT7466_FANA_MSB 0x49
#define DBCOOL_ADT7466_FANB_LSB 0x4A
#define DBCOOL_ADT7466_FANB_MSB 0x4B
#define DBCOOL_ADT7466_FANA_LOLIM_LSB 0x4C
#define DBCOOL_ADT7466_FANA_LOLIM_MSB 0x4D
#define DBCOOL_ADT7466_FANB_LOLIM_LSB 0x4E
#define DBCOOL_ADT7466_FANB_LOLIM_MSB 0x4F
#define DBCOOL_ADT7466_CFG1_Vcc 0x40
#define DBCOOL_ADT7466_CFG2_SHDN 0x40
/*
* Even though it's not really a member of the dbCool family, we also
* support the ADM1030 chip. It has a different register set.
*/
#define DBCOOL_ADM1030_CFG1 0x00
#define DBCOOL_ADM1030_CFG2 0x01
#define DBCOOL_ADM1030_STATUS1 0x02
#define DBCOOL_ADM1030_STATUS2 0x03
#define DBCOOL_ADM1030_TEMP_EXTRES 0x06
#define DBCOOL_ADM1030_TEST_REG 0x07
#define DBCOOL_ADM1030_FAN_TACH 0x08
#define DBCOOL_ADM1030_L_TEMP 0x0A
#define DBCOOL_ADM1030_R_TEMP 0x0B
#define DBCOOL_ADM1030_L_OFFSET 0x0D
#define DBCOOL_ADM1030_R_OFFSET 0x0E
#define DBCOOL_ADM1030_FAN_LO_LIM 0x10
#define DBCOOL_ADM1030_L_HI_LIM 0x14
#define DBCOOL_ADM1030_L_LO_LIM 0x15
#define DBCOOL_ADM1030_L_TTHRESH 0x16
#define DBCOOL_ADM1030_R_HI_LIM 0x18
#define DBCOOL_ADM1030_R_LO_LIM 0x19
#define DBCOOL_ADM1030_R_TTHRESH 0x1A
#define DBCOOL_ADM1030_FAN_CHAR 0x20
#define DBCOOL_ADM1030_FAN_SPEED_CFG 0x22
#define DBCOOL_ADM1030_FAN_FILTER 0x23
#define DBCOOL_ADM1030_L_TMIN 0x24
#define DBCOOL_ADM1030_R_TMIN 0x25
#define DBCOOL_ADM1030_DEVICEID DBCOOL_DEVICEID_REG
#define DBCOOL_ADM1030_COMPANYID DBCOOL_COMPANYID_REG
#define DBCOOL_ADM1030_REVISION DBCOOL_REVISION_REG
/*
* Macros to locate limit registers for the various sensor types
*/
#define DBCOOL_VOLT_LOLIM(reg) ((reg - DBCOOL_25VIN) * 2 + DBCOOL_25VIN_LOWLIM)
#define DBCOOL_VOLT_HILIM(reg) (DBCOOL_VOLT_LOLIM(reg) + 1)
#define DBCOOL_TEMP_LOLIM(reg) \
((reg - DBCOOL_LOCAL_TEMP) * 2 + DBCOOL_LOCAL_LOWLIM)
#define DBCOOL_TEMP_HILIM(reg) (DBCOOL_TEMP_LOLIM(reg) + 1)
#define DBCOOL_TACH_LOLIM(reg) \
(reg - DBCOOL_FAN1_TACH_LSB + DBCOOL_TACH1_MIN_LSB)
#define ADM1030_TEMP_HILIM(reg) \
((reg - DBCOOL_ADM1030_L_TEMP) * 3 + DBCOOL_ADM1030_L_HI_LIM)
#define ADM1030_TEMP_LOLIM(reg) \
((reg - DBCOOL_ADM1030_L_TEMP) * 3 + DBCOOL_ADM1030_L_LO_LIM)
#define ADT7466_LIM_OFFSET(reg) \
((reg - DBCOOL_AIN1) * 2 + DBCOOL_AIN1_LOWLIM)
#define ADT7466_FAN_LIM_OFFSET(reg) \
(reg - DBCOOL_FANA_LSB + DBCOOL_FANA_LOWLIM_LSB)
/* Company and Device ID values */
#define DBCOOL_COMPANYID 0x41
#define ADM1027_DEVICEID 0x27
#define ADM1030_DEVICEID 0x30
#define ADT7463_DEVICEID 0x27
#define ADT7466_DEVICEID 0x66
#define ADT7467_DEVICEID 0x67
#define ADT7468_DEVICEID 0x68
#define ADT7473_DEVICEID 0x73
#define ADT7475_DEVICEID 0x75
#define ADT7476_DEVICEID 0x76
#define ADM1027_REV_ID 0x60
#define ADT7463_REV_ID1 0x62
#define ADT7463_REV_ID2 0x6A
#define ADT7467_REV_ID1 0x71
#define ADT7467_REV_ID2 0x72
#define ADT7473_REV_ID 0x68
#define ADT7473_1_REV_ID 0x69
#endif /* def DBCOOLREG_H */
/* $NetBSD: dbcool_var.h,v 1.1 2008/10/02 00:47:51 pgoyette Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Paul Goyette
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* A driver for dbCool(tm) family of environmental controllers
*/
#ifndef DBCOOLVAR_H
#define DBCOOLVAR_H
#define DBCOOL_DEBUG
/*
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: dbcool_var.h,v 1.1 2008/10/02 00:47:51 pgoyette Exp $");
#include <dev/i2c/i2cvar.h>
#include <dev/sysmon/sysmonvar.h>
#include "sysmon_envsys.h"
#include <dev/i2c/dbcool_reg.h>
enum dbc_pwm_params {
DBC_PWM_BEHAVIOR = 0,
DBC_PWM_RANGE,
DBC_PWM_MIN_DUTY,
DBC_PWM_MAX_DUTY,
DBC_PWM_CUR_DUTY,
DBC_PWM_LAST_PARAM
};
enum dbc_sensor_type {
DBC_CTL = 0,
DBC_TEMP,
DBC_VOLT,
DBC_FAN,
DBC_EOF
};
#define DBCFLAG_TEMPOFFSET 0x0001
#define DBCFLAG_HAS_MAXDUTY 0x0002
#define DBCFLAG_HAS_SHDN 0x0004
#define DBCFLAG_MULTI_VCC 0x0008
#define DBCFLAG_4BIT_VER 0x0010
#define DBCFLAG_HAS_VID 0x0020
#define DBCFLAG_HAS_VID_SEL 0x0040
#define DBCFLAG_ADM1027 0x1000
#define DBCFLAG_ADM1030 0x2000
#define DBCFLAG_ADT7466 0x4000
/* Maximum sensors for any dbCool device */
#define DBCOOL_MAXSENSORS 15
struct reg_list {
uint8_t val_reg;
uint8_t hi_lim_reg;
uint8_t lo_lim_reg;
};
struct dbcool_sensor {
enum dbc_sensor_type type;
struct reg_list reg;
int name_index;
int sysctl_index;
};
/*
* The members of dbcool_power_control need to stay in the same order
* as the enum dbc_pwm_params above
*/
struct dbcool_power_control {
uint8_t behavior;
uint8_t range;
uint8_t min;
uint8_t max;
uint8_t cur;
const char *desc;
};
struct chip_id;
struct dbcool_softc {
struct device *parent;
i2c_tag_t sc_tag;
i2c_addr_t sc_addr;
struct chip_id *sc_chip;
struct sysmon_envsys *sc_sme;
envsys_data_t sc_sensor[DBCOOL_MAXSENSORS];
int sc_sysctl_num[DBCOOL_MAXSENSORS];
struct reg_list *sc_regs[DBCOOL_MAXSENSORS];
uint8_t sc_suspend;
uint8_t sc_temp_offset;
#ifdef DBCOOL_DEBUG
uint8_t sc_user_reg;
#endif
};
struct chip_id {
uint8_t company;
uint8_t device;
uint8_t rev;
struct dbcool_sensor *table;
struct dbcool_power_control *power;
int flags;
int rpm_dividend;
const char *name;
};
/*
* Expose some routines for the macppc's ki2c match/attach routines
*/
uint8_t dbcool_readreg(struct dbcool_softc *, uint8_t);
void dbcool_writereg(struct dbcool_softc *, uint8_t, uint8_t);
void dbcool_setup(device_t);
int dbcool_chip_ident(struct dbcool_softc *);
bool dbcool_pmf_suspend(device_t PMF_FN_PROTO);
bool dbcool_pmf_resume(device_t PMF_FN_PROTO);
#endif /* def DBCOOLVAR_H */
--- src/sys/dev/i2c/files.i2c 2008/09/11 20:48:50 1.18
+++ src/sys/dev/i2c/files.i2c 2008/10/02 00:47:51 1.19
| @@ -1,115 +1,121 @@ | | | @@ -1,115 +1,121 @@ |
1 | # $NetBSD: files.i2c,v 1.18 2008/09/11 20:48:50 pgoyette Exp $ | | 1 | # $NetBSD: files.i2c,v 1.19 2008/10/02 00:47:51 pgoyette Exp $ |
2 | | | 2 | |
3 | defflag opt_i2cbus.h I2C_SCAN | | 3 | defflag opt_i2cbus.h I2C_SCAN |
4 | define i2cbus { } | | 4 | define i2cbus { } |
5 | define i2cexec | | 5 | define i2cexec |
6 | | | 6 | |
7 | device iic { [addr = -1], [size = -1] } | | 7 | device iic { [addr = -1], [size = -1] } |
8 | attach iic at i2cbus | | 8 | attach iic at i2cbus |
9 | file dev/i2c/i2c.c iic | i2cbus | | 9 | file dev/i2c/i2c.c iic | i2cbus |
10 | file dev/i2c/i2c_exec.c iic | i2cbus | i2cexec | | 10 | file dev/i2c/i2c_exec.c iic | i2cbus | i2cexec |
11 | | | 11 | |
12 | # Common module for bit-bang'ing an I2C bus | | 12 | # Common module for bit-bang'ing an I2C bus |
13 | define i2c_bitbang | | 13 | define i2c_bitbang |
14 | file dev/i2c/i2c_bitbang.c i2c_bitbang | | 14 | file dev/i2c/i2c_bitbang.c i2c_bitbang |
15 | | | 15 | |
16 | # | | 16 | # |
17 | # I2C client devices | | 17 | # I2C client devices |
18 | # | | 18 | # |
19 | | | 19 | |
20 | # M41T00 Real Time Clock | | 20 | # M41T00 Real Time Clock |
21 | device m41trtc | | 21 | device m41trtc |
22 | attach m41trtc at iic | | 22 | attach m41trtc at iic |
23 | file dev/i2c/m41t00.c m41trtc | | 23 | file dev/i2c/m41t00.c m41trtc |
24 | | | 24 | |
25 | # M41ST84 Real Time Clock | | 25 | # M41ST84 Real Time Clock |
26 | device strtc | | 26 | device strtc |
27 | attach strtc at iic | | 27 | attach strtc at iic |
28 | file dev/i2c/m41st84.c strtc | | 28 | file dev/i2c/m41st84.c strtc |
29 | | | 29 | |
30 | # MAX6900 Real Time Clock | | 30 | # MAX6900 Real Time Clock |
31 | device maxrtc | | 31 | device maxrtc |
32 | attach maxrtc at iic | | 32 | attach maxrtc at iic |
33 | file dev/i2c/max6900.c maxrtc | | 33 | file dev/i2c/max6900.c maxrtc |
34 | | | 34 | |
35 | # Philips PCF8583 Real Time Clock | | 35 | # Philips PCF8583 Real Time Clock |
36 | device pcfrtc | | 36 | device pcfrtc |
37 | attach pcfrtc at iic | | 37 | attach pcfrtc at iic |
38 | file dev/i2c/pcf8583.c pcfrtc | | 38 | file dev/i2c/pcf8583.c pcfrtc |
39 | | | 39 | |
40 | # Atmel/Microchip 24Cxx Serial EEPROM | | 40 | # Atmel/Microchip 24Cxx Serial EEPROM |
41 | define at24cxx_eeprom | | 41 | define at24cxx_eeprom |
42 | device seeprom | | 42 | device seeprom |
43 | attach seeprom at iic | | 43 | attach seeprom at iic |
44 | file dev/i2c/at24cxx.c seeprom | at24cxx_eeprom | | 44 | file dev/i2c/at24cxx.c seeprom | at24cxx_eeprom |
45 | needs-flag | | 45 | needs-flag |
46 | | | 46 | |
47 | # National Semiconductor LM75 temperature sensor | | 47 | # National Semiconductor LM75 temperature sensor |
48 | device lmtemp: sysmon_envsys | | 48 | device lmtemp: sysmon_envsys |
49 | attach lmtemp at iic | | 49 | attach lmtemp at iic |
50 | file dev/i2c/lm75.c lmtemp | | 50 | file dev/i2c/lm75.c lmtemp |
51 | | | 51 | |
52 | # Dallas DS1307 Real Time Clock | | 52 | # Dallas DS1307 Real Time Clock |
53 | device dsrtc | | 53 | device dsrtc |
54 | attach dsrtc at iic | | 54 | attach dsrtc at iic |
55 | file dev/i2c/ds1307.c dsrtc | | 55 | file dev/i2c/ds1307.c dsrtc |
56 | | | 56 | |
57 | # Xicor X1226 Real Time Clock | | 57 | # Xicor X1226 Real Time Clock |
58 | device xrtc | | 58 | device xrtc |
59 | attach xrtc at iic | | 59 | attach xrtc at iic |
60 | file dev/i2c/x1226.c xrtc | | 60 | file dev/i2c/x1226.c xrtc |
61 | | | 61 | |
62 | # Analog Devices ADT 7463 thermal monitor / fan controller | | 62 | # Analog Devices ADT 7463 thermal monitor / fan controller |
63 | define adt7463c {} | | 63 | define adt7463c {} |
64 | device adt7463c: sysmon_envsys | | 64 | device adt7463c: sysmon_envsys |
65 | attach adt7463c at iic | | 65 | attach adt7463c at iic |
66 | file dev/i2c/adt7463.c adt7463c | | 66 | file dev/i2c/adt7463.c adt7463c |
67 | | | 67 | |
68 | # Analog Devices ADT 7467 thermal monitor / fan controller | | 68 | # Analog Devices ADT 7467 thermal monitor / fan controller |
69 | define adt7467c {} | | 69 | define adt7467c {} |
70 | device adt7467c: sysmon_envsys | | 70 | device adt7467c: sysmon_envsys |
71 | attach adt7467c at iic | | 71 | attach adt7467c at iic |
72 | file dev/i2c/adt7467.c adt7467c | | 72 | file dev/i2c/adt7467.c adt7467c |
73 | | | 73 | |
| | | 74 | # Analog Devices dBCool family of thermal monitors / fan controllers |
| | | 75 | define dbcool {} |
| | | 76 | device dbcool: sysmon_envsys |
| | | 77 | attach dbcool at iic |
| | | 78 | file dev/i2c/dbcool.c dbcool |
| | | 79 | |
74 | # Analog Devices ADM 1030 thermal monitor / fan controller | | 80 | # Analog Devices ADM 1030 thermal monitor / fan controller |
75 | define adm1030c {} | | 81 | define adm1030c {} |
76 | device adm1030c: sysmon_envsys | | 82 | device adm1030c: sysmon_envsys |
77 | attach adm1030c at iic | | 83 | attach adm1030c at iic |
78 | file dev/i2c/adm1030.c adm1030c | | 84 | file dev/i2c/adm1030.c adm1030c |
79 | | | 85 | |
80 | # RICOH RS5C372[AB] Real Time Clock | | 86 | # RICOH RS5C372[AB] Real Time Clock |
81 | device rs5c372rtc | | 87 | device rs5c372rtc |
82 | attach rs5c372rtc at iic | | 88 | attach rs5c372rtc at iic |
83 | file dev/i2c/rs5c372.c rs5c372rtc | | 89 | file dev/i2c/rs5c372.c rs5c372rtc |
84 | | | 90 | |
85 | # RICOH R2025S/D Real Time Clock | | 91 | # RICOH R2025S/D Real Time Clock |
86 | device r2025rtc | | 92 | device r2025rtc |
87 | attach r2025rtc at iic | | 93 | attach r2025rtc at iic |
88 | file dev/i2c/r2025.c r2025rtc | | 94 | file dev/i2c/r2025.c r2025rtc |
89 | | | 95 | |
90 | # VESA Display Data Channel 2 | | 96 | # VESA Display Data Channel 2 |
91 | device ddc | | 97 | device ddc |
92 | define ddc_read_edid | | 98 | define ddc_read_edid |
93 | attach ddc at iic | | 99 | attach ddc at iic |
94 | file dev/i2c/ddc.c ddc | ddc_read_edid | | 100 | file dev/i2c/ddc.c ddc | ddc_read_edid |
95 | | | 101 | |
96 | # SGS TDA7433 audio mixer | | 102 | # SGS TDA7433 audio mixer |
97 | device sgsmix | | 103 | device sgsmix |
98 | attach sgsmix at iic | | 104 | attach sgsmix at iic |
99 | file dev/i2c/sgsmix.c sgsmix needs-flag | | 105 | file dev/i2c/sgsmix.c sgsmix needs-flag |
100 | defflag opt_sgsmix.h SGSMIX_DEBUG | | 106 | defflag opt_sgsmix.h SGSMIX_DEBUG |
101 | | | 107 | |
102 | # Xbox PIC16LC System Management Controller | | 108 | # Xbox PIC16LC System Management Controller |
103 | device pic16lc: sysmon_envsys | | 109 | device pic16lc: sysmon_envsys |
104 | attach pic16lc at iic | | 110 | attach pic16lc at iic |
105 | file dev/i2c/pic16lc.c pic16lc needs-flag | | 111 | file dev/i2c/pic16lc.c pic16lc needs-flag |
106 | | | 112 | |
107 | # Xbox Serial EEPROM | | 113 | # Xbox Serial EEPROM |
108 | device xbseeprom | | 114 | device xbseeprom |
109 | attach xbseeprom at iic | | 115 | attach xbseeprom at iic |
110 | file dev/i2c/xbseeprom.c xbseeprom | | 116 | file dev/i2c/xbseeprom.c xbseeprom |
111 | | | 117 | |
112 | # Memory Serial Presence Detect | | 118 | # Memory Serial Presence Detect |
113 | device spdmem | | 119 | device spdmem |
114 | attach spdmem at iic | | 120 | attach spdmem at iic |
115 | file dev/i2c/spdmem.c spdmem | | 121 | file dev/i2c/spdmem.c spdmem |