implement hwmon fan divisor setting for w83697hf
authorFlorian Zumbiehl <florz@florz.de>
Tue, 1 Nov 2011 19:19:06 +0000 (20:19 +0100)
committerRudolf Marek <r.marek@assembler.cz>
Tue, 22 Nov 2011 22:07:03 +0000 (23:07 +0100)
Change-Id: I887ac1142875ca1dc1a1eb8eebec402fbe7512c3
Signed-off-by: Florian Zumbiehl <florz@florz.de>
Reviewed-on: http://review.coreboot.org/384
Reviewed-by: Rudolf Marek <r.marek@assembler.cz>
Tested-by: build bot (Jenkins)
src/superio/winbond/w83697hf/chip.h
src/superio/winbond/w83697hf/superio.c

index 1a1cbcc038c07b253ec79a36906d055d5749f81b..2359b6679fcf5280182ae6b12759404ddfedaed3 100644 (file)
@@ -26,7 +26,8 @@
 extern struct chip_operations superio_winbond_w83697hf_ops;
 
 struct superio_winbond_w83697hf_config {
-
+       unsigned int hwmon_fan1_divisor;
+       unsigned int hwmon_fan2_divisor;
 };
 
 #endif
index d2cbcbd6424d6395db4293ca762ee188c08d39d4..8f090d0b6652f1826b680fe5c85a56261f3a6f64 100644 (file)
@@ -41,10 +41,44 @@ static void pnp_exit_ext_func_mode(device_t dev)
        outb(0xaa, dev->path.pnp.port);
 }
 
+static void hwmon_set_fan_divisor(unsigned int base, int num, unsigned int divisor) {
+       unsigned char enc, buf;
+
+       if (divisor) {
+               enc = log2(divisor);
+               if (1 << enc != divisor || enc > 7)
+                       die("invalid fan divisor");
+               outb(0x4e, base + 5);
+               outb(0x00, base + 6);
+               outb(0x47, base + 5);
+               outb((inb(base + 6) & ~(0x30 << (num * 2))) | ((enc & 3) << (4 + num * 2)), base + 6);
+               outb(0x5d, base + 5);
+               buf = inb(base + 6);
+               /* the above inb() auto-increments the address pointer ... */
+               outb(0x5d, base + 5);
+               outb((buf & ~(0x20 << num)) | ((enc & 4) << (3 + num)), base + 6);
+       }
+}
+
 static void w83697hf_init(device_t dev)
 {
+       struct resource *res0;
+       struct superio_winbond_w83697hf_config *cfg;
+
        if (!dev->enabled)
                return;
+
+       cfg = dev->chip_info;
+
+       switch (dev->path.pnp.device) {
+       case W83697HF_HWM:
+               if (cfg) {
+                       res0 = find_resource(dev, PNP_IDX_IO0);
+                       hwmon_set_fan_divisor(res0->base, 0, cfg->hwmon_fan1_divisor);
+                       hwmon_set_fan_divisor(res0->base, 1, cfg->hwmon_fan2_divisor);
+               }
+               break;
+       }
 }
 
 static void w83697hf_pnp_set_resources(device_t dev)