LCOV - code coverage report
Current view: top level - dev/onewire - owsbm.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 101 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: owsbm.c,v 1.10 2015/03/14 03:38:48 jsg Exp $  */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007 Aaron Linville <aaron@linville.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : /*
      20             :  * 1-Wire Smart Battery Monitor family type device driver.
      21             :  * Provides on-board temperature, an A/D converter for voltage/current,
      22             :  * current accumulator, elapsed time metter, and 40 bytes of nonvolatile
      23             :  * memory.
      24             :  */
      25             : 
      26             : #include <sys/param.h>
      27             : #include <sys/systm.h>
      28             : #include <sys/device.h>
      29             : #include <sys/rwlock.h>
      30             : #include <sys/sensors.h>
      31             : 
      32             : #include <dev/onewire/onewiredevs.h>
      33             : #include <dev/onewire/onewirereg.h>
      34             : #include <dev/onewire/onewirevar.h>
      35             : 
      36             : /* Commands */
      37             : #define DSSBM_CMD_READ_SCRATCHPAD       0xbe
      38             : #define DSSBM_CMD_WRITE_SCRATCHPAD      0x4e
      39             : #define DSSBM_CMD_COPY_SCRATCHPAD       0x48
      40             : 
      41             : #define DSSBM_CMD_RECALL_MEMORY         0xb8
      42             : 
      43             : #define DSSBM_CMD_CONVERT_T             0x44
      44             : #define DSSBM_CMD_CONVERT_V             0xb4    
      45             : 
      46             : /* Scratchpad layout */
      47             : #define DS2438_SP_STATUS                0
      48             : #define DS2438_SP_TEMP_LSB              1
      49             : #define DS2438_SP_TEMP_MSB              2
      50             : #define DS2438_SP_VOLT_LSB              3
      51             : #define DS2438_SP_VOLT_MSB              4
      52             : #define DS2438_SP_CURRENT_LSB           5
      53             : #define DS2438_SP_CURRENT_MSB           6
      54             : #define DS2438_SP_THRESHOLD             7
      55             : #define DS2438_SP_CRC                   8
      56             : 
      57             : struct owsbm_softc {
      58             :         struct device           sc_dev;
      59             : 
      60             :         void *                  sc_onewire;
      61             :         u_int64_t               sc_rom;
      62             : 
      63             :         struct ksensordev       sc_sensordev;
      64             : 
      65             :         struct ksensor          sc_temp;
      66             :         struct ksensor          sc_voltage_vdd; /* Battery, AD = 1*/
      67             :         struct ksensor          sc_voltage_vad; /* General purpose, AD = 0 */
      68             :         struct ksensor          sc_voltage_cr; /* Current Register */
      69             : 
      70             :         struct sensor_task      *sc_sensortask;
      71             : 
      72             :         struct rwlock           sc_lock;
      73             : };
      74             : 
      75             : int     owsbm_match(struct device *, void *, void *);
      76             : void    owsbm_attach(struct device *, struct device *, void *);
      77             : int     owsbm_detach(struct device *, int);
      78             : int     owsbm_activate(struct device *, int);
      79             : 
      80             : void    owsbm_update(void *);
      81             : 
      82             : struct cfattach owsbm_ca = {
      83             :         sizeof(struct owsbm_softc),
      84             :         owsbm_match,
      85             :         owsbm_attach,
      86             :         owsbm_detach,
      87             :         owsbm_activate
      88             : };
      89             : 
      90             : struct cfdriver owsbm_cd = {
      91             :         NULL, "owsbm", DV_DULL
      92             : };
      93             : 
      94             : static const struct onewire_matchfam owsbm_fams[] = {
      95             :         { ONEWIRE_FAMILY_DS2438 }
      96             : };
      97             : 
      98             : int
      99           0 : owsbm_match(struct device *parent, void *match, void *aux)
     100             : {
     101           0 :         return (onewire_matchbyfam(aux, owsbm_fams, nitems(owsbm_fams)));
     102             : }
     103             : 
     104             : void
     105           0 : owsbm_attach(struct device *parent, struct device *self, void *aux)
     106             : {
     107           0 :         struct owsbm_softc *sc = (struct owsbm_softc *)self;
     108           0 :         struct onewire_attach_args *oa = aux;
     109             : 
     110           0 :         sc->sc_onewire = oa->oa_onewire;
     111           0 :         sc->sc_rom = oa->oa_rom;
     112             : 
     113             :         /* Initialize temp sensor */
     114           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     115             :             sizeof(sc->sc_sensordev.xname));
     116           0 :         sc->sc_temp.type = SENSOR_TEMP;
     117           0 :         snprintf(sc->sc_temp.desc, sizeof(sc->sc_temp.desc), "sn %012llx",
     118           0 :             ONEWIRE_ROM_SN(oa->oa_rom));
     119           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_temp);
     120             : 
     121             :         /* Initialize voltage sensor */
     122           0 :         sc->sc_voltage_vdd.type = SENSOR_VOLTS_DC;
     123           0 :         strlcpy(sc->sc_voltage_vdd.desc, "VDD", sizeof(sc->sc_voltage_vdd.desc));
     124           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_vdd);
     125             : 
     126             :         /* Initialize voltage sensor */
     127           0 :         sc->sc_voltage_vad.type = SENSOR_VOLTS_DC;
     128           0 :         strlcpy(sc->sc_voltage_vad.desc, "VAD", sizeof(sc->sc_voltage_vad.desc));
     129           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_vad);
     130             : 
     131             :         /* Initialize the current sensor */
     132           0 :         sc->sc_voltage_cr.type = SENSOR_VOLTS_DC;
     133           0 :         strlcpy(sc->sc_voltage_cr.desc, "CR", sizeof(sc->sc_voltage_cr.desc));
     134           0 :         sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_cr);
     135             : 
     136           0 :         sc->sc_sensortask = sensor_task_register(sc, owsbm_update, 10);
     137           0 :         if (sc->sc_sensortask == NULL) {
     138           0 :                 printf(": unable to register update task\n");
     139           0 :                 return;
     140             :         }
     141             : 
     142           0 :         sensordev_install(&sc->sc_sensordev);
     143             : 
     144           0 :         rw_init(&sc->sc_lock, sc->sc_dev.dv_xname);
     145           0 :         printf("\n");
     146           0 : }
     147             : 
     148             : int
     149           0 : owsbm_detach(struct device *self, int flags)
     150             : {
     151           0 :         struct owsbm_softc *sc = (struct owsbm_softc *)self;
     152             : 
     153           0 :         rw_enter_write(&sc->sc_lock);
     154           0 :         sensordev_deinstall(&sc->sc_sensordev);
     155           0 :         if (sc->sc_sensortask != NULL)
     156           0 :                 sensor_task_unregister(sc->sc_sensortask);
     157           0 :         rw_exit_write(&sc->sc_lock);
     158             : 
     159           0 :         return (0);
     160             : }
     161             : 
     162             : int
     163           0 : owsbm_activate(struct device *self, int act)
     164             : {
     165           0 :         return (0);
     166             : }
     167             : 
     168             : void
     169           0 : owsbm_update(void *arg)
     170             : {
     171           0 :         struct owsbm_softc *sc = arg;
     172           0 :         u_int8_t data[9];
     173             : 
     174           0 :         rw_enter_write(&sc->sc_lock);
     175           0 :         onewire_lock(sc->sc_onewire, 0);
     176           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     177             :                 goto done;
     178             : 
     179           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     180           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_T);
     181           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     182             :                 goto done;
     183             :         
     184           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     185           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_V);
     186           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     187             :                 goto done;
     188             : 
     189           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     190             :         /* Issue Recall Memory page 00h cmd */
     191           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_RECALL_MEMORY);
     192           0 :         onewire_write_byte(sc->sc_onewire, 0);
     193             : 
     194           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     195             :                 goto done;
     196             : 
     197           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     198             :         /* Read page 0 of Memory Map from Scratchpad */
     199           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_READ_SCRATCHPAD);
     200           0 :         onewire_write_byte(sc->sc_onewire, 0);
     201           0 :         onewire_read_block(sc->sc_onewire, data, 9);
     202           0 :         if (onewire_crc(data, 8) == data[DS2438_SP_CRC]) {
     203           0 :                 sc->sc_temp.value = 273150000 +
     204           0 :                      (int)(((u_int16_t)data[DS2438_SP_TEMP_MSB] << 5) |
     205           0 :                      ((u_int16_t)data[DS2438_SP_TEMP_LSB] >> 3)) * 31250;
     206           0 :                 sc->sc_voltage_vdd.value =
     207           0 :                      (int)(((u_int16_t)data[DS2438_SP_VOLT_MSB] << 8) |
     208           0 :                      data[DS2438_SP_VOLT_LSB]) * 10000;
     209             : 
     210           0 :                 sc->sc_voltage_cr.value =
     211           0 :                     (int)(((u_int16_t)data[DS2438_SP_CURRENT_MSB] << 8) |
     212           0 :                     data[DS2438_SP_CURRENT_LSB]) * 244;
     213           0 :         }
     214             : 
     215             :         /* Reconfigure DS2438 to measure VAD */
     216             : 
     217           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     218             :                 goto done;
     219             : 
     220           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     221           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_WRITE_SCRATCHPAD);
     222           0 :         onewire_write_byte(sc->sc_onewire, 0);
     223           0 :         onewire_write_byte(sc->sc_onewire, 0x7); /* AD = 0 */
     224             : 
     225           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     226             :                 goto done;
     227             : 
     228           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     229           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_CONVERT_V);
     230           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     231             :                 goto done;
     232             : 
     233           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     234             :         /* Issue Recall Memory page 00h cmd */
     235           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_RECALL_MEMORY);
     236           0 :         onewire_write_byte(sc->sc_onewire, 0);
     237             : 
     238           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     239             :                 goto done;
     240             : 
     241           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     242           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_READ_SCRATCHPAD);
     243           0 :         onewire_write_byte(sc->sc_onewire, 0);
     244           0 :         onewire_read_block(sc->sc_onewire, data, 9);
     245           0 :         if (onewire_crc(data, 8) == data[8]) {
     246           0 :                 sc->sc_voltage_vad.value =
     247           0 :                     (int)(((u_int16_t)data[DS2438_SP_VOLT_MSB] << 8) |
     248           0 :                     data[DS2438_SP_VOLT_LSB]) * 10000;
     249           0 :         }
     250             : 
     251             :         /* Reconfigure back DS2438 to measure VDD (default) */
     252             : 
     253           0 :         if (onewire_reset(sc->sc_onewire) != 0)
     254             :                 goto done;
     255             : 
     256           0 :         onewire_matchrom(sc->sc_onewire, sc->sc_rom);
     257           0 :         onewire_write_byte(sc->sc_onewire, DSSBM_CMD_WRITE_SCRATCHPAD);
     258           0 :         onewire_write_byte(sc->sc_onewire, 0);
     259           0 :         onewire_write_byte(sc->sc_onewire, 0xf); /* AD = 1 */
     260           0 :         onewire_reset(sc->sc_onewire);
     261             : 
     262             : done:
     263           0 :         onewire_unlock(sc->sc_onewire);
     264           0 :         rw_exit_write(&sc->sc_lock);
     265           0 : }

Generated by: LCOV version 1.13