diff options
author | 2006-06-15 20:50:44 +0000 | |
---|---|---|
committer | 2006-06-15 20:50:44 +0000 | |
commit | c721882c3d1b8e314ddedafdf67edc6c93d97cf8 (patch) | |
tree | 1f26dc9eb599fc76d60149745a5af2725ee9aa88 | |
parent | Ricoh rtc support for armish, driver from netbsd. (diff) | |
download | wireguard-openbsd-c721882c3d1b8e314ddedafdf67edc6c93d97cf8.tar.xz wireguard-openbsd-c721882c3d1b8e314ddedafdf67edc6c93d97cf8.zip |
Fan controller for Thecus N2100, still needs more work, currently sets the
fan so it is running. The nice auto fan speed isn't working currently.
Also gives temperature sensors.
-rw-r--r-- | sys/arch/armish/conf/GENERIC | 3 | ||||
-rw-r--r-- | sys/arch/armish/conf/RAMDISK | 3 | ||||
-rw-r--r-- | sys/dev/i2c/files.i2c | 6 | ||||
-rw-r--r-- | sys/dev/i2c/fintek.c | 530 |
4 files changed, 539 insertions, 3 deletions
diff --git a/sys/arch/armish/conf/GENERIC b/sys/arch/armish/conf/GENERIC index e04a382e849..5aa8104ab38 100644 --- a/sys/arch/armish/conf/GENERIC +++ b/sys/arch/armish/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.5 2006/06/15 20:42:53 drahn Exp $ +# $OpenBSD: GENERIC,v 1.6 2006/06/15 20:50:44 drahn Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -46,6 +46,7 @@ iopiic* at iopxs? # I2C Controller Unit(s) iic0 at iopiic? iic1 at iopiic? ricohrtc0 at iic? addr 0x32 # Ricoh RTC +fintek0 at iic? # temp/fan controller #iopwdog* at iopxs? # Watchdog timer pci0 at iopxs? bus ? # PCI/PCI-X support diff --git a/sys/arch/armish/conf/RAMDISK b/sys/arch/armish/conf/RAMDISK index f600b9562cd..596d99f19c3 100644 --- a/sys/arch/armish/conf/RAMDISK +++ b/sys/arch/armish/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.5 2006/06/15 20:42:53 drahn Exp $ +# $OpenBSD: RAMDISK,v 1.6 2006/06/15 20:50:44 drahn Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -57,6 +57,7 @@ iopiic* at iopxs? # I2C Controller Unit(s) iic0 at iopiic? iic1 at iopiic? ricohrtc0 at iic? addr 0x32 # Ricoh RTC +fintek0 at iic? # temp/fan controller #iopwdog* at iopxs? # Watchdog timer pci0 at iopxs? bus ? # PCI/PCI-X support diff --git a/sys/dev/i2c/files.i2c b/sys/dev/i2c/files.i2c index 82dbff24bc8..7f225434141 100644 --- a/sys/dev/i2c/files.i2c +++ b/sys/dev/i2c/files.i2c @@ -1,4 +1,4 @@ -# $OpenBSD: files.i2c,v 1.34 2006/06/15 20:42:53 drahn Exp $ +# $OpenBSD: files.i2c,v 1.35 2006/06/15 20:50:44 drahn Exp $ # $NetBSD: files.i2c,v 1.3 2003/10/20 16:24:10 briggs Exp $ define i2c {[addr = -1], [size = -1]} @@ -113,3 +113,7 @@ device ricohrtc attach ricohrtc at i2c file dev/i2c/rs5c372.c ricohrtc +# Fintek F75375 +device fintek +attach fintek at i2c +file dev/i2c/fintek.c fintek diff --git a/sys/dev/i2c/fintek.c b/sys/dev/i2c/fintek.c new file mode 100644 index 00000000000..e3e3e76915a --- /dev/null +++ b/sys/dev/i2c/fintek.c @@ -0,0 +1,530 @@ +/* $OpenBSD: fintek.c,v 1.1 2006/06/15 20:50:44 drahn Exp $ */ +/* + * Copyright (c) 2006 Dale Rahn <drahn@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/sensors.h> + +#include <dev/i2c/i2cvar.h> + +/* Sensors */ +#define F_VCC 0 +#define F_V1 1 +#define F_V2 2 +#define F_V3 3 +#define F_TEMP1 4 +#define F_TEMP2 5 +#define F_FAN1 6 +#define F_FAN2 7 +#define F_NUM_SENSORS 8 + + +struct fintek_softc { + struct device sc_dev; + i2c_tag_t sc_tag; + i2c_addr_t sc_addr; + + struct sensor sc_sensor[F_NUM_SENSORS]; +}; + +int fintek_match(struct device *, void *, void *); +void fintek_attach(struct device *, struct device *, void *); + +void fintek_refresh(void *); + +int fintek_read_reg(struct fintek_softc *sc, u_int8_t cmd, u_int8_t *data, + size_t size); +int fintek_write_reg(struct fintek_softc *sc, u_int8_t cmd, u_int8_t *data, + size_t size); + +void fintek_setspeed(struct fintek_softc *sc); +void fintek_setauto(struct fintek_softc *sc); +void fintek_setpwm(struct fintek_softc *sc); + +struct cfattach fintek_ca = { + sizeof(struct fintek_softc), fintek_match, fintek_attach +}; + +struct cfdriver fintek_cd = { + NULL, "fintek", DV_DULL +}; + +#define FINTEK_VOLT0 0x10 +#define FINTEK_VOLT1 0x11 +#define FINTEK_VOLT2 0x12 +#define FINTEK_VOLT3 0x13 +#define FINTEK_TEMP1 0x14 +#define FINTEK_TEMP2 0x15 +#define FINTEK_FAN1 0x16 +#define FINTEK_FAN2 0x18 +#define FINTEK_VERSION 0x5c +#define FINTEK_RSTCR 0x60 + +int +fintek_match(struct device *parent, void *match, void *aux) +{ + struct i2c_attach_args *ia = aux; + + if (strcmp(ia->ia_name, "f75375") == 0) + return (1); + return (0); +} + +int +fintek_read_reg(struct fintek_softc *sc, u_int8_t cmd, u_int8_t *data, + size_t size) +{ + return iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, data, size, 0); +} +int +fintek_write_reg(struct fintek_softc *sc, u_int8_t cmd, u_int8_t *data, + size_t size) +{ + return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, data, size, 0); +} + +void +fintek_attach(struct device *parent, struct device *self, void *aux) +{ + struct fintek_softc *sc = (struct fintek_softc *)self; + struct i2c_attach_args *ia = aux; + u_int8_t cmd, data, data2; + int i; + + sc->sc_tag = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + iic_acquire_bus(sc->sc_tag, 0); + + cmd = FINTEK_VERSION; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + + + printf(": F75375 rev %d.%d", data>> 4, data & 0xf); + + + cmd = FINTEK_RSTCR; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; +#if 1 + data = 0x81; + cmd = 0; + if (fintek_write_reg(sc, cmd, &data, sizeof data)) + goto failwrite; + if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, + sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { + iic_release_bus(sc->sc_tag, 0); + printf(": cannot read ID register\n"); + return; + } +#endif + + +#ifdef NOISY_DEBUG + cmd = 0; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" conf 0 %x", data); + + cmd = 0x1; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" conf 1 %x", data); + + cmd = 0x2; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + + printf(" conf 2 %x", data); + cmd = 0x3; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" conf 3 %x\n", data); + cmd = 0x70; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0x71; + if (fintek_read_reg(sc, cmd, &data2, sizeof data2)) + goto failread; + printf(" fan full speed %x %x\n", data, data2); + + cmd = 0xa0; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" temp 1 b %x\n", data); + + cmd = 0xa1; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" temp 2 b %x\n", data); + + cmd = 0xa2; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" temp 3 b %x\n", data); + + cmd = 0xa3; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + printf(" temp 4 b %x\n", data); + + cmd = 0xa4; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0xa5; + if (fintek_read_reg(sc, cmd, &data2, sizeof data)) + goto failread; + printf(" sec1speed %x %x\n", data, data2); + + cmd = 0xa6; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0xa7; + if (fintek_read_reg(sc, cmd, &data2, sizeof data)) + goto failread; + printf(" sec2speed %x %x\n", data, data2); + + cmd = 0xa8; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0xa9; + if (fintek_read_reg(sc, cmd, &data2, sizeof data)) + goto failread; + printf(" sec3speed %x %x\n", data, data2); + + cmd = 0xaa; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0xab; + if (fintek_read_reg(sc, cmd, &data2, sizeof data)) + goto failread; + printf(" sec4speed %x %x\n", data, data2); + + cmd = 0xac; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) + goto failread; + cmd = 0xad; + if (fintek_read_reg(sc, cmd, &data2, sizeof data)) + goto failread; + printf(" sec5speed %x %x\n", data, data2); +#endif + +#if 0 + fintek_setpwm(sc); +#endif +#if 0 + fintek_setauto(sc); +#endif + data2 = data2; +#if 1 + fintek_setspeed(sc); +#endif + iic_release_bus(sc->sc_tag, 0); + +for (i = 0; i < F_NUM_SENSORS; i++) + strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensor[i].device)); + + sc->sc_sensor[F_VCC].type = SENSOR_VOLTS_DC; + strlcpy(sc->sc_sensor[F_VCC].desc, "VCC", + sizeof(sc->sc_sensor[F_VCC].desc)); + + sc->sc_sensor[F_V1].type = SENSOR_VOLTS_DC; + strlcpy(sc->sc_sensor[F_V1].desc, "Volt 1", + sizeof(sc->sc_sensor[F_V1].desc)); + + sc->sc_sensor[F_V2].type = SENSOR_VOLTS_DC; + strlcpy(sc->sc_sensor[F_V2].desc, "Volt 2", + sizeof(sc->sc_sensor[F_V2].desc)); + + sc->sc_sensor[F_V3].type = SENSOR_VOLTS_DC; + strlcpy(sc->sc_sensor[F_V3].desc, "Volt 3", + sizeof(sc->sc_sensor[F_V3].desc)); + + sc->sc_sensor[F_TEMP1].type = SENSOR_TEMP; + strlcpy(sc->sc_sensor[F_TEMP1].desc, "Temp 1", + sizeof(sc->sc_sensor[F_TEMP1].desc)); + + sc->sc_sensor[F_TEMP2].type = SENSOR_TEMP; + strlcpy(sc->sc_sensor[F_TEMP2].desc, "Temp 2", + sizeof(sc->sc_sensor[F_TEMP2].desc)); + + sc->sc_sensor[F_FAN1].type = SENSOR_FANRPM; + strlcpy(sc->sc_sensor[F_FAN1].desc, "FAN1", + sizeof(sc->sc_sensor[F_FAN1].desc)); + + sc->sc_sensor[F_FAN2].type = SENSOR_FANRPM; + strlcpy(sc->sc_sensor[F_FAN2].desc, "FAN1", + sizeof(sc->sc_sensor[F_FAN2].desc)); + + if (sensor_task_register(sc, fintek_refresh, 5)) { + printf(", unable to register update task\n"); + return; + } + + for (i = 0; i < F_NUM_SENSORS; i++) { + sc->sc_sensor[i].flags &= ~SENSOR_FINVALID; + sensor_add(&sc->sc_sensor[i]); + } + return; + +failread: + printf("unable to read reg %d\n", cmd); + iic_release_bus(sc->sc_tag, 0); + return; +#if 1 +failwrite: + printf("unable to write reg %d\n", cmd); + iic_release_bus(sc->sc_tag, 0); +#endif +} + + +struct { + char sensor; + u_int8_t cmd; +} fintek_worklist[] = { + { F_VCC, FINTEK_VOLT0 }, + { F_V1, FINTEK_VOLT1 }, + { F_V2, FINTEK_VOLT2 }, + { F_V3, FINTEK_VOLT3 }, + { F_TEMP1, FINTEK_TEMP1 }, + { F_TEMP2, FINTEK_TEMP2 }, + { F_FAN1, FINTEK_FAN1 }, + { F_FAN2, FINTEK_FAN2 } +}; +#define FINTEK_WORKLIST_SZ (sizeof fintek_worklist/sizeof(fintek_worklist[0])) + +void +fintek_refresh(void *arg) +{ + struct fintek_softc *sc = arg; + u_int8_t cmd, data, data2; + int i; + + iic_acquire_bus(sc->sc_tag, 0); + + for (i = 0; i < FINTEK_WORKLIST_SZ; i++){ + cmd = fintek_worklist[i].cmd; + if (fintek_read_reg(sc, cmd, &data, sizeof data)) { + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + continue; + } + sc->sc_sensor[i].flags &= ~SENSOR_FINVALID; + switch (fintek_worklist[i].sensor) { + case F_VCC: + /* FALLTHROUGH */ + case F_V1: + /* FALLTHROUGH */ + case F_V2: + /* FALLTHROUGH */ + case F_V3: + sc->sc_sensor[i].value = 1000 * (data*8); + break; + case F_TEMP1: + /* FALLTHROUGH */ + case F_TEMP2: + sc->sc_sensor[i].value = 273150000 + 1000000 * (data); + break; + case F_FAN1: + /* FALLTHROUGH */ + case F_FAN2: + /* FANxLSB follows FANxMSB */ + cmd = fintek_worklist[i].cmd + 1; + if (fintek_read_reg(sc, cmd, &data2, sizeof data2)) { + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + continue; + } +// printf("fan speed %x: %x %x\n", fintek_worklist[i].cmd, +// data, data2); + if ((data == 0xff && data2 == 0xff) || + (data == 0 && data2 == 0)) + sc->sc_sensor[i].value = 0; + else + sc->sc_sensor[i].value = 1500000/ + (data << 8 | data2); + { + extern long hostid; + static long currentspeed; + int i; + if (currentspeed != hostid) { + currentspeed = hostid; + printf("setting speed to %d\n", hostid); + +#if 0 + data = hostid & 0xff; + cmd = 0x76; + fintek_write_reg(sc, cmd, &data, + sizeof data); +#else + cmd = 0x6d; + fintek_read_reg(sc, cmd, &data, + sizeof data); + printf("reg 6d contains %x setting to 0x11\n", data); + fintek_write_reg(sc, cmd, &data, + sizeof data); + i = hostid ; /* desired value */ + cmd = 0x74; + data = i >> 8; + fintek_write_reg(sc, cmd, &data, + sizeof data); + + cmd = 0x75; + data = i & 0xff; + fintek_write_reg(sc, cmd, &data, + sizeof data); +#endif + } + } + break; + default: + sc->sc_sensor[i].flags |= SENSOR_FINVALID; + break; + } + } + + iic_release_bus(sc->sc_tag, 0); +} +void +fintek_setspeed(struct fintek_softc *sc) +{ + u_int8_t cmd, data; + int i; + + cmd = 0x1; + fintek_read_reg(sc, cmd, &data, sizeof data); + + data |= (1<<4); + fintek_write_reg(sc, cmd, &data, sizeof data); + + i = 300; /* desired speed */ + i = 1500000/i; + cmd = 0x74; + data = i >> 8; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0x75; + data = i & 0xff; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0x60; + fintek_read_reg(sc, cmd, &data, sizeof data); + + data &= ~(0x1 << 4); + data |= (0x2 << 4); /* manual */ + fintek_write_reg(sc, cmd, &data, sizeof data); + printf("\n"); +} + +void +fintek_setauto(struct fintek_softc *sc) +{ + u_int8_t cmd, data, data2; + int i; + + i = 2000; /* desired speed */ + i = 1500000/i; + data2 = i >> 8; + data = i & 0xff; + + cmd = 0xa4; + fintek_write_reg(sc, cmd, &data, sizeof data); + fintek_write_reg(sc, cmd, &data2, sizeof data2); + + i = 0x3A98; + data2 = i >> 8; + data = i & 0xff; + cmd = 0xa6; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0xa7; + fintek_write_reg(sc, cmd, &data2, sizeof data2); + + i = 0x3A98; + data2 = i >> 8; + data = i & 0xff; + cmd = 0xa8; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0xa9; + fintek_write_reg(sc, cmd, &data2, sizeof data2); + + i = 0x3A98; + data2 = i >> 8; + data = i & 0xff; + cmd = 0xaa; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0xab; + fintek_write_reg(sc, cmd, &data2, sizeof data2); + + i = 0x3A98; + data2 = i >> 8; + data = i & 0xff; + cmd = 0xac; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0xad; + fintek_write_reg(sc, cmd, &data2, sizeof data2); + + cmd = 0x74; + fintek_read_reg(sc, cmd, &data, sizeof data); + + cmd = 0x75; + fintek_read_reg(sc, cmd, &data2, sizeof data); + + printf("fan speed %x %x\n", data, data2); + + cmd = 0x60; + fintek_read_reg(sc, cmd, &data, sizeof data); + + data &= ~(0x3 << 4); + data |= (1 << 4); + fintek_write_reg(sc, cmd, &data, sizeof data); + + printf("\n"); + +} +void +fintek_setpwm(struct fintek_softc *sc) +{ + u_int8_t cmd, data; + + cmd = 0x01; + fintek_read_reg(sc, cmd, &data, sizeof data); + data |= 1<<4; + fintek_write_reg(sc, cmd, &data, sizeof data); + + cmd = 0x60; + fintek_read_reg(sc, cmd, &data, sizeof data); + + data |= 0x3 << 4; + + fintek_write_reg(sc, cmd, &data, sizeof data); + + + data = 0x28; + cmd = 0x76; + fintek_write_reg(sc, cmd, &data, sizeof data); + + printf("\n"); + +} |