Module Name:    src
Committed By:   kiyohara
Date:           Sat Oct  2 06:07:37 UTC 2010

Modified Files:
        src/sys/dev/i2c: files.i2c
Added Files:
        src/sys/dev/i2c: g760a.c g760areg.h

Log Message:
Add G760a fan speed controller driver.


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/i2c/files.i2c
cvs rdiff -u -r0 -r1.1 src/sys/dev/i2c/g760a.c src/sys/dev/i2c/g760areg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/files.i2c
diff -u src/sys/dev/i2c/files.i2c:1.27 src/sys/dev/i2c/files.i2c:1.28
--- src/sys/dev/i2c/files.i2c:1.27	Wed Mar 24 00:31:41 2010
+++ src/sys/dev/i2c/files.i2c	Sat Oct  2 06:07:37 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i2c,v 1.27 2010/03/24 00:31:41 pgoyette Exp $
+#	$NetBSD: files.i2c,v 1.28 2010/10/02 06:07:37 kiyohara Exp $
 
 defflag	opt_i2cbus.h				I2C_SCAN
 define	i2cbus { }
@@ -119,3 +119,8 @@
 device	smscmon: sysmon_envsys
 attach	smscmon at iic
 file	dev/i2c/smscmon.c		smscmon
+
+# G760a FAN controller
+device	g760a: sysmon_envsys
+attach	g760a at iic
+file	dev/i2c/g760a.c			g760a

Added files:

Index: src/sys/dev/i2c/g760a.c
diff -u /dev/null src/sys/dev/i2c/g760a.c:1.1
--- /dev/null	Sat Oct  2 06:07:38 2010
+++ src/sys/dev/i2c/g760a.c	Sat Oct  2 06:07:37 2010
@@ -0,0 +1,261 @@
+/*	$NetBSD: g760a.c,v 1.1 2010/10/02 06:07:37 kiyohara Exp $	*/
+
+/*-
+ * Copyright (C) 2008 A.Leo.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * The driver for the G760A FAN Speed PWM controller.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: g760a.c,v 1.1 2010/10/02 06:07:37 kiyohara Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/sysctl.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <dev/i2c/i2cvar.h>
+#include <dev/i2c/g760areg.h>
+
+
+struct g760a_softc {
+	device_t sc_dev;
+	struct sysmon_envsys *sc_sme;
+
+	envsys_data_t sc_sensor;
+	i2c_tag_t sc_tag;
+	int sc_addr;
+};
+
+static int g760a_match(device_t, struct cfdata*, void*);
+static void g760a_attach(device_t, device_t, void*);
+static void g760a_setup(struct g760a_softc*);
+static uint8_t g760a_readreg(struct g760a_softc*, uint8_t);
+static void g760a_writereg(struct g760a_softc*, uint8_t, uint8_t);
+
+static int g760a_reg2rpm(int);
+
+static void g760a_refresh(struct sysmon_envsys*, envsys_data_t*);
+static int sysctl_g760a_rpm(SYSCTLFN_PROTO);
+
+CFATTACH_DECL_NEW(g760a, sizeof(struct g760a_softc),
+		g760a_match, g760a_attach, NULL, NULL);
+
+static int
+g760a_match(device_t parent, struct cfdata* cf, void* arg)
+{
+	struct i2c_attach_args* ia = arg;
+
+	if (ia->ia_addr == G760A_ADDR) {
+		/*
+		 * TODO: set up minimal speed? 
+		 */
+		return 1;
+	}
+
+	return 0;
+}
+
+
+static void
+g760a_attach(device_t parent, device_t self, void* arg)
+{
+	struct i2c_attach_args* ia = arg;
+	struct g760a_softc* sc = device_private(self);
+
+	aprint_normal(": G760A Fan Controller\n");
+
+	sc->sc_dev = self;
+	sc->sc_tag = ia->ia_tag;
+	sc->sc_addr = ia->ia_addr;
+
+	g760a_setup(sc);
+}
+
+
+static int
+g760a_reg2rpm(int n)
+{
+	if(n == 255)
+		return 0;
+
+	if(n == 0)
+		return 255;
+
+	return G760A_N2RPM(n);
+}
+
+
+static uint8_t
+g760a_readreg(struct g760a_softc* sc, uint8_t reg)
+{
+	uint8_t data;
+
+	if (iic_acquire_bus(sc->sc_tag, 0)) {
+		aprint_error_dev(sc->sc_dev, "unable to acquire the iic bus\n");
+		return 0;
+	}
+
+	iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1,
+	    &data, 1, 0);
+	iic_release_bus(sc->sc_tag, 0);
+
+	return data;
+}
+
+
+static void
+g760a_writereg(struct g760a_softc* sc, uint8_t reg, uint8_t data)
+{
+
+	if (iic_acquire_bus(sc->sc_tag, 0)) {
+		aprint_error_dev(sc->sc_dev, "unable to acquire the iic bus\n");
+		return;
+	}
+
+	iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, &reg, 1,
+	    &data, 1, 0);
+	iic_release_bus(sc->sc_tag, 0);
+}
+
+
+SYSCTL_SETUP(sysctl_g760a_setup, "sysctl g760a subtree setup")
+{
+
+	sysctl_createv(NULL, 0, NULL, NULL,  
+			CTLFLAG_PERMANENT,
+			CTLTYPE_NODE, "machdep", NULL, 
+			NULL, 0, NULL, 0,
+			CTL_MACHDEP, CTL_EOL);
+}
+
+
+/*ARGUSED*/
+static int
+sysctl_g760a_rpm(SYSCTLFN_ARGS)
+{
+	int error, t;
+	struct sysctlnode node;
+	struct g760a_softc* sc;
+       	
+	node = *rnode;
+	sc = node.sysctl_data;
+
+	t = g760a_readreg(sc, G760A_REG_SET_CNT);
+	t = g760a_reg2rpm(t);
+
+	node.sysctl_data = &t;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+
+	if (error || newp == NULL)
+		return error;
+
+	if (t > 20000 || t < G760A_N2RPM(254))
+		return EINVAL;
+
+	t = g760a_reg2rpm(t);
+
+	g760a_writereg(sc, G760A_REG_SET_CNT, t);
+
+	return 0;
+}
+
+
+static void
+g760a_refresh(struct sysmon_envsys* sme, envsys_data_t* edata)
+{
+	struct g760a_softc* sc = sme->sme_cookie;
+	
+	switch (edata->units) {
+		case ENVSYS_SFANRPM:
+			{
+				uint8_t n;
+				
+				n = g760a_readreg(sc, G760A_REG_ACT_CNT);
+				edata->value_cur = g760a_reg2rpm(n);
+			}
+			break;
+		default:
+			aprint_error_dev(sc->sc_dev, "oops\n");
+	}
+
+	edata->state = ENVSYS_SVALID;
+}
+
+
+static void
+g760a_setup(struct g760a_softc* sc)
+{
+	int error;
+	int ret;
+	struct sysctlnode* me = NULL, * node = NULL;
+
+	sc->sc_sme = sysmon_envsys_create();
+
+	ret = sysctl_createv(NULL, 0, NULL, (const struct sysctlnode**)&me,
+			CTLFLAG_READWRITE,
+			CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
+			NULL, 0, NULL, 0,
+			CTL_MACHDEP, CTL_CREATE, CTL_EOL);
+
+	(void)strlcpy(sc->sc_sensor.desc, "sysfan rpm",
+			sizeof(sc->sc_sensor.desc));
+	sc->sc_sensor.units = ENVSYS_SFANRPM;
+
+	if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor))
+		goto out;
+
+	ret = sysctl_createv(NULL, 0, NULL, (const struct sysctlnode**)&node,
+			CTLFLAG_READWRITE,
+			CTLTYPE_INT, "rpm", sc->sc_sensor.desc,
+			sysctl_g760a_rpm, 0x42, NULL, 0,
+			CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
+	if (node != NULL)
+		node->sysctl_data = sc;
+
+	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
+	sc->sc_sme->sme_cookie = sc;
+	sc->sc_sme->sme_refresh = g760a_refresh;
+
+	error = sysmon_envsys_register(sc->sc_sme);
+
+	if (error) {
+		aprint_error_dev(sc->sc_dev,
+		    "unable to register with sysmon. errorcode %i\n", error);
+		goto out;
+	}
+
+	return;
+out:
+	sysmon_envsys_destroy(sc->sc_sme);
+}
Index: src/sys/dev/i2c/g760areg.h
diff -u /dev/null src/sys/dev/i2c/g760areg.h:1.1
--- /dev/null	Sat Oct  2 06:07:38 2010
+++ src/sys/dev/i2c/g760areg.h	Sat Oct  2 06:07:37 2010
@@ -0,0 +1,53 @@
+/*	$NetBSD: g760areg.h,v 1.1 2010/10/02 06:07:37 kiyohara Exp $	*/
+
+/*-
+ * Copyright (C) 2008 A.Leo.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+
+#ifndef _DEV_I2C_G760aREG_H_
+#define _DEV_I2C_G760aREG_H_
+
+#define	G760A_ADDR			0x3e
+
+#define	G760A_REG_SET_CNT		0x00	/* RW, Programmed fan speed
+						   register, it contains the
+						   count number of the
+						   desired fan speed. */
+
+#define	G760A_REG_ACT_CNT		0x01	/* RO, Actual fan speed. */
+#define	G760A_REG_FAN_STA		0x02	/* RO, Fan status. */
+#define G760A_REG_FAN_STA_MASK		0x03u	/* 2 lower bits */
+
+#define G760A_CLK			32768
+#define G760A_P				2
+
+
+
+#define G760A_N2RPM(a)			(G760A_CLK*30/G760A_P/(a)) 
+#define G760A_RPM2N(a)			(G760A_CLK*30/G760A_P/(a))     /* wow */
+
+
+#endif /* !_DEV_I2C_G760AREG_H_ */

Reply via email to