From owner-freebsd-ppc@FreeBSD.ORG Sat May 28 18:11:38 2011 Return-Path: Delivered-To: freebsd-ppc@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 963F0106564A for ; Sat, 28 May 2011 18:11:38 +0000 (UTC) (envelope-from chmeeedalf@gmail.com) Received: from mail-gw0-f54.google.com (mail-gw0-f54.google.com [74.125.83.54]) by mx1.freebsd.org (Postfix) with ESMTP id 4C3568FC14 for ; Sat, 28 May 2011 18:11:37 +0000 (UTC) Received: by gwb15 with SMTP id 15so1404029gwb.13 for ; Sat, 28 May 2011 11:11:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:sender:message-id:from:to:content-type :mime-version:subject:date:x-mailer; bh=Do6NOcOv5kwY3RmLxsIuNZLkVWQcAwMOE6ipZLEtJwM=; b=KqbmrPkQa6nlEeYVNv/L039eU9udGilO7fvTVW4WOtyIhn3asSZ0bevd5PFD3o3dab W94QM1zEToSy4UGBpsCExxFzcp34eBy57CUHrTgMt61sVLuap5vvkMEqF77zltqtSGhL Mw9yL6oelLILBrLklWkyMriXRSDTgB0Xy+p6o= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=sender:message-id:from:to:content-type:mime-version:subject:date :x-mailer; b=PJ1OX3okJZjWzK48gIy0IWABa9jn4mff4TR3UoApFJPNpLSvroP40iAwNBOiXveWSz diGg/lGx0l30QQXWArkLJc7/HJjm1TmfjeV03EsLnQ11znI1wris2g8UGj8v4TEDkdEk SZSFSI8G4Jsm1OVLe5NLUciTJQjTl6JWKH0o0= Received: by 10.236.144.230 with SMTP id n66mr4222637yhj.17.1306604804091; Sat, 28 May 2011 10:46:44 -0700 (PDT) Received: from triad.knownspace (216-15-41-8.c3-0.gth-ubr1.lnh-gth.md.cable.rcn.com [216.15.41.8]) by mx.google.com with ESMTPS id i46sm1319499yhk.76.2011.05.28.10.46.42 (version=TLSv1/SSLv3 cipher=OTHER); Sat, 28 May 2011 10:46:43 -0700 (PDT) Sender: Justin Hibbits Message-Id: <28099850-93EB-48CD-A186-8A1DAE2D7C8C@alumni.cwru.edu> From: Justin Hibbits To: FreeBSD PowerPC ML Content-Type: multipart/mixed; boundary=Apple-Mail-8--267396345 Mime-Version: 1.0 (Apple Message framework v936) Date: Sat, 28 May 2011 13:46:41 -0400 X-Mailer: Apple Mail (2.936) Subject: CFT: G4 MDD fan driver take 2 X-BeenThere: freebsd-ppc@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to the PowerPC List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 May 2011 18:11:38 -0000 --Apple-Mail-8--267396345 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Some slight modifications to my driver posted January. I'd like for someone to get this in before the 9.0 freeze, so please test and comment. Someone can style(9) it, too, if they notice any problems. I hope the list doesn't eat my patch this time. - Justin --Apple-Mail-8--267396345 Content-Disposition: attachment; filename=windtunnel.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="windtunnel.patch" Content-Transfer-Encoding: 7bit Index: sys/conf/files.powerpc =================================================================== --- sys/conf/files.powerpc (revision 221779) +++ sys/conf/files.powerpc (working copy) @@ -143,6 +143,7 @@ powerpc/powermac/cpcht.c optional powermac pci powerpc/powermac/dbdma.c optional powermac pci powerpc/powermac/fcu.c optional powermac fcu +powerpc/powermac/windtunnel.c optional powermac windtunnel powerpc/powermac/grackle.c optional powermac pci powerpc/powermac/hrowpic.c optional powermac pci powerpc/powermac/kiic.c optional powermac kiic Index: sys/powerpc/powermac/windtunnel.c =================================================================== --- sys/powerpc/powermac/windtunnel.c (revision 0) +++ sys/powerpc/powermac/windtunnel.c (revision 0) @@ -0,0 +1,306 @@ +/*- + * Copyright (c) 2011 Justin Hibbits + * Copyright (c) 2010 Andreas Tobler + * All rights reserved. + * + * 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 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#define ADM1030_FANMGT_INTERVAL 1000 /* ms */ + +#define ADM1030_FAN_TEMPS_COUNT 15 + +/* Temperatures read are half-degrees, so don't go any finer than that. */ +#define T(x,y) (x << 8 | ((y / 5) << 7)) +static int adm1030_fan_temps[] = +{ + T(55, 0), + T(57, 0), + T(57, 5), + T(58, 5), + T(59, 0), + T(59, 0), + T(59, 5), + T(59, 5), + T(60, 0), + T(60, 5), + T(61, 0), + T(61, 5), + T(62, 0), + T(62, 0), + T(62, 0), +}; + +struct adm1030_softc { + device_t sc_dev; + struct proc *sc_management_proc; + struct intr_config_hook enum_hook; + uint32_t sc_addr; + int current_speed; + phandle_t sc_thermostat_phandle; + device_t sc_thermostat_dev; +}; + +/* Regular bus attachment functions */ +static int adm1030_probe(device_t); +static int adm1030_attach(device_t); + +/* Utility functions */ +static void adm1030_start(void *xdev); +static int adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t buf); +static int read_reg(device_t dev, uint32_t addr, uint8_t reg, uint16_t * data); +static void adm1030_fan_manage(void *xdev); +static void adm1030_manage_fans(device_t fan); + +static device_method_t adm1030_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, adm1030_probe), + DEVMETHOD(device_attach, adm1030_attach), + {0, 0}, +}; + +static driver_t adm1030_driver = { + "adm1030", + adm1030_methods, + sizeof(struct adm1030_softc) +}; + +static devclass_t adm1030_devclass; + +DRIVER_MODULE(adm1030, iicbus, adm1030_driver, adm1030_devclass, 0, 0); +MALLOC_DEFINE(M_ADM1030, "adm1030", "ADM1030 Sensor Information"); + +static device_t +device_node_from_phandle(phandle_t handle, device_t parent_node) +{ + int children_count; + device_t *child_list; + device_t retval; + int i; + + retval = NULL; + if (device_get_children(parent_node, &child_list, &children_count) < 0) { + return NULL; + } + for (i = 0; i < children_count; i++) { + if (ofw_bus_get_node(child_list[i]) == handle) { + retval = child_list[i]; + break; + } + } + + free(child_list, M_TEMP); + return retval; +} + +static int +adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t byte) +{ + unsigned char buf[4]; + struct iic_msg msg[] = { + {addr, IIC_M_WR, 0, buf} + }; + + msg[0].len = 2; + buf[0] = reg; + buf[1] = byte; + if (iicbus_transfer(dev, msg, 1) != 0) { + device_printf(dev, "iicbus write failed\n"); + return (EIO); + } + return (0); +} + +static int +read_reg(device_t dev, uint32_t addr, uint8_t reg, uint16_t * data) +{ + uint8_t buf [4]; + + struct iic_msg msg[2] = { + {addr, IIC_M_WR | IIC_M_NOSTOP, 1, ®}, + {addr, IIC_M_RD, 2, buf}, + }; + + if (iicbus_transfer(dev, msg, 2) != 0) { + device_printf(dev, "iicbus read failed\n"); + return (EIO); + } + *data = *((uint16_t *) buf); + + return (0); +} + +static int +adm1030_probe(device_t dev) +{ + const char *name, *compatible; + struct adm1030_softc *sc; + phandle_t handle; + phandle_t thermostat; + + name = ofw_bus_get_name(dev); + compatible = ofw_bus_get_compat(dev); + handle = ofw_bus_get_node(dev); + + if (!name) + return (ENXIO); + + if (strcmp(name, "fan") != 0 || strcmp(compatible, "adm1030") != 0) + return (ENXIO); + + /* This driver can only be used if there's an associated temp sensor. */ + if (OF_getprop(handle, "platform-getTemp", &thermostat, sizeof(thermostat)) < 0) + return (ENXIO); + + sc = device_get_softc(dev); + sc->sc_dev = dev; + sc->sc_addr = iicbus_get_addr(dev); + sc->sc_thermostat_phandle = thermostat; + + device_set_desc(dev, "G4 MDD Fan driver"); + + return (0); +} + +static int +adm1030_attach(device_t dev) +{ + struct adm1030_softc *sc; + + sc = device_get_softc(dev); + + sc->enum_hook.ich_func = adm1030_start; + sc->enum_hook.ich_arg = dev; + + /* + * We have to wait until interrupts are enabled. I2C read and write + * only works if the interrupts are available. The unin/i2c is + * controlled by the htpic on unin. But this is not the master. The + * openpic on mac-io is controlling the htpic. This one gets attached + * after the mac-io probing and then the interrupts will be + * available. + */ + + if (config_intrhook_establish(&sc->enum_hook) != 0) + return (ENOMEM); + + return (0); +} + +static void +adm1030_start(void *xdev) +{ + struct adm1030_softc *sc; + + device_t dev = (device_t) xdev; + + sc = device_get_softc(dev); + + /* Start the adm1030 device. */ + adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x1, 0x1); + adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x0, 0x95); + adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x23, 0x91); + + config_intrhook_disestablish(&sc->enum_hook); + + sc->sc_thermostat_dev = device_node_from_phandle(sc->sc_thermostat_phandle, device_get_parent(dev)); + sc->current_speed = 0; + + kproc_create(adm1030_fan_manage, dev, &sc->sc_management_proc, + RFHIGHPID, 0, "adm1030_fan"); +} + +static void +adm1030_fan_manage(void *xdev) +{ + device_t adm1030_dev = xdev; + + while (1) { + adm1030_manage_fans(adm1030_dev); + pause("adm1030", ADM1030_FANMGT_INTERVAL * hz / 1000); + } +} + +static int +thermostat_get_temp(device_t dev) +{ + uint16_t temp = 0; + struct iicbus_ivar *devi = IICBUS_IVAR(dev); + + if (read_reg(dev, devi->addr, 0, &temp) < 0) + return -1; + + return temp; +} + +static void +adm1030_manage_fans(device_t fan) +{ + int temp; + struct adm1030_softc *sc; + uint8_t fan_idx; + + sc = device_get_softc(fan); + + temp = thermostat_get_temp(sc->sc_thermostat_dev); + if (temp < 0) + return; + + fan_idx = sc->current_speed; + + // Only adjust the fan one index per second. + if (temp < adm1030_fan_temps[fan_idx] && fan_idx > 0) { + fan_idx--; + } else if (fan_idx < 15) { + fan_idx++; + } + sc->current_speed = fan_idx; + adm1030_write_byte(fan, sc->sc_addr, 0x22, fan_idx); +} --Apple-Mail-8--267396345 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit --Apple-Mail-8--267396345--