Tested on an F71882 (at 0x2e; GENERIC only configs it at 4e).
The voltage dividers register is full of lies, so the part of this
patch that reads it can be ripped out (along with the temperature
diode offset bits, I guess). These chips also have a watchdog
timer. I can set it and watch it counting down, but reboot does
not happen, so it's evidently not wired on my board.
hw.sensors.kate0.temp0=6.50 degC
hw.sensors.kate0.temp1=-2.75 degC
hw.sensors.kate0.temp2=12.50 degC
hw.sensors.kate0.temp3=5.75 degC
hw.sensors.fins0.temp0=35.00 degC
hw.sensors.fins0.temp1=38.00 degC
hw.sensors.fins0.fan0=1718 RPM
hw.sensors.fins0.volt0=3.33 VDC (+3.3V)
hw.sensors.fins0.volt1=1.12 VDC (Vcore)
hw.sensors.fins0.volt2=1.78 VDC (Vram)
hw.sensors.fins0.volt3=1.08 VDC (Vchips)
hw.sensors.fins0.volt4=4.92 VDC (+5V)
hw.sensors.fins0.volt5=12.14 VDC (+12V)
hw.sensors.fins0.volt6=1.62 VDC (+1.5V)
hw.sensors.fins0.volt7=3.28 VDC (Vsb)
hw.sensors.fins0.volt8=3.14 VDC (Vbat)
OpenBSD 4.4-current (GENERIC.MP) #51: Thu Feb 5 15:48:59 EST 2009
[email protected]:/usr/src/sys/arch/i386/compile/GENERIC.MP
cpu0: AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ ("AuthenticAMD" 686-class,
512KB L2 cache) 2.22 GHz
cpu0:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16
real mem = 3488968704 (3327MB)
avail mem = 3384877056 (3228MB)
mainbus0 at root
bios0 at mainbus0: AT/286+ BIOS, date 07/26/08, BIOS32 rev. 0 @ 0xf0010, SMBIOS
rev. 2.5 @ 0xfc2c0 (67 entries)
bios0: vendor American Megatrends Inc. version "080014" date 07/26/2008
bios0: FOXCONN RS690M2MA
acpi0 at bios0: rev 0
acpi0: tables DSDT FACP APIC MCFG OEMB HPET SSDT
acpi0: wakeup devices PCE2(S4) PCE3(S4) PCE4(S4) PCE5(S4) PCE6(S4) PCE7(S4)
SBAZ(S4) PS2K(S4) PS2M(S1) P0PC(S4) WOL_(S4) AC97(S4) MC97(S4) USB1(S1)
USB2(S1) USB3(S1) USB4(S1) USB5(S1) EUSB(S1) PWRB(S4)
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: apic clock running at 200MHz
cpu1 at mainbus0: apid 1 (application processor)
cpu1: AMD Athlon(tm) 64 X2 Dual Core Processor 4200+ ("AuthenticAMD" 686-class,
512KB L2 cache) 2.21 GHz
cpu1:
FPU,V86,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,MMX,FXSR,SSE,SSE2,HTT,SSE3,CX16
ioapic0 at mainbus0: apid 2 pa 0xfec00000, version 21, 24 pins
acpihpet0 at acpi0: 14318180 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpiprt1 at acpi0: bus -1 (P0P1)
acpiprt2 at acpi0: bus 1 (PCE2)
acpiprt3 at acpi0: bus -1 (PCE3)
acpiprt4 at acpi0: bus -1 (PCE4)
acpiprt5 at acpi0: bus -1 (PCE5)
acpiprt6 at acpi0: bus -1 (PCE6)
acpiprt7 at acpi0: bus -1 (PCE7)
acpiprt8 at acpi0: bus 2 (P0PC)
acpicpu0 at acpi0: PSS
acpicpu1 at acpi0: PSS
acpibtn0 at acpi0: PWRB
bios0: ROM list: 0xc0000/0xf000
cpu0: PowerNow! K8 2210 MHz: speeds: 2200 2000 1800 1000 MHz
pci0 at mainbus0 bus 0: configuration mode 1 (bios)
pchb0 at pci0 dev 0 function 0 "ATI RS690 Host" rev 0x00
ppb0 at pci0 dev 2 function 0 "ATI RS690M PCIE" rev 0x00
pci1 at ppb0 bus 1
vga1 at pci1 dev 0 function 0 vendor "ATI", unknown product 0x9490 rev 0x00
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
azalia0 at pci1 dev 0 function 1 vendor "ATI", unknown product 0xaa38 rev 0x00:
apic 2 int 19 (irq 10)
azalia0: codecs: ATI/0xaa01
audio0 at azalia0
ahci0 at pci0 dev 18 function 0 "ATI SB600 SATA" rev 0x00: apic 2 int 22 (irq
11), AHCI 1.1
scsibus0 at ahci0: 32 targets, initiator 32
sd0 at scsibus0 targ 0 lun 0: <ATA, ST3160815AS, 3.AA> SCSI3 0/direct fixed
sd0: 152627MB, 512 bytes/sec, 312581808 sec total
ohci0 at pci0 dev 19 function 0 "ATI SB600 USB" rev 0x00: apic 2 int 16 (irq
5), version 1.0, legacy support
ohci1 at pci0 dev 19 function 1 "ATI SB600 USB" rev 0x00: apic 2 int 17 (irq
15), version 1.0, legacy support
ohci2 at pci0 dev 19 function 2 "ATI SB600 USB" rev 0x00: apic 2 int 18 (irq
10), version 1.0, legacy support
ohci3 at pci0 dev 19 function 3 "ATI SB600 USB" rev 0x00: apic 2 int 17 (irq
15), version 1.0, legacy support
ohci4 at pci0 dev 19 function 4 "ATI SB600 USB" rev 0x00: apic 2 int 18 (irq
10), version 1.0, legacy support
ehci0 at pci0 dev 19 function 5 "ATI SB600 USB2" rev 0x00: apic 2 int 19 (irq
10)
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 "ATI EHCI root hub" rev 2.00/1.00 addr 1
piixpm0 at pci0 dev 20 function 0 "ATI SBx00 SMBus" rev 0x14: SMI
iic0 at piixpm0
iic0: addr 0x2f 01=33 02=30 03=33 04=30 05=33 06=33 07=33 08=33 09=38 0a=38
0b=ab 0c=98 11=70 12=40 5a=05 5b=10 5c=10 5d=19 5e=34 f0=20 f1=20 f2=02 fa=00
ff=5e words 00=ffff 01=33ff 02=30ff 03=33ff 04=30ff 05=33ff 06=33ff 07=33ff
spdmem0 at iic0 addr 0x50: 2GB DDR2 SDRAM non-parity PC2-6400CL5
spdmem1 at iic0 addr 0x51: 2GB DDR2 SDRAM non-parity PC2-6400CL5
spdmem2 at iic0 addr 0x52: 2GB DDR2 SDRAM non-parity PC2-6400CL5
spdmem3 at iic0 addr 0x53: 2GB DDR2 SDRAM non-parity PC2-6400CL5
pciide0 at pci0 dev 20 function 1 "ATI SB600 IDE" rev 0x00: DMA, channel 0
configured to compatibility, channel 1 configured to compatibility
atapiscsi0 at pciide0 channel 0 drive 0
scsibus1 at atapiscsi0: 2 targets, initiator 7
cd0 at scsibus1 targ 0 lun 0: <SONY, CD-RW CRX215E1, SYS2> ATAPI 5/cdrom
removable
cd0(pciide0:0:0): using PIO mode 4, DMA mode 2, Ultra-DMA mode 2
azalia1 at pci0 dev 20 function 2 "ATI SBx00 HD Audio" rev 0x00: apic 2 int 16
(irq 5)
azalia1: codecs: Realtek ALC883
audio1 at azalia1
pcib0 at pci0 dev 20 function 3 "ATI SB600 ISA" rev 0x00
ppb1 at pci0 dev 20 function 4 "ATI SB600 PCI" rev 0x00
pci2 at ppb1 bus 2
re0 at pci2 dev 4 function 0 "Realtek 8169SC" rev 0x10: RTL8169/8110SCd
(0x1800), apic 2 int 23 (irq 5), address 00:1c:25:6c:67:ea
rgephy0 at re0 phy 7: RTL8169S/8110S PHY, rev. 2
pchb1 at pci0 dev 24 function 0 "AMD AMD64 0Fh HyperTransport" rev 0x00
pchb2 at pci0 dev 24 function 1 "AMD AMD64 0Fh Address Map" rev 0x00
pchb3 at pci0 dev 24 function 2 "AMD AMD64 0Fh DRAM Cfg" rev 0x00
kate0 at pci0 dev 24 function 3 "AMD AMD64 0Fh Misc Cfg" rev 0x00: core rev
BH-G2
usb1 at ohci0: USB revision 1.0
uhub1 at usb1 "ATI OHCI root hub" rev 1.00/1.00 addr 1
usb2 at ohci1: USB revision 1.0
uhub2 at usb2 "ATI OHCI root hub" rev 1.00/1.00 addr 1
usb3 at ohci2: USB revision 1.0
uhub3 at usb3 "ATI OHCI root hub" rev 1.00/1.00 addr 1
usb4 at ohci3: USB revision 1.0
uhub4 at usb4 "ATI OHCI root hub" rev 1.00/1.00 addr 1
usb5 at ohci4: USB revision 1.0
uhub5 at usb5 "ATI OHCI root hub" rev 1.00/1.00 addr 1
isa0 at pcib0
isadma0 at isa0
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: probed fifo depth: 15 bytes
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo
com1: probed fifo depth: 15 bytes
pckbc0 at isa0 port 0x60/5
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
midi0 at pcppi0: <PC speaker>
spkr0 at pcppi0
lpt0 at isa0 port 0x378/4 irq 7
fins0 at isa0 port 0x2e/2
npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
mtrr: Pentium Pro MTRR support
uhub6 at uhub2 port 1 "Chicony USB HUB with TrackPoint USB Keyboard" rev
1.10/1.23 addr 2
uhidev0 at uhub6 port 1 configuration 1 interface 0 "Chicony USB TrackPoint
Keyboard" rev 1.10/1.23 addr 3
uhidev0: iclass 3/1
ukbd0 at uhidev0: 8 modifier keys, 6 key codes
wskbd1 at ukbd0 mux 1
wskbd1: connecting to wsdisplay0
uhidev1 at uhub6 port 1 configuration 1 interface 1 "Chicony USB TrackPoint
Keyboard" rev 1.10/1.23 addr 3
uhidev1: iclass 3/0, 3 report ids
uhid0 at uhidev1 reportid 1: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 2: input=1, output=0, feature=0
uhid2 at uhidev1 reportid 3: input=3, output=1, feature=0
uhidev2 at uhub6 port 2 configuration 1 interface 0 "Chicony USB Trackpoint
pointing device" rev 1.10/1.2c addr 4
uhidev2: iclass 3/1
ums0 at uhidev2: 3 buttons, Z dir
wsmouse0 at ums0 mux 0
uhidev3 at uhub6 port 4 configuration 1 interface 0 "Microsoft Microsoft
5-Button Mouse with IntelliEye(TM)" rev 1.10/3.00 addr 5
uhidev3: iclass 3/1
ums1 at uhidev3: 5 buttons, Z dir
wsmouse1 at ums1 mux 0
softraid0 at root
root on sd0a swap on sd0b dump on sd0b
Index: fins.c
===================================================================
RCS file: /cvs/src/sys/dev/isa/fins.c,v
retrieving revision 1.1
diff -u -r1.1 fins.c
--- fins.c 19 Mar 2008 19:33:09 -0000 1.1
+++ fins.c 5 Feb 2009 21:05:37 -0000
@@ -46,30 +46,44 @@
* This section of the chip controls the fans. We don't do anything to them.
*/
-
#define FINS_UNLOCK 0x87 /* magic constant - write 2x to select chip */
#define FINS_LOCK 0xaa /* magic constant - write 1x to deselect reg */
-#define FINS_FUNC_SEL 0x07 /* select which subchip to access */
-# define FINS_FUNC_SENSORS 0x4
-
/* ISA registers index to an internal register space on chip */
#define FINS_ADDR 0x00
#define FINS_DATA 0x01
-/* Chip identification regs and values in bank 0 */
-#define FINS_MANUF 0x23 /* manufacturer ID */
-# define FINTEK_ID 0x1934
+#define FINS_FUNC_SEL 0x07 /* select which chip function to access */
#define FINS_CHIP 0x20 /* chip ID */
-# define FINS_ID 0x0406
-
-/* in bank sensors of config space */
-#define FINS_SENSADDR 0x60 /* sensors assigned I/O address (2 bytes) */
+#define FINS_MANUF 0x23 /* manufacturer ID */
+#define FINS_BASEADDR 0x60 /* I/O base of chip function */
-/* in sensors space */
-#define FINS_TMODE 0x01 /* temperature mode reg */
+#define FINS_71806 0x0341 /* same as F71872 */
+#define FINS_71805 0x0406
+#define FINS_71882 0x0541 /* same as F71883 */
+#define FINS_71862 0x0601 /* same as F71863 */
+#define FINTEK_ID 0x1934
+
+#define FINS_FUNC_SENSORS 0x04
+#define FINS_FUNC_WATCHDOG 0x07
+
+/* sensors device registers */
+#define FINS_SENS_TMODE(sc) ((sc)->fins_chipid <= FINS_71805 ? 0x01 : 0x6b)
+#define FINS_SENS_VDIVS 0x0e
+
+/* watchdog device registers (mapped straight to i/o port offsets) */
+#define FINS_WDOG_CR0 0x00
+#define FINS_WDOG_CR1 0x05
+#define FINS_WDOG_TIMER 0x06
+
+/* CR0 flags */
+#define FINS_WDOG_OUTEN 0x80
+
+/* CR1 flags */
+#define FINS_WDOG_EN 0x20
+#define FINS_WDOG_MINS 0x08
-#define FINS_MAX_SENSORS 20
+#define FINS_MAX_SENSORS 18
/*
* Fintek chips typically measure voltages using 8mv steps.
* To measure higher voltages the input is attenuated with (external)
@@ -81,21 +95,14 @@
#define FRFACT(x, y) (FRFACT_NONE * ((x) + (y)) / (y))
#define FNRFACT(x, y) (-FRFACT_NONE * (x) / (y))
-#if defined(FINSDEBUG)
-#define DPRINTF(x) do { printf x; } while (0)
-#else
-#define DPRINTF(x)
-#endif
-
struct fins_softc;
struct fins_sensor {
char *fs_desc;
+ void (*fs_refresh)(struct fins_softc *, int);
enum sensor_type fs_type;
- u_int8_t fs_aux;
+ int fs_aux;
u_int8_t fs_reg;
- void (*fs_refresh)(struct fins_softc *, int);
- int fs_rfact;
};
struct fins_softc {
@@ -105,227 +112,295 @@
struct ksensordev fins_sensordev;
struct sensor_task *fins_sensortask;
struct fins_sensor *fins_sensors;
- u_int fins_numsensors;
- void (*refresh_sensor_data) (struct fins_softc *);
- u_int8_t (*fins_readreg)(struct fins_softc *, int);
- void (*fins_writereg)(struct fins_softc *, int, int);
- u_int fins_tempsel;
+ bus_space_handle_t sc_ioh_sens;
+ bus_space_handle_t sc_ioh_wdog;
+ bus_space_tag_t sc_iot;
+
+ u_int16_t fins_chipid;
+ u_int8_t fins_tempsel;
+ u_int8_t fins_wdog_cr;
};
+int fins_match(struct device *, void *, void *);
+void fins_attach(struct device *, struct device *, void *);
-struct fins_isa_softc {
- struct fins_softc sc_finssc;
+void fins_unlock(bus_space_tag_t, bus_space_handle_t);
+void fins_lock(bus_space_tag_t, bus_space_handle_t);
- bus_space_tag_t sc_iot;
- bus_space_handle_t sc_ioh;
-};
+u_int8_t fins_read(bus_space_tag_t, bus_space_handle_t, int);
+u_int16_t fins_read_2(bus_space_tag_t, bus_space_handle_t, int);
+void fins_write(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
+
+static __inline u_int8_t fins_read_sens(struct fins_softc *, int);
+static __inline u_int16_t fins_read_sens_2(struct fins_softc *, int);
-int fins_isa_match(struct device *, void *, void *);
-void fins_isa_attach(struct device *, struct device *, void *);
-u_int8_t fins_isa_readreg(struct fins_softc *, int);
-void fins_isa_writereg(struct fins_softc *, int, int);
+static __inline u_int8_t fins_read_wdog(struct fins_softc *, int);
+static __inline void fins_write_wdog(struct fins_softc *, int, u_int8_t);
void fins_setup_sensors(struct fins_softc *, struct fins_sensor *);
void fins_refresh(void *);
-void fins_refresh_volt(struct fins_softc *, int);
-void fins_refresh_temp(struct fins_softc *, int);
-void fins_refresh_offset(struct fins_softc *, int);
-void fins_refresh_fanrpm(struct fins_softc *, int);
-void fins_attach(struct fins_softc *);
-int fins_detach(struct fins_softc *);
+void fins_get_rpm(struct fins_softc *, int);
+void fins_get_temp(struct fins_softc *, int);
+void fins_get_volt(struct fins_softc *, int);
+
+int fins_wdog_cb(void *, int);
struct cfattach fins_ca = {
- sizeof(struct fins_isa_softc),
- fins_isa_match,
- fins_isa_attach
+ sizeof(struct fins_softc),
+ fins_match,
+ fins_attach
};
struct cfdriver fins_cd = {
NULL, "fins", DV_DULL
};
-struct fins_sensor fins_sensors[] = {
- /* Voltage */
- { "+3.3V", SENSOR_VOLTS_DC, 0, 0x10, fins_refresh_volt, FRFACT(100,
100) },
- { "Vtt", SENSOR_VOLTS_DC, 0, 0x11, fins_refresh_volt, FRFACT_NONE },
- { "Vram", SENSOR_VOLTS_DC, 0, 0x12, fins_refresh_volt, FRFACT(100, 100)
},
- { "Vchips", SENSOR_VOLTS_DC, 0, 0x13, fins_refresh_volt, FRFACT(47,
100) },
- { "+5V", SENSOR_VOLTS_DC, 0, 0x14, fins_refresh_volt, FRFACT(200, 47) },
- { "+12V", SENSOR_VOLTS_DC, 0, 0x15, fins_refresh_volt, FRFACT(200, 20)
},
- { "Vcc 1.5V", SENSOR_VOLTS_DC, 0, 0x16, fins_refresh_volt, FRFACT_NONE
},
- { "VCore", SENSOR_VOLTS_DC, 0, 0x17, fins_refresh_volt, FRFACT_NONE },
- { "Vsb", SENSOR_VOLTS_DC, 0, 0x18, fins_refresh_volt, FRFACT(200, 47) },
- { "Vsbint", SENSOR_VOLTS_DC, 0, 0x19, fins_refresh_volt, FRFACT(200,
47) },
- { "Vbat", SENSOR_VOLTS_DC, 0, 0x1A, fins_refresh_volt, FRFACT(200, 47)
},
-
- /* Temperature */
- { "Temp1", SENSOR_TEMP, 0x01, 0x1B, fins_refresh_temp },
- { "Temp2", SENSOR_TEMP, 0x02, 0x1C, fins_refresh_temp },
- { "Temp3", SENSOR_TEMP, 0x04, 0x1D, fins_refresh_temp },
-
- /* Fans */
- { "Fan1", SENSOR_FANRPM, 0, 0x20, fins_refresh_fanrpm },
- { "Fan2", SENSOR_FANRPM, 0, 0x22, fins_refresh_fanrpm },
- { "Fan3", SENSOR_FANRPM, 0, 0x24, fins_refresh_fanrpm },
+struct fins_sensor fins_71805_sensors[] = {
+ { "+3.3V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x10 },
+ { "Vtt", fins_get_volt, SENSOR_VOLTS_DC, FRFACT_NONE, 0x11 },
+ { "Vram", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x12 },
+ { "Vchips", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(47, 100), 0x13 },
+ { "+5V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 47), 0x14 },
+ { "+12V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 20), 0x15 },
+ { "+1.5V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT_NONE, 0x16 },
+ { "Vcore", fins_get_volt, SENSOR_VOLTS_DC, FRFACT_NONE, 0x17 },
+ { "Vsb", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 47), 0x18 },
+ { "Vsbint", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 47), 0x19 },
+ { "Vbat", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 47), 0x1a },
+
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x01, 0x1b },
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x02, 0x1c },
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x04, 0x1d },
+
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0x20 },
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0x22 },
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0x24 },
{ NULL }
};
+struct fins_sensor fins_71882_sensors[] = {
+ { "+3.3V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x20 },
+ { "Vcore", fins_get_volt, SENSOR_VOLTS_DC, FRFACT_NONE, 0x21 },
+ { "Vram", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x22 },
+ { "Vchips", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(47, 100), 0x23 },
+ { "+5V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 47), 0x24 },
+ { "+12V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(200, 20), 0x25 },
+ { "+1.5V", fins_get_volt, SENSOR_VOLTS_DC, FRFACT_NONE, 0x26 },
+ { "Vsb", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x27 },
+ { "Vbat", fins_get_volt, SENSOR_VOLTS_DC, FRFACT(100, 100), 0x28 },
+
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x02, 0x72 },
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x04, 0x74 },
+ { NULL, fins_get_temp, SENSOR_TEMP, 0x08, 0x76 },
+
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0xa0 },
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0xb0 },
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0xc0 },
+ { NULL, fins_get_rpm, SENSOR_FANRPM, 0, 0xd0 },
+
+ { NULL }
+};
int
-fins_isa_match(struct device *parent, void *match, void *aux)
+fins_match(struct device *parent, void *match, void *aux)
{
- bus_space_tag_t iot;
- bus_addr_t iobase;
- bus_space_handle_t ioh;
struct isa_attach_args *ia = aux;
- u_int val;
+ bus_space_handle_t ioh;
+ bus_space_tag_t iot;
+ int ret = 0;
+ u_int16_t id;
iot = ia->ia_iot;
- iobase = ia->ipa_io[0].base;
-
- if (bus_space_map(iot, iobase, 2, 0, &ioh))
+ if (bus_space_map(iot, ia->ipa_io[0].base, 2, 0, &ioh))
return (0);
/* Fintek uses magic cookie locks to distinguish their chips */
- bus_space_write_1(iot, ioh, 0, FINS_UNLOCK);
- bus_space_write_1(iot, ioh, 0, FINS_UNLOCK);
- bus_space_write_1(iot, ioh, 0, FINS_FUNC_SEL);
- bus_space_write_1(iot, ioh, 1, 0); /* IDs appear only in space 0 */
- bus_space_write_1(iot, ioh, 0, FINS_MANUF);
- val = bus_space_read_1(iot, ioh, 1) << 8;
- bus_space_write_1(iot, ioh, 0, FINS_MANUF + 1);
- val |= bus_space_read_1(iot, ioh, 1);
- if (val != FINTEK_ID) {
- bus_space_write_1(iot, ioh, 0, FINS_LOCK);
- goto notfound;
- }
- bus_space_write_1(iot, ioh, 0, FINS_CHIP);
- val = bus_space_read_1(iot, ioh, 1) << 8;
- bus_space_write_1(iot, ioh, 0, FINS_CHIP + 1);
- val |= bus_space_read_1(iot, ioh, 1);
- /* If we cared which Fintek chip this was we would save the chip ID
here */
- if (val != FINS_ID) {
- bus_space_write_1(iot, ioh, 0, FINS_LOCK);
- goto notfound;
- }
- /* select sensor function of the chip */
- bus_space_write_1(iot, ioh, FINS_ADDR, FINS_FUNC_SEL);
- bus_space_write_1(iot, ioh, FINS_DATA, FINS_FUNC_SENSORS);
- /* read I/O address assigned by BIOS to this function */
- bus_space_write_1(iot, ioh, FINS_ADDR, FINS_SENSADDR);
- val = bus_space_read_1(iot, ioh, FINS_DATA) << 8;
- bus_space_write_1(iot, ioh, FINS_ADDR, FINS_SENSADDR + 1);
- val |= bus_space_read_1(iot, ioh, FINS_DATA);
- bus_space_write_1(iot, ioh, 0, FINS_LOCK);
- ia->ipa_io[1].length = 2;
- ia->ipa_io[1].base = val;
+ fins_unlock(iot, ioh);
- bus_space_unmap(iot, ioh, 2);
- ia->ipa_nio = 2;
- ia->ipa_io[0].length = 2;
- ia->ipa_nmem = 0;
- ia->ipa_nirq = 0;
- ia->ipa_ndrq = 0;
- return (1);
-
- notfound:
- bus_space_unmap(iot, ioh, 2);
- return (0);
+ fins_write(iot, ioh, FINS_FUNC_SEL, 0); /* IDs appear only in space 0 */
+ if (fins_read_2(iot, ioh, FINS_MANUF) != FINTEK_ID)
+ goto match_done;
+ id = fins_read_2(iot, ioh, FINS_CHIP);
+ switch(id) {
+ case FINS_71882:
+ case FINS_71862:
+ ia->ipa_nio = 3;
+ fins_write(iot, ioh, FINS_FUNC_SEL, FINS_FUNC_WATCHDOG);
+ ia->ipa_io[2].base = fins_read_2(iot, ioh, FINS_BASEADDR);
+ ia->ipa_io[2].length = 8;
+ fins_write(iot, ioh, FINS_FUNC_SEL, FINS_FUNC_SENSORS);
+ ia->ipa_io[1].base = fins_read_2(iot, ioh, FINS_BASEADDR);
+ ia->ipa_io[1].base += 5;
+ break;
+ case FINS_71806:
+ case FINS_71805:
+ ia->ipa_nio = 2;
+ fins_write(iot, ioh, FINS_FUNC_SEL, FINS_FUNC_SENSORS);
+ ia->ipa_io[1].base = fins_read_2(iot, ioh, FINS_BASEADDR);
+ break;
+ default:
+ goto match_done;
+ }
+ ia->ipa_io[0].length = ia->ipa_io[1].length = 2;
+ ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0;
+ ia->ia_aux = (void *)(u_long)id;
+ ret = 1;
+match_done:
+ fins_lock(iot, ioh);
+ return (ret);
}
void
-fins_isa_attach(struct device *parent, struct device *self, void *aux)
+fins_attach(struct device *parent, struct device *self, void *aux)
{
- struct fins_isa_softc *sc = (struct fins_isa_softc *)self;
+ struct fins_softc *sc = (struct fins_softc *)self;
struct isa_attach_args *ia = aux;
bus_addr_t iobase;
+ u_int32_t iosize;
+ u_int i;
sc->sc_iot = ia->ia_iot;
+ sc->fins_chipid = (u_int16_t)(u_long)ia->ia_aux;
iobase = ia->ipa_io[1].base;
- sc->sc_finssc.fins_writereg = fins_isa_writereg;
- sc->sc_finssc.fins_readreg = fins_isa_readreg;
- if (bus_space_map(sc->sc_iot, iobase, 2, 0, &sc->sc_ioh)) {
- printf(": can't map i/o space\n");
+ iosize = ia->ipa_io[1].length;
+ if (bus_space_map(sc->sc_iot, iobase, iosize, 0, &sc->sc_ioh_sens)) {
+ printf(": can't map sensor i/o space\n");
+ return;
+ }
+ switch(sc->fins_chipid) {
+ case FINS_71882:
+ case FINS_71862:
+ fins_setup_sensors(sc, fins_71882_sensors);
+ break;
+ case FINS_71806:
+ case FINS_71805:
+ fins_setup_sensors(sc, fins_71805_sensors);
+ break;
+ }
+ sc->fins_sensortask = sensor_task_register(sc, fins_refresh, 5);
+ if (sc->fins_sensortask == NULL) {
+ printf(": can't register update task\n");
+ return;
+ }
+ for (i = 0; sc->fins_sensors[i].fs_refresh != NULL; ++i)
+ sensor_attach(&sc->fins_sensordev, &sc->fins_ksensors[i]);
+ sensordev_install(&sc->fins_sensordev);
+
+ if (sc->fins_chipid <= FINS_71805)
+ goto attach_done;
+ iobase = ia->ipa_io[2].base;
+ iosize = ia->ipa_io[2].length;
+ if (bus_space_map(sc->sc_iot, iobase, iosize, 0, &sc->sc_ioh_wdog)) {
+ printf(": can't map watchdog i/o space\n");
return;
}
- fins_attach(&sc->sc_finssc);
+ sc->fins_wdog_cr = fins_read_wdog(sc, FINS_WDOG_CR1);
+ sc->fins_wdog_cr &= ~(FINS_WDOG_MINS | FINS_WDOG_EN);
+ fins_write_wdog(sc, FINS_WDOG_CR1, sc->fins_wdog_cr);
+ wdog_register(sc, fins_wdog_cb);
+attach_done:
+ printf("\n");
}
u_int8_t
-fins_isa_readreg(struct fins_softc *lmsc, int reg)
+fins_read(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
{
- struct fins_isa_softc *sc = (struct fins_isa_softc *)lmsc;
-
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, FINS_ADDR, reg);
- return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, FINS_DATA));
+ bus_space_write_1(iot, ioh, FINS_ADDR, reg);
+ return (bus_space_read_1(iot, ioh, FINS_DATA));
}
-void
-fins_isa_writereg(struct fins_softc *lmsc, int reg, int val)
+u_int16_t
+fins_read_2(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
{
- struct fins_isa_softc *sc = (struct fins_isa_softc *)lmsc;
+ u_int16_t val;
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, FINS_ADDR, reg);
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, FINS_DATA, val);
+ bus_space_write_1(iot, ioh, FINS_ADDR, reg);
+ val = bus_space_read_1(iot, ioh, FINS_DATA) << 8;
+ bus_space_write_1(iot, ioh, FINS_ADDR, reg + 1);
+ return (val | bus_space_read_1(iot, ioh, FINS_DATA));
}
void
-fins_attach(struct fins_softc *sc)
+fins_write(bus_space_tag_t iot, bus_space_handle_t ioh, int reg, u_int8_t val)
{
- u_int i;
-
- fins_setup_sensors(sc, fins_sensors);
- sc->fins_sensortask = sensor_task_register(sc, fins_refresh, 5);
- if (sc->fins_sensortask == NULL) {
- printf(": unable to register update task\n");
- return;
- }
+ bus_space_write_1(iot, ioh, FINS_ADDR, reg);
+ bus_space_write_1(iot, ioh, FINS_DATA, val);
+}
- printf("\n");
- /* Add sensors */
- for (i = 0; i < sc->fins_numsensors; ++i)
- sensor_attach(&sc->fins_sensordev, &sc->fins_ksensors[i]);
- sensordev_install(&sc->fins_sensordev);
+static __inline u_int8_t
+fins_read_sens(struct fins_softc *sc, int reg)
+{
+ return (fins_read(sc->sc_iot, sc->sc_ioh_sens, reg));
}
-int
-fins_detach(struct fins_softc *sc)
+static __inline u_int16_t
+fins_read_sens_2(struct fins_softc *sc, int reg)
{
- int i;
+ return (fins_read_2(sc->sc_iot, sc->sc_ioh_sens, reg));
+}
- /* Remove sensors */
- sensordev_deinstall(&sc->fins_sensordev);
- for (i = 0; i < sc->fins_numsensors; i++)
- sensor_detach(&sc->fins_sensordev, &sc->fins_ksensors[i]);
+static __inline u_int8_t
+fins_read_wdog(struct fins_softc *sc, int reg)
+{
+ return (bus_space_read_1(sc->sc_iot, sc->sc_ioh_wdog, reg));
+}
- if (sc->fins_sensortask != NULL)
- sensor_task_unregister(sc->fins_sensortask);
+static __inline void
+fins_write_wdog(struct fins_softc *sc, int reg, u_int8_t val)
+{
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh_wdog, reg, val);
+}
- return 0;
+void
+fins_unlock(bus_space_tag_t iot, bus_space_handle_t ioh)
+{
+ bus_space_write_1(iot, ioh, 0, FINS_UNLOCK);
+ bus_space_write_1(iot, ioh, 0, FINS_UNLOCK);
}
+void
+fins_lock(bus_space_tag_t iot, bus_space_handle_t ioh)
+{
+ bus_space_write_1(iot, ioh, 0, FINS_LOCK);
+ bus_space_unmap(iot, ioh, 2);
+}
void
fins_setup_sensors(struct fins_softc *sc, struct fins_sensor *sensors)
{
int i;
- struct ksensor *ksensor = sc->fins_ksensors;
+ for (i = 0; sensors[i].fs_refresh != NULL; ++i) {
+ sc->fins_ksensors[i].type = sensors[i].fs_type;
+ if (sensors[i].fs_desc != NULL)
+ strlcpy(sc->fins_ksensors[i].desc, sensors[i].fs_desc,
+ sizeof(sc->fins_ksensors[i].desc));
+ }
strlcpy(sc->fins_sensordev.xname, sc->sc_dev.dv_xname,
- sizeof(sc->fins_sensordev.xname));
+ sizeof(sc->fins_sensordev.xname));
+ sc->fins_sensors = sensors;
+ sc->fins_tempsel = fins_read_sens(sc, FINS_SENS_TMODE(sc));
+}
+
+#if 0
+void
+fins_get_dividers(struct fins_softc *sc)
+{
+ int i, p, m;
+ u_int16_t r = fins_read_sens_2(sc, FINS_SENS_VDIVS);
- for (i = 0; sensors[i].fs_desc; i++) {
- ksensor[i].type = sensors[i].fs_type;
- strlcpy(ksensor[i].desc, sensors[i].fs_desc,
- sizeof(ksensor[i].desc));
+ for (i = 0; i < 6; ++i) {
+ p = (i < 4) ? i : i + 2;
+ m = (r & (0x03 << p)) >> p;
+ if (m == 3)
+ m = 4;
+ fins_71882_sensors[i + 1].fs_aux = FRFACT_NONE << m;
}
- sc->fins_numsensors = i;
- sc->fins_sensors = sensors;
- sc->fins_tempsel = sc->fins_readreg(sc, FINS_TMODE);
}
+#endif
void
fins_refresh(void *arg)
@@ -333,30 +408,30 @@
struct fins_softc *sc = arg;
int i;
- for (i = 0; i < sc->fins_numsensors; i++)
+ for (i = 0; sc->fins_sensors[i].fs_refresh != NULL; ++i)
sc->fins_sensors[i].fs_refresh(sc, i);
}
void
-fins_refresh_volt(struct fins_softc *sc, int n)
+fins_get_volt(struct fins_softc *sc, int n)
{
struct ksensor *sensor = &sc->fins_ksensors[n];
struct fins_sensor *fs = &sc->fins_sensors[n];
int data;
- data = sc->fins_readreg(sc, fs->fs_reg);
+ data = fins_read_sens(sc, fs->fs_reg);
if (data == 0xff || data == 0) {
sensor->flags |= SENSOR_FINVALID;
sensor->value = 0;
} else {
sensor->flags &= ~SENSOR_FINVALID;
- sensor->value = data * fs->fs_rfact;
+ sensor->value = data * fs->fs_aux;
}
}
/* The BIOS seems to add a fudge factor to the CPU temp of +5C */
void
-fins_refresh_temp(struct fins_softc *sc, int n)
+fins_get_temp(struct fins_softc *sc, int n)
{
struct ksensor *sensor = &sc->fins_ksensors[n];
struct fins_sensor *fs = &sc->fins_sensors[n];
@@ -369,7 +444,7 @@
* what kind of sensor is used.
* A disconnected sensor seems to read over 110 or so.
*/
- data = sc->fins_readreg(sc, fs->fs_reg) & 0xFF;
+ data = fins_read_sens(sc, fs->fs_reg);
max = (sc->fins_tempsel & fs->fs_aux) ? 111 : 128;
if (data == 0 || data >= max) { /* disconnected? */
sensor->flags |= SENSOR_FINVALID;
@@ -382,6 +457,7 @@
/* The chip holds a fudge factor for BJT sensors */
/* this is currently unused but might be reenabled */
+#if 0
void
fins_refresh_offset(struct fins_softc *sc, int n)
{
@@ -390,22 +466,21 @@
u_int data;
sensor->flags &= ~SENSOR_FINVALID;
- data = sc->fins_readreg(sc, fs->fs_reg);
+ data = fins_read_sens(sc, fs->fs_reg);
data |= ~0 * (data & 0x40); /* sign extend 7-bit value */
sensor->value = data * 1000000 + 273150000;
}
-
+#endif
/* fan speed appears to be a 12-bit number */
void
-fins_refresh_fanrpm(struct fins_softc *sc, int n)
+fins_get_rpm(struct fins_softc *sc, int n)
{
struct ksensor *sensor = &sc->fins_ksensors[n];
struct fins_sensor *fs = &sc->fins_sensors[n];
int data;
- data = sc->fins_readreg(sc, fs->fs_reg) << 8;
- data |= sc->fins_readreg(sc, fs->fs_reg + 1);
+ data = fins_read_sens_2(sc, fs->fs_reg);
if (data >= 0xfff) {
sensor->value = 0;
sensor->flags |= SENSOR_FINVALID;
@@ -413,4 +488,29 @@
sensor->value = 1500000 / data;
sensor->flags &= ~SENSOR_FINVALID;
}
+}
+
+int
+fins_wdog_cb(void *arg, int period)
+{
+ struct fins_softc *sc = arg;
+ u_int8_t cr0, cr1, t;
+
+ cr0 = fins_read_wdog(sc, FINS_WDOG_CR0) & ~FINS_WDOG_OUTEN;
+ fins_write_wdog(sc, FINS_WDOG_CR0, cr0);
+
+ cr1 = sc->fins_wdog_cr;
+ if (period > 0xff) {
+ cr1 |= FINS_WDOG_MINS;
+ t = (period + 59) / 60;
+ period = (int)t * 60;
+ } else if (period > 0)
+ t = period;
+ else
+ return (0);
+
+ fins_write_wdog(sc, FINS_WDOG_TIMER, t);
+ fins_write_wdog(sc, FINS_WDOG_CR0, cr0 | FINS_WDOG_OUTEN);
+ fins_write_wdog(sc, FINS_WDOG_CR1, cr1 | FINS_WDOG_EN);
+ return (period);
}