Module Name: src Committed By: khorben Date: Thu May 16 15:36:50 UTC 2013
Modified Files: src/sys/dev/i2c [khorben-n900]: files.i2c Added Files: src/sys/dev/i2c [khorben-n900]: lp5523.c lp5523reg.h Log Message: Initial import of the lp5523led(4) driver, a programmable 9-output LED driver from Texas Instruments. This is not functional yet, but exposes sysctl nodes and the internal temperature sensor (not refreshed at the moment). Tested on my Nokia N900 smartphone. To generate a diff of this commit: cvs rdiff -u -r1.49.2.3 -r1.49.2.4 src/sys/dev/i2c/files.i2c cvs rdiff -u -r0 -r1.1.2.1 src/sys/dev/i2c/lp5523.c \ src/sys/dev/i2c/lp5523reg.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.49.2.3 src/sys/dev/i2c/files.i2c:1.49.2.4 --- src/sys/dev/i2c/files.i2c:1.49.2.3 Sun May 12 01:49:44 2013 +++ src/sys/dev/i2c/files.i2c Thu May 16 15:36:50 2013 @@ -1,4 +1,4 @@ -# $NetBSD: files.i2c,v 1.49.2.3 2013/05/12 01:49:44 khorben Exp $ +# $NetBSD: files.i2c,v 1.49.2.4 2013/05/16 15:36:50 khorben Exp $ obsolete defflag opt_i2cbus.h I2C_SCAN define i2cbus { } @@ -187,3 +187,7 @@ device mcp980x: sysmon_envsys attach mcp980x at iic file dev/i2c/mcp980x.c mcp980x +# TI LP5523 LED driver +device lp5523led: sysmon_envsys +attach lp5523led at iic +file dev/i2c/lp5523.c lp5523led Added files: Index: src/sys/dev/i2c/lp5523.c diff -u /dev/null src/sys/dev/i2c/lp5523.c:1.1.2.1 --- /dev/null Thu May 16 15:36:50 2013 +++ src/sys/dev/i2c/lp5523.c Thu May 16 15:36:50 2013 @@ -0,0 +1,255 @@ +/* $NetBSD: lp5523.c,v 1.1.2.1 2013/05/16 15:36:50 khorben Exp $ */ + +/* + * Texas Instruments LP5523 Programmable 9-Output LED Driver + * + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Pierre Pronchery (khor...@defora.org). + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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 <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: lp5523.c,v 1.1.2.1 2013/05/16 15:36:50 khorben Exp $"); + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/sysctl.h> + +#include <dev/sysmon/sysmonvar.h> + +#include <dev/i2c/i2cvar.h> + +#include <dev/i2c/lp5523reg.h> + +#define LP5523_DEGC2UK(t) ((t * 1000000) + 273150000) + +/* constants */ +enum lp5523_leds { + LP5523_LED_0 = 0, + LP5523_LED_1, + LP5523_LED_2, + LP5523_LED_3, + LP5523_LED_4, + LP5523_LED_5, + LP5523_LED_6, + LP5523_LED_7, + LP5523_LED_8 +}; +#define LP5523_LED_LAST LP5523_LED_8 +#define LP5523_LED_CNT (LP5523_LED_LAST + 1) + +/* variables */ +struct lp5523_softc { + device_t sc_dev; + i2c_tag_t sc_i2c; + i2c_addr_t sc_addr; + + struct sysctllog *sc_sysctllog; + + /* temperature sensor */ + struct sysmon_envsys *sc_sme; + envsys_data_t sc_temp_sensor; +}; + +static int lp5523_match(device_t, cfdata_t, void *); +static void lp5523_attach(device_t, device_t, void *); +static void lp5523_attach_envsys(struct lp5523_softc *); +static void lp5523_attach_sysctl(struct lp5523_softc *); + +static int lp5523_reset(struct lp5523_softc *); + +static int lp5523_sysctl(SYSCTLFN_ARGS); + +static int lp5523_read_1(struct lp5523_softc *, uint8_t, uint8_t *); +static int lp5523_write_1(struct lp5523_softc *, uint8_t, uint8_t); + +CFATTACH_DECL_NEW(lp5523led, sizeof(struct lp5523_softc), + lp5523_match, lp5523_attach, NULL, NULL); + +static int +lp5523_match(device_t parent, cfdata_t match, void *aux) +{ + return 1; +} + +static void +lp5523_attach(device_t parent, device_t self, void *aux) +{ + struct lp5523_softc *sc = device_private(self); + struct i2c_attach_args *ia = aux; + + sc->sc_dev = self; + sc->sc_i2c = ia->ia_tag; + sc->sc_addr = ia->ia_addr; + + lp5523_reset(sc); + + aprint_normal(": LED driver\n"); + aprint_naive(": LED driver\n"); + + lp5523_attach_sysctl(sc); + + lp5523_attach_envsys(sc); + + if (!pmf_device_register(sc->sc_dev, NULL, NULL)) { + aprint_error_dev(sc->sc_dev, + "could not establish power handler\n"); + } +} + +static void +lp5523_attach_envsys(struct lp5523_softc *sc) +{ + const int flags = ENVSYS_FMONNOTSUPP | ENVSYS_FHAS_ENTROPY + | ENVSYS_FVALID_MIN | ENVSYS_FVALID_MAX; + int8_t s8; + + sc->sc_sme = sysmon_envsys_create(); + + sc->sc_sme->sme_cookie = sc; + sc->sc_sme->sme_name = device_xname(sc->sc_dev); + sc->sc_sme->sme_flags = SME_DISABLE_REFRESH; + + sc->sc_temp_sensor.flags = flags; + sc->sc_temp_sensor.units = ENVSYS_STEMP; + sc->sc_temp_sensor.state = ENVSYS_SINVALID; + sc->sc_temp_sensor.value_min = LP5523_DEGC2UK(-41); + sc->sc_temp_sensor.value_max = LP5523_DEGC2UK(89); + + strlcat(sc->sc_temp_sensor.desc, "temperature", + sizeof(sc->sc_temp_sensor.desc)); + + if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_temp_sensor) != 0 + || sysmon_envsys_register(sc->sc_sme) != 0) + { + aprint_error_dev(sc->sc_dev, "unable to attach the temperature" + " sensor\n"); + sysmon_envsys_destroy(sc->sc_sme); + sc->sc_sme = NULL; + return; + } + + iic_acquire_bus(sc->sc_i2c, 0); + lp5523_read_1(sc, LP5523_REG_TEMP_READ, &s8); + iic_release_bus(sc->sc_i2c, 0); + if (s8 >= -41 && s8 <= 89) { + sc->sc_temp_sensor.state = ENVSYS_SVALID; + sc->sc_temp_sensor.value_cur = LP5523_DEGC2UK(s8); + } +} + +static void +lp5523_attach_sysctl(struct lp5523_softc *sc) +{ + struct sysctllog **log = &sc->sc_sysctllog; + const struct sysctlnode *rnode, *cnode; + unsigned int i; + char buf[8]; + int error; + + error = sysctl_createv(log, 0, NULL, &rnode, CTLFLAG_PERMANENT, + CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0, CTL_HW, + CTL_EOL); + if (error) + return; + + error = sysctl_createv(log, 0, &rnode, &rnode, CTLFLAG_PERMANENT, + CTLTYPE_NODE, device_xname(sc->sc_dev), + SYSCTL_DESCR("lp5523led control"), NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + if (error) + return; + + for (i = 0; i < LP5523_LED_CNT; i++) { + snprintf(buf, sizeof(buf), "led%u", i); + error = sysctl_createv(log, 0, &rnode, &cnode, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, buf, SYSCTL_DESCR("LED enable"), + lp5523_sysctl, 0, (void *)sc, 0, CTL_CREATE, + CTL_EOL); + if (error) + break; + } +} + +static int +lp5523_reset(struct lp5523_softc *sc) +{ + uint8_t u8; + + iic_acquire_bus(sc->sc_i2c, 0); + lp5523_write_1(sc, LP5523_REG_RESET, 0xff); + + u8 = LP5523_REG_ENGINE_CNTRL1_CHIP_EN; + lp5523_write_1(sc, LP5523_REG_ENGINE_CNTRL1, u8); + iic_release_bus(sc->sc_i2c, 0); + + return 0; +} + +static int +lp5523_sysctl(SYSCTLFN_ARGS) +{ + struct lp5523_softc *sc; + struct sysctlnode node; + u_int led; + int error; + + node = *rnode; + sc = node.sysctl_data; + iic_acquire_bus(sc->sc_i2c, 0); + /* FIXME really implement */ + led = 0; + iic_release_bus(sc->sc_i2c, 0); + + node.sysctl_data = &led; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + + iic_acquire_bus(sc->sc_i2c, 0); + /* FIXME really implement */ + error = 0; + iic_release_bus(sc->sc_i2c, 0); + + return error; +} + +static int +lp5523_read_1(struct lp5523_softc *sc, uint8_t reg, uint8_t *val) +{ + return iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP, sc->sc_addr, + ®, sizeof(reg), val, sizeof(*val), 0); +} + +static int +lp5523_write_1(struct lp5523_softc *sc, uint8_t reg, uint8_t val) +{ + uint8_t data[2] = { reg, val }; + + return iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, + NULL, 0, data, sizeof(data), 0); +} Index: src/sys/dev/i2c/lp5523reg.h diff -u /dev/null src/sys/dev/i2c/lp5523reg.h:1.1.2.1 --- /dev/null Thu May 16 15:36:50 2013 +++ src/sys/dev/i2c/lp5523reg.h Thu May 16 15:36:50 2013 @@ -0,0 +1,142 @@ +/* $NetBSD: lp5523reg.h,v 1.1.2.1 2013/05/16 15:36:50 khorben Exp $ */ + +/* + * Texas Instruments LP5523 Programmable 9-Output LED Driver + * + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Pierre Pronchery (khor...@defora.org). + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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_LP5523REG_H_ +#define _DEV_I2C_LP5523REG_H_ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: lp5523reg.h,v 1.1.2.1 2013/05/16 15:36:50 khorben Exp $"); + +/* registers */ +#define LP5523_REG_ENGINE_CNTRL1 0x00 +#define LP5523_REG_ENGINE_CNTRL1_CHIP_EN __BIT(6) +#define LP5523_REG_ENGINE_CNTRL1_ENGINE1_EXEC __BITS(4,5) +#define LP5523_REG_ENGINE_CNTRL1_ENGINE2_EXEC __BITS(2,3) +#define LP5523_REG_ENGINE_CNTRL1_ENGINE3_EXEC __BITS(0,1) + +#define LP5523_REG_ENGINE_CNTRL2 0x01 +#define LP5523_REG_OUTPUT_DIRECT_MSB 0x02 +#define LP5523_REG_OUTPUT_DIRECT_LSB 0x03 +#define LP5523_REG_OUTPUT_ONOFF_MSB 0x04 +#define LP5523_REG_OUTPUT_ONOFF_LSB 0x05 +#define LP5523_REG_D1_CONTROL 0x06 +#define LP5523_REG_D2_CONTROL 0x07 +#define LP5523_REG_D3_CONTROL 0x08 +#define LP5523_REG_D4_CONTROL 0x09 +#define LP5523_REG_D5_CONTROL 0x0a +#define LP5523_REG_D6_CONTROL 0x0b +#define LP5523_REG_D7_CONTROL 0x0c +#define LP5523_REG_D8_CONTROL 0x0d +#define LP5523_REG_D9_CONTROL 0x0e +#define LP5523_REG_D1_PWM 0x16 +#define LP5523_REG_D2_PWM 0x17 +#define LP5523_REG_D3_PWM 0x18 +#define LP5523_REG_D4_PWM 0x19 +#define LP5523_REG_D5_PWM 0x1a +#define LP5523_REG_D6_PWM 0x1b +#define LP5523_REG_D7_PWM 0x1c +#define LP5523_REG_D8_PWM 0x1d +#define LP5523_REG_D9_PWM 0x1e +#define LP5523_REG_D1_CURRENT 0x26 +#define LP5523_REG_D2_CURRENT 0x27 +#define LP5523_REG_D3_CURRENT 0x28 +#define LP5523_REG_D4_CURRENT 0x29 +#define LP5523_REG_D5_CURRENT 0x2a +#define LP5523_REG_D6_CURRENT 0x2b +#define LP5523_REG_D7_CURRENT 0x2c +#define LP5523_REG_D8_CURRENT 0x2d +#define LP5523_REG_D9_CURRENT 0x2e +#define LP5523_REG_MISC 0x36 +#define LP5523_REG_ENGINE1_PC 0x37 +#define LP5523_REG_ENGINE2_PC 0x38 +#define LP5523_REG_ENGINE3_PC 0x39 +#define LP5523_REG_STATUS 0x3a +#define LP5523_REG_GPO 0x3b +#define LP5523_REG_VARIABLE 0x3c +#define LP5523_REG_RESET 0x3d +#define LP5523_REG_TEMP_ADC 0x3e +#define LP5523_REG_TEMP_READ 0x3f +#define LP5523_REG_TEMP_WRITE 0x40 +#define LP5523_REG_LED_TEST 0x41 +#define LP5523_REG_TEST_ADC 0x42 +#define LP5523_REG_ENGINE1_VARA 0x45 +#define LP5523_REG_ENGINE2_VARA 0x46 +#define LP5523_REG_ENGINE3_VARA 0x47 +#define LP5523_REG_MASTER_FADER1 0x48 +#define LP5523_REG_MASTER_FADER2 0x49 +#define LP5523_REG_MASTER_FADER3 0x4a +#define LP5523_REG_ENG1_PROG_START 0x4c +#define LP5523_REG_ENG2_PROG_START 0x4d +#define LP5523_REG_ENG3_PROG_START 0x4e +#define LP5523_REG_PROG_MEM_PAGE_SEL 0x4f +#define LP5523_REG_PROGRAM_MEMORY_08 0x50 +#define LP5523_REG_PROGRAM_MEMORY_00 0x51 +#define LP5523_REG_PROGRAM_MEMORY_18 0x52 +#define LP5523_REG_PROGRAM_MEMORY_10 0x53 +#define LP5523_REG_PROGRAM_MEMORY_28 0x54 +#define LP5523_REG_PROGRAM_MEMORY_20 0x55 +#define LP5523_REG_PROGRAM_MEMORY_38 0x56 +#define LP5523_REG_PROGRAM_MEMORY_30 0x57 +#define LP5523_REG_PROGRAM_MEMORY_48 0x58 +#define LP5523_REG_PROGRAM_MEMORY_40 0x59 +#define LP5523_REG_PROGRAM_MEMORY_58 0x5a +#define LP5523_REG_PROGRAM_MEMORY_50 0x5b +#define LP5523_REG_PROGRAM_MEMORY_68 0x5c +#define LP5523_REG_PROGRAM_MEMORY_60 0x5d +#define LP5523_REG_PROGRAM_MEMORY_78 0x5e +#define LP5523_REG_PROGRAM_MEMORY_70 0x5f +#define LP5523_REG_PROGRAM_MEMORY_88 0x60 +#define LP5523_REG_PROGRAM_MEMORY_80 0x61 +#define LP5523_REG_PROGRAM_MEMORY_98 0x62 +#define LP5523_REG_PROGRAM_MEMORY_90 0x63 +#define LP5523_REG_PROGRAM_MEMORY_A8 0x64 +#define LP5523_REG_PROGRAM_MEMORY_A0 0x65 +#define LP5523_REG_PROGRAM_MEMORY_B8 0x66 +#define LP5523_REG_PROGRAM_MEMORY_B0 0x67 +#define LP5523_REG_PROGRAM_MEMORY_C8 0x68 +#define LP5523_REG_PROGRAM_MEMORY_C0 0x69 +#define LP5523_REG_PROGRAM_MEMORY_D8 0x6a +#define LP5523_REG_PROGRAM_MEMORY_D0 0x6b +#define LP5523_REG_PROGRAM_MEMORY_E8 0x6c +#define LP5523_REG_PROGRAM_MEMORY_E0 0x6d +#define LP5523_REG_PROGRAM_MEMORY_F8 0x6e +#define LP5523_REG_PROGRAM_MEMORY_F0 0x6f +#define LP5523_REG_ENG1_MAPPING_MSB 0x70 +#define LP5523_REG_ENG1_MAPPING_LSB 0x71 +#define LP5523_REG_ENG2_MAPPING_MSB 0x72 +#define LP5523_REG_ENG2_MAPPING_LSB 0x73 +#define LP5523_REG_ENG3_MAPPING_MSB 0x74 +#define LP5523_REG_ENG3_MAPPING_LSB 0x75 +#define LP5523_REG_GAIN_CHANGE_CTRL 0x76 + +#endif /* _DEV_I2C_LP5523REG_H_ */