Index: share/man/man4/Makefile =================================================================== --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -372,6 +372,9 @@ oce.4 \ ohci.4 \ orm.4 \ + ow.4 \ + ow_temp.4 \ + owc.4 \ ${_padlock.4} \ pass.4 \ patm.4 \ @@ -657,6 +660,7 @@ MLINKS+=${_ntb.4} ${_if_ntb.4} \ ${_ntb.4} ${_ntb_hw.4} MLINKS+=${_nxge.4} ${_if_nxge.4} +MLINKS+=ow.4 onewire.4 MLINKS+=patm.4 if_patm.4 MLINKS+=pccbb.4 cbb.4 MLINKS+=pcm.4 snd.4 \ Index: share/man/man4/ow.4 =================================================================== --- /dev/null +++ share/man/man4/ow.4 @@ -0,0 +1,55 @@ +.\" +.\" Copyright (c) 2015 M. Warner Losh +.\" 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. 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 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 6, 2015 +.Dt OW 4 +.Os +.Sh NAME +.Nm ow +.Nd Dallas Semiconductor One Wire bus +.Sh DESCRIPTION +The +.Nm +module implements the Dallas Semiconductor One Wire bus. +It attaches to the +.Xr owc 4 +driver, which implements the low-level signaling of the +one wire bus. +.Sh SEE ALSO +.Xr owc 4 , +.Xr ow_temp 4 , +.Xr owll 9 , +.Xr own 9 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm +device driver and this manual page were written by +.An Warner Losh . Index: share/man/man4/ow_temp.4 =================================================================== --- /dev/null +++ share/man/man4/ow_temp.4 @@ -0,0 +1,135 @@ +.\" +.\" Copyright (c) 2015 M. Warner Losh +.\" 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. 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 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 6, 2015 +.Dt OW_TEMP 4 +.Os +.Sh NAME +.Nm ow_temp +.Nd Dallas Semiconductor One Wire Temperature sensor +.Sh DESCRIPTION +The +.Nm +module supports many of the One Wire Temperature sensors. +.Pp +The sensor is read periodically and the results returned via a +.Xr sysctl 3 +as described below. +.Sh HARDWARE +The following families of temperature sensors are supported by the +.Nm +driver: +.Bl -tag -width MAX31820 -compact +.It DS1820 +1-Wire Digital Thermometer +.It DS18S20 +High-Precision 1-Wire Digital Thermometer +.It DS18B20 +Programmable Resolution 1-Wire Digital Thermometer +.It DS1822 +Econo 1-Wire Digital Thermometer +.It DS1825 +Programmable Resolution 1-Wire Digital Thermometer with 4-bit ID +.It MAX31820 +1-Wire, Parasite-Power, Ambient Temperature Sensor +.El +.Pp +The Family Codes for these devices are reused for many variants of +these devices marketed under different names. +The variants are software compatible with earlier chips, though they +may have different operating characteristics (such as accuracy or +temperature range). +This driver supports the 0x10, 0x22, 0x28 and 0x3b family codes. +.Sh SYSCTL +This driver supports a number of +.Xr sysctl 3 +entries in the device's node in the +.Xr sysctl 3 +tree. +.Bl -tag -width xxxxxxxxxx +.It temperature +The last read temperature, in milli-Kelvin. +.It badcrc +The number of CRC errors in reading the temperature form the +device. +Some CRC errors are to be expected. +High rates of CRC errors, however, generally indicates a noisy +environment and/or cabling issues. +.It badread +The number of times an error was encountered reading the temperature +from the card, apart from CRC errors. +These should almost never happen. +.It reading_interval +The time, in ticks, between successive reads of the sensor. +.It parasite +This item is non-zero when the device is connected using its parasitic +power mode. +At present, parasitic mode likely doesn't work, so this would also +indicate a wiring error. +.El +.Sh SEE ALSO +.Xr ow 4 , +.Xr owc 4 , +.Xr owll 9 , +.Xr own 9 +.Sh BUGS +Parasitic mode doesn't work. +.Pp +The ID bits from the +.Em DS1825 +are not recognized. +.Pp +The type of the device is not reported via a sysctl. +.Pp +Alarm mode is not supported. +It is not possible to configure the low and high temperatures either. +.Pp +There's no way to write to the EEPROM. +.Pp +Convert Temperature requests are sent directly to the device. +There is no way use the 1-Wire bus' broadcast ability to do all the +conversions in parallel. +.Pp +It is not possible to set the precision on those devices that support +it. +.Pp +The time to convert is fixed at 1 second, even though some devices are +faster. +.Pp +There's no character device to supply a stream of readings to a +program. +Programs interested in the temperature must poll the sysctl to get the +temperature. +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm +device driver and this manual page were written by +.An Warner Losh . Index: share/man/man4/owc.4 =================================================================== --- /dev/null +++ share/man/man4/owc.4 @@ -0,0 +1,65 @@ +.\" +.\" Copyright (c) 2015 M. Warner Losh +.\" 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. 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 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 6, 2015 +.Dt OWC 4 +.Os +.Sh NAME +.Nm owc +.Nd Dallas Semiconductor One Wire Controller +.Sh DESCRIPTION +The +.Nm +module implements the Dallas Semiconductor One Wire signaling. +It attaches the +.Xr ow 4 +driver one wire bus protocol. +.Pp +Only a controller implementing the one wire via bit banging +pins on a gpio bus. +It implements both the standard and overdrive transfer timings. +It does not implement strong pull-up functionality needed to +support parasitic mode. +.Sh SEE ALSO +.Xr ow 4 , +.Xr ow_temp 4 , +.Xr owll 9 , +.Xr own 9 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 11.0 . +.Sh AUTHORS +The +.Nm +device driver and this manual page were written by +.An Warner Losh . +.Sh CAVEATS +The gpio driver implements timing by busy waiting, which may cause a +high load on slower systems. +.Sh BUGS +Overdrive mode has not actually been tested. Index: sys/boot/fdt/dts/arm/rpi.dts =================================================================== --- sys/boot/fdt/dts/arm/rpi.dts +++ sys/boot/fdt/dts/arm/rpi.dts @@ -340,6 +340,11 @@ }; }; + onewire { + compatible = "w1-gpio"; + gpios = <&gpio 4 1>; + }; + power: regulator { compatible = "broadcom,bcm2835-power-mgr", "broadcom,bcm2708-power-mgr", Index: sys/boot/fdt/dts/arm/rpi2.dts =================================================================== --- sys/boot/fdt/dts/arm/rpi2.dts +++ sys/boot/fdt/dts/arm/rpi2.dts @@ -351,6 +351,11 @@ }; }; + onewire { + compatible = "w1-gpio"; + gpios = <&gpio 4 1>; + }; + power: regulator { compatible = "broadcom,bcm2835-power-mgr", "broadcom,bcm2708-power-mgr", Index: sys/dev/gpio/gpiobus.c =================================================================== --- sys/dev/gpio/gpiobus.c +++ sys/dev/gpio/gpiobus.c @@ -559,12 +559,16 @@ GPIOBUS_ASSERT_UNLOCKED(sc); GPIOBUS_LOCK(sc); if (sc->sc_owner != NULL) { + if (sc->sc_owner == child) + panic("gpiobus: %s already acquired the bus\n", device_get_nameunit(child)); if (how == GPIOBUS_DONTWAIT) { GPIOBUS_UNLOCK(sc); return (EWOULDBLOCK); } - while (sc->sc_owner != NULL) + while (sc->sc_owner != NULL) { + device_printf(busdev, "%s is waiting for %s to drop the bus\n", device_get_name(child), device_get_name(sc->sc_owner)); mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0); + } } sc->sc_owner = child; GPIOBUS_UNLOCK(sc); Index: sys/dev/ow/README.txt =================================================================== --- /dev/null +++ sys/dev/ow/README.txt @@ -0,0 +1,19 @@ +Quick Design Document for one wire bus + +In new bus terms, One wire devices are attached to one wire busses +which are attached to a one wire bridge. + +The implementation follows the termonology used in the Maxim AN927 +Application note which defines the 1-wire bus as implemented for the +iButton product. This is considered to be the canonical definition of +the 1wire bus. This means that the one wire bridge will implement the +owll interface. ow is one wire. ll is for Link Level to +mirror the ISO stack terminology used by AN927. The one wire bus is +implemented in ow device, which implements the own interface (n +for network, the layer described in the AN927). The Transport layer +and above is the responsibility of the client device drivers to +implement. While there is some commonality at the Transport layer, too +many devices aren't compatible with it because they don't implement +all the commands. While the presentation layer is common enough for +useful implementaitons, it is currently unimplemented because the +focus of this work is on temperature sensors and product ID ROMs. Index: sys/dev/ow/ow.h =================================================================== --- /dev/null +++ sys/dev/ow/ow.h @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 unmodified, 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. + */ + +#ifndef DEV_OW_OW_H +#define DEV_OW_OW_H 1 + +enum ow_device_ivars { + OW_IVAR_FAMILY, + OW_IVAR_ROMID +}; + +#define OW_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(ow, var, OW, ivar, type); + +OW_ACCESSOR(family, FAMILY, uint8_t) +OW_ACCESSOR(romid, ROMID, uint8_t *) + +#undef OW_ACCSSOR + +/* + * Generalized command structure for a 1wire bus transaction. Not all possible + * transactions on the 1wire bus can be represented here (a notable exception + * being both the search ROM commands), but most of them can be, allowing for + * general transactions from userland. A lower-level interface to the link + * layer is also provided. + */ +#define MAX_ROM 8 +#define MAX_EXTRA 32 +#define MAX_READ 32 +struct ow_cmd +{ + uint32_t flags; /* Various flags */ +#define OW_FLAG_SEND_XPT_CMD 1 /* Send normal command after rom command */ +#define OW_FLAG_OVERDRIVE 2 /* Send xpt stuff overdrive speed */ +#define OW_FLAG_READ_BIT 4 /* Read a single bit after xpt_cmd */ + uint8_t rom_cmd; /* Rom command to send */ + uint8_t rom_extra_len; /* Number of additional ROM bytes to send */ + uint8_t rom_extra[MAX_ROM]; /* Extra bytes to send */ + uint8_t rom_read_len; /* Number of bytes to read */ + uint8_t rom_read[MAX_ROM]; /* Extra bytes read */ + uint8_t xpt_cmd; /* Device specific command to send, if flagged */ + uint8_t xpt_extra_len; /* Additiona data bytes to send */ + uint8_t xpt_extra[MAX_EXTRA]; /* Extra bytes to send */ + uint8_t xpt_read_len; /* Number of bytes to read after */ + uint8_t xpt_read[MAX_READ]; /* Buffer for read bytes */ +}; + +typedef uint64_t romid_t; + +#define READ_ROM 0x33 +#define MATCH_ROM 0x55 +#define SKIP_ROM 0xcc +#define ALARM_SEARCH 0xec +#define SEARCH_ROM 0xf0 + +#endif /* DEV_OW_OW_H */ Index: sys/dev/ow/ow.c =================================================================== --- /dev/null +++ sys/dev/ow/ow.c @@ -0,0 +1,613 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 unmodified, 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 + +/* + * lldev - link level device + * ndev - network / transport device (this module) + * pdev - presentation device (children of this module) + */ + +typedef int ow_enum_fn(device_t, device_t); +typedef int ow_found_fn(device_t, romid_t); + +struct ow_softc +{ + device_t dev; /* Newbus driver back pointer */ + struct mtx mtx; /* bus mutex */ + device_t owner; /* bus owner, if != NULL */ +}; + +struct ow_devinfo +{ + romid_t romid; +}; + +static int ow_acquire_bus(device_t ndev, device_t pdev, int how); +static int ow_release_bus(device_t ndev, device_t pdev); + +#define OW_LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define OW_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) +#define OW_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx) +#define OW_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED) +#define OW_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED) + +static MALLOC_DEFINE(M_OW, "ow", "House keeping data for 1wire bus"); + +static struct ow_timing timing_regular = { + .t_slot = 60, /* 60 to 120 */ + .t_low0 = 60, /* really 60 to 120 */ + .t_low1 = 1, /* really 1 to 15 */ + .t_release = 45, /* <= 45us */ + .t_rec = 1, /* at least 1us */ + .t_rdv = 15, /* 15us */ + .t_rstl = 480, /* 480us or more */ + .t_rsth = 480, /* 480us or more */ + .t_pdl = 60, /* 60us to 240us */ + .t_pdh = 60, /* 15us to 60us */ + .t_lowr = 1, /* 1us */ +}; + +/* NB: Untested */ +static struct ow_timing timing_overdrive = { + .t_slot = 11, /* 6us to 16us */ + .t_low0 = 6, /* really 6 to 16 */ + .t_low1 = 1, /* really 1 to 2 */ + .t_release = 4, /* <= 4us */ + .t_rec = 1, /* at least 1us */ + .t_rdv = 2, /* 2us */ + .t_rstl = 48, /* 48us to 80us */ + .t_rsth = 48, /* 48us or more */ + .t_pdl = 8, /* 8us to 24us */ + .t_pdh = 2, /* 2us to 6us */ + .t_lowr = 1, /* 1us */ +}; + +static void +ow_send_byte(device_t lldev, struct ow_timing *t, uint8_t byte) +{ + int i; + + for (i = 0; i < 8; i++) + if (byte & (1 << i)) + OWLL_WRITE_ONE(lldev, t); + else + OWLL_WRITE_ZERO(lldev, t); +} + +static void +ow_read_byte(device_t lldev, struct ow_timing *t, uint8_t *bytep) +{ + int i; + uint8_t byte = 0; + int bit; + + for (i = 0; i < 8; i++) { + OWLL_READ_DATA(lldev, t, &bit); + byte |= bit << i; + } + *bytep = byte; +} + +static int +ow_send_command(device_t ndev, device_t pdev, struct ow_cmd *cmd) +{ + int present, i, bit; + device_t lldev; + struct ow_timing *t; + + lldev = device_get_parent(ndev); + OWLL_RESET_AND_PRESENCE(lldev, &timing_regular, &present); + if (present == 1) { + printf("Reset said the device wasn't there.\n"); + return ENOENT; /* No devices acked the RESET */ + } + + ow_send_byte(lldev, &timing_regular, cmd->rom_cmd); + for (i = 0; i < cmd->rom_extra_len; i++) + ow_send_byte(lldev, &timing_regular, cmd->rom_extra[i]); + for (i = 0; i < cmd->rom_read_len; i++) + ow_read_byte(lldev, &timing_regular, cmd->rom_read + i); + if (cmd->flags & OW_FLAG_SEND_XPT_CMD) { + /* + * Per AN937, the reset pulse and ROM level are always + * done with the regular timings. Certain ROM commands + * put the device into overdrive mode for the remainder + * of the data transfer, which is why we have to pass the + * timings here. Commands that need to be handled like this + * are expected to be flagged by the client. + */ + t = (cmd->flags & OW_FLAG_OVERDRIVE) ? + &timing_overdrive : &timing_regular; + ow_send_byte(lldev, t, cmd->xpt_cmd); + for (i = 0; i < cmd->xpt_extra_len; i++) + ow_send_byte(lldev, t, cmd->xpt_extra[i]); + if (cmd->flags & OW_FLAG_READ_BIT) { + OWLL_READ_DATA(lldev, t, &bit); + cmd->xpt_read[0] = bit; + } else { + for (i = 0; i < cmd->xpt_read_len; i++) + ow_read_byte(lldev, t, cmd->xpt_read + i); + } + } + return 0; +} + +static int +ow_search_rom(device_t lldev, device_t dev) +{ + struct ow_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.rom_cmd = SEARCH_ROM; + return ow_send_command(lldev, dev, &cmd); +} + +#if 0 +static int +ow_alarm_search(device_t lldev, device_t dev) +{ + struct ow_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.rom_cmd = ALARM_SEARCH; + return ow_send_command(lldev, dev, &cmd); +} +#endif + +static int +ow_add_child(device_t dev, romid_t romid) +{ + struct ow_devinfo *di; + device_t child; + + di = malloc(sizeof(*di), M_OW, M_WAITOK); + di->romid = romid; + child = device_add_child(dev, NULL, -1); + if (child == NULL) { + free(di, M_OW); + return ENOMEM; + } + device_set_ivars(child, di); + return (0); +} + +static device_t +ow_child_by_romid(device_t dev, romid_t romid) +{ + device_t *children, retval, child; + int nkid, i; + struct ow_devinfo *di; + + if (device_get_children(dev, &children, &nkid) != 0) + return (NULL); + retval = NULL; + for (i = 0; i < nkid; i++) { + child = children[i]; + di = device_get_ivars(child); + if (di->romid == romid) { + retval = child; + break; + } + } + free(children, M_TEMP); + + return (retval); +} + +/* + * CRC generator table -- taken from AN937 DOW CRC LOOKUP FUNCTION Table 2 + */ +const uint8_t ow_crc_table[] = { + 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, + 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, + 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, + 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, + 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, + 219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, + 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, + 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, + 140,210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113,147, 205, + 17, 79, 173, 243, 112, 46, 204, 146, 211,141, 111, 49, 178, 236, 14, 80, + 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82,176, 238, + 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, + 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, + 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, + 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, + 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 +}; + +/* + * Converted from DO_CRC page 131 ANN937 + */ +static uint8_t +ow_crc(device_t ndev, device_t pdev, uint8_t *buffer, size_t len) +{ + uint8_t crc = 0; + int i; + + for (i = 0; i < len; i++) + crc = ow_crc_table[crc ^ buffer[i]]; + return crc; +} + +static int +ow_check_crc(romid_t romid) +{ + return ow_crc(NULL, NULL, (uint8_t *)&romid, sizeof(romid)) == 0; +} + +static int +ow_device_found(device_t dev, romid_t romid) +{ + + /* XXX Move this up into enumerate? */ + /* + * All valid ROM IDs have a valid CRC. Check that first. + */ + if (!ow_check_crc(romid)) { + device_printf(dev, "Device romid %8D failed CRC.\n", + romid, ":"); + return EINVAL; + } + + /* + * If we've seen this child before, don't add a new one for it. + */ + if (ow_child_by_romid(dev, romid) != NULL) + return 0; + + return ow_add_child(dev, romid); +} + +static int +ow_enumerate(device_t dev, ow_enum_fn *enumfp, ow_found_fn *foundfp) +{ + device_t lldev = device_get_parent(dev); + int first, second, i, dir, prior, last, err, retries; + uint64_t probed, last_mask; + + prior = -1; + last_mask = 0; + retries = 0; + last = -2; + err = ow_acquire_bus(dev, dev, OWN_DONTWAIT); + if (err != 0) + return err; + while (last != -1) { +again: + probed = 0; + last = -1; + + /* + * See AN397 section 5.II.C.3 for the algorithm (though a bit + * poorly stated). The search command forces each device to + * send ROM ID bits one at a time (first the bit, then the + * complement) the the master (us) sends back a bit. If the + * device's bit doesn't match what we send back, that device + * stops sending bits back. So each time through we remember + * the where we made the last decision (always 0). If there's a + * conflict there this time (and there will be in the absence + * of a hardware failure) we go with 1. This way, we prune the + * devices on the bus and wind up with a unique ROM. We know + * we're done when we detect no new conflicts. The same + * algorithm is used for devices in alarm state as well. + * + * In addition, experience has shown that sometimes devices + * stop responding in the middle of enumeration, so try this + * step again a few times when that happens. It is unclear if + * this is due to a nosiy electrical environment or some odd + * timing issue. + */ + err = enumfp(dev, dev); + if (err != 0) { + device_printf(dev, "Could not enumerate: %d\n", err); + return (err); + } + + for (i = 0; i < 64; i++) { + OWLL_READ_DATA(lldev, &timing_regular, &first); + OWLL_READ_DATA(lldev, &timing_regular, &second); + switch (first | second << 1) { + case 0: /* Conflict */ + if (i < prior) + dir = (last_mask >> i) & 1; + else + dir = i == prior; + + if (dir == 0) + last = i; + break; + case 1: /* 1 then 0 -> 1 for all */ + dir = 1; + break; + case 2: /* 0 then 1 -> 0 for all */ + dir = 0; + break; + case 3: + /* + * No device responded. This is unexpected, but + * experience has shown that on some platforms + * we miss a timing window, or otherwise have + * an issue. Start this step over. Since we've + * not updated prior yet, we can just jump to + * the top of the loop for a re-do of this step. + */ + printf("oops, starting over\n"); + if (++retries > 5) + return (EIO); + goto again; + } + if (dir) { + OWLL_WRITE_ONE(lldev, &timing_regular); + probed |= 1ull << i; + } else { + OWLL_WRITE_ZERO(lldev, &timing_regular); + } + } + retries = 0; + foundfp(dev, probed); + last_mask = probed; + prior = last; + }; + ow_release_bus(dev, dev); + + return (0); +} + +static int +ow_probe(device_t dev) +{ + + device_set_desc(dev, "1 Wire Bus"); + return (BUS_PROBE_GENERIC); +} + +static int +ow_attach(device_t ndev) +{ + struct ow_softc *sc; + + /* + * Find all the devices on the bus. We don't probe / attach them in the + * enumeration phase. We do this because we want to allow the probe / + * attach routines of the child drivers to have as full an access to + * the bus as possible. While we reset things before the next step of + * the search (so it would likely be OK to allow access by the clients + * to the bus), it is more conservative to find them all, then to do + * the attach of the devices. This also allows the child devices to + * have more knowledge of the bus. + */ + sc = device_get_softc(ndev); + sc->dev = ndev; + mtx_init(&sc->mtx, device_get_nameunit(sc->dev), "ow", MTX_DEF); + ow_enumerate(ndev, ow_search_rom, ow_device_found); + return bus_generic_attach(ndev); +} + +static int +ow_detach(device_t ndev) +{ + device_t *children, child; + int nkid, i; + struct ow_devinfo *di; + struct ow_softc *sc; + + sc = device_get_softc(ndev); + /* + * detach all the children first. This is blocking until any threads + * have stopped, etc. + */ + bus_generic_detach(ndev); + + /* + * We delete all the children, and free up the ivars + */ + if (device_get_children(ndev, &children, &nkid) != 0) + return ENOMEM; + for (i = 0; i < nkid; i++) { + child = children[i]; + di = device_get_ivars(child); + free(di, M_OW); + device_delete_child(ndev, child); + } + free(children, M_TEMP); + + OW_LOCK_DESTROY(sc); + return 0; +} + +/* + * Not sure this is really needed. I'm having trouble figuring out what + * location means in the context of the one wire bus. + */ +static int +ow_child_location_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + + snprintf(buf, buflen, ""); + return (0); +} + +static int +ow_child_pnpinfo_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + struct ow_devinfo *di; + + di = device_get_ivars(child); + snprintf(buf, buflen, "romid=%8D", &di->romid, ":"); + return (0); +} + +static int +ow_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct ow_devinfo *di; + romid_t **ptr; + + di = device_get_ivars(child); + switch (which) { + case OW_IVAR_FAMILY: + *result = di->romid & 0xff; + break; + case OW_IVAR_ROMID: + ptr = (romid_t **)result; + *ptr = &di->romid; + break; + default: + return EINVAL; + } + + return 0; +} + +static int +ow_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + + return EINVAL; +} + +static int +ow_print_child(device_t ndev, device_t pdev) +{ + int retval = 0; + struct ow_devinfo *di; + + di = device_get_ivars(pdev); + + retval += bus_print_child_header(ndev, pdev); + retval += printf(" romid %8D", &di->romid, ":"); + retval += bus_print_child_footer(ndev, pdev); + + return retval; +} + +static void +ow_probe_nomatch(device_t ndev, device_t pdev) +{ + struct ow_devinfo *di; + + di = device_get_ivars(pdev); + device_printf(ndev, "romid %8D: no driver\n", &di->romid, ":"); +} + +static int +ow_acquire_bus(device_t ndev, device_t pdev, int how) +{ + struct ow_softc *sc; + + sc = device_get_softc(ndev); + OW_ASSERT_UNLOCKED(sc); + OW_LOCK(sc); + if (sc->owner != NULL) { + if (sc->owner == pdev) + panic("%s: %s recursively acquiring the bus.\n", + device_get_nameunit(ndev), + device_get_nameunit(pdev)); + if (how == OWN_DONTWAIT) { + OW_UNLOCK(sc); + return EWOULDBLOCK; + } + while (sc->owner != NULL) + mtx_sleep(sc, &sc->mtx, 0, "owbuswait", 0); + } + sc->owner = pdev; + OW_UNLOCK(sc); + + return 0; +} + +static void +ow_release_bus(device_t ndev, device_t pdev) +{ + struct ow_softc *sc; + + sc = device_get_softc(ndev); + OW_ASSERT_UNLOCKED(sc); + OW_LOCK(sc); + if (sc->owner == NULL) + panic("%s: %s releasing unowned bus.", device_get_nameunit(ndev), + device_get_nameunit(pdev)); + if (sc->owner != pdev) + panic("%s: %s don't own the bus. %s does. game over.", + device_get_nameunit(ndev), device_get_nameunit(pdev), + device_get_nameunit(sc->owner)); + sc->owner = NULL; + wakeup(sc); + OW_UNLOCK(sc); +} + +devclass_t ow_devclass; + +static device_method_t ow_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ow_probe), + DEVMETHOD(device_attach, ow_attach), + DEVMETHOD(device_detach, ow_detach), + + /* Bus interface */ + DEVMETHOD(bus_child_pnpinfo_str, ow_child_pnpinfo_str), + DEVMETHOD(bus_child_location_str, ow_child_location_str), + DEVMETHOD(bus_read_ivar, ow_read_ivar), + DEVMETHOD(bus_write_ivar, ow_write_ivar), + DEVMETHOD(bus_print_child, ow_print_child), + DEVMETHOD(bus_probe_nomatch, ow_probe_nomatch), + + /* One Wire Network/Transport layer interface */ + DEVMETHOD(own_send_command, ow_send_command), + DEVMETHOD(own_acquire_bus, ow_acquire_bus), + DEVMETHOD(own_release_bus, ow_release_bus), + DEVMETHOD(own_crc, ow_crc), + { 0, 0 } +}; + +static driver_t ow_driver = { + "ow", + ow_methods, + sizeof(struct ow_softc), +}; + +DRIVER_MODULE(ow, owc, ow_driver, ow_devclass, 0, 0); +MODULE_VERSION(ow, 1); Index: sys/dev/ow/ow_temp.c =================================================================== --- /dev/null +++ sys/dev/ow/ow_temp.c @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 unmodified, 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 + +#define OWT_DS1820 0x10 /* Also 18S20 */ +#define OWT_DS1822 0x22 /* Very close to 18B20 */ +#define OWT_DS18B20 0x28 /* Also MAX31820 */ +#define OWT_DS1825 0x3B /* Just like 18B20 with address bits */ + +#define CONVERT_T 0x44 +#define COPY_SCRATCHPAD 0x48 +#define WRITE_SCRATCHPAD 0x4e +#define READ_POWER_SUPPLY 0xb4 +#define RECALL_EE 0xb8 +#define READ_SCRATCHPAD 0xbe + + +#define OW_TEMP_DONE 0x01 +#define OW_TEMP_RUNNING 0x02 + +struct ow_temp_softc +{ + device_t dev; + int type; + int temp; + int flags; + int bad_crc; + int bad_reads; + int reading_interval; + int parasite; + struct mtx temp_lock; + struct proc *event_thread; +}; + +static int +ow_temp_probe(device_t dev) +{ + + switch (ow_get_family(dev)) { + case OWT_DS1820: + device_set_desc(dev, "One Wire Temperature"); + return BUS_PROBE_DEFAULT; + case OWT_DS1822: + case OWT_DS1825: + case OWT_DS18B20: + device_set_desc(dev, "Advanced One Wire Temperature"); + return BUS_PROBE_DEFAULT; + default: + return ENXIO; + } +} + +static int +ow_temp_read_scratchpad(device_t dev, uint8_t *scratch, int len) +{ + struct ow_cmd cmd; + + own_self_command(dev, &cmd, READ_SCRATCHPAD); + cmd.xpt_read_len = len; + own_command_wait(dev, &cmd); + memcpy(scratch, cmd.xpt_read, len); + + return 0; +} + +static int +ow_temp_convert_t(device_t dev) +{ + struct ow_cmd cmd; + + own_self_command(dev, &cmd, CONVERT_T); + own_command_wait(dev, &cmd); + + return 0; +} + + +static int +ow_temp_read_power_supply(device_t dev, int *parasite) +{ + struct ow_cmd cmd; + + own_self_command(dev, &cmd, READ_POWER_SUPPLY); + cmd.flags |= OW_FLAG_READ_BIT; + own_command_wait(dev, &cmd); + *parasite = !cmd.xpt_read[0]; /* parasites pull bus low */ + + return 0; +} + +static void +ow_temp_event_thread(void *arg) +{ + struct ow_temp_softc *sc; + uint8_t scratch[8 + 1]; + uint8_t crc; + int retries, rv; + + sc = arg; + pause("owtstart", device_get_unit(sc->dev) * hz / 100); // 10ms stagger + mtx_lock(&sc->temp_lock); + sc->flags |= OW_TEMP_RUNNING; + ow_temp_read_power_supply(sc->dev, &sc->parasite); + if (sc->parasite) + device_printf(sc->dev, "Running in parasitic mode unsupported\n"); + while ((sc->flags & OW_TEMP_DONE) == 0) { + mtx_unlock(&sc->temp_lock); + ow_temp_convert_t(sc->dev); + mtx_lock(&sc->temp_lock); + msleep(sc, &sc->temp_lock, 0, "owtcvt", hz); + if (sc->flags & OW_TEMP_DONE) + break; + for (retries = 5; retries > 0; retries--) { + mtx_unlock(&sc->temp_lock); + rv = ow_temp_read_scratchpad(sc->dev, scratch, sizeof(scratch)); + mtx_lock(&sc->temp_lock); + if (rv == 0) { + crc = own_crc(sc->dev, scratch, sizeof(scratch) - 1); + if (crc == scratch[8]) { + if (sc->type == OWT_DS1820) { + if (scratch[7]) { + /* + * Formula from DS18S20 datasheet, page 6 + * DS18S20 datahseet says count_per_c is 16, DS1820 does not + */ + sc->temp = (int16_t)((scratch[0] & 0xfe) | + (scratch[1] << 8)) << 3; + sc->temp += 16 - scratch[6] - 4; /* count_per_c == 16 */ + } else + sc->temp = (int16_t)(scratch[0] | (scratch[1] << 8)) << 3; + } else + sc->temp = (int16_t)(scratch[0] | (scratch[1] << 8)); + break; + } + sc->bad_crc++; + } else + sc->bad_reads++; + } + msleep(sc, &sc->temp_lock, 0, "owtcvt", sc->reading_interval); + } + sc->flags &= ~OW_TEMP_RUNNING; + mtx_unlock(&sc->temp_lock); + kproc_exit(0); +} + +static int +ow_temp_attach(device_t dev) +{ + struct ow_temp_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->type = ow_get_family(dev); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "temperature", CTLFLAG_RD, + &sc->temp, 0, + "Current Temperature"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "badcrc", CTLFLAG_RD, + &sc->bad_crc, 0, + "Number of Bad CRC on reading scratchpad"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "badread", CTLFLAG_RD, + &sc->bad_reads, 0, + "Number of errors on reading scratchpad"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "reading_interval", CTLFLAG_RW, + &sc->reading_interval, 0, + "ticks between reads"); + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "parasite", CTLFLAG_RW, + &sc->parasite, 0, + "In Parasite mode"); + /* + * Just do this for unit 0 to avoid locking + * the ow bus until that code can be put + * into place. + */ + sc->temp = -500; + sc->reading_interval = 10 * hz; + mtx_init(&sc->temp_lock, "lock for doing temperature", NULL, MTX_DEF); + /* Start the thread */ + if (kproc_create(ow_temp_event_thread, sc, &sc->event_thread, 0, 0, + "%s event thread", device_get_nameunit(dev))) { + device_printf(dev, "unable to create event thread.\n"); + panic("cbb_create_event_thread"); + } + + return 0; +} + +static int +ow_temp_detach(device_t dev) +{ + struct ow_temp_softc *sc; + + sc = device_get_softc(dev); + + /* + * Wait for the thread to die. kproc_exit will do a wakeup + * on the event thread's struct thread * so that we know it is + * safe to proceed. IF the thread is running, set the please + * die flag and wait for it to comply. Since the wakeup on + * the event thread happens only in kproc_exit, we don't + * need to loop here. + */ + mtx_lock(&sc->temp_lock); + sc->flags |= OW_TEMP_DONE; + while (sc->flags & OW_TEMP_RUNNING) { + wakeup(sc); + msleep(sc->event_thread, &sc->temp_lock, PWAIT, "owtun", 0); + } + mtx_destroy(&sc->temp_lock); + + return 0; +} + +devclass_t ow_temp_devclass; + +static device_method_t ow_temp_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ow_temp_probe), + DEVMETHOD(device_attach, ow_temp_attach), + DEVMETHOD(device_detach, ow_temp_detach), + + { 0, 0 } +}; + +static driver_t ow_temp_driver = { + "ow_temp", + ow_temp_methods, + sizeof(struct ow_temp_softc), +}; + +DRIVER_MODULE(ow_temp, ow, ow_temp_driver, ow_temp_devclass, 0, 0); +MODULE_DEPEND(ow_temp, ow, 1, 1, 1); Index: sys/dev/ow/owc_gpiobus.c =================================================================== --- /dev/null +++ sys/dev/ow/owc_gpiobus.c @@ -0,0 +1,382 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef FDT +#include +#include +#include +#endif + +#include +#include "gpiobus_if.h" + +#include + +#define OW_PIN 0 + +#define OWC_GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define OWC_GPIOBUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define OWC_GPIOBUS_LOCK_INIT(_sc) \ + mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \ + "owc_gpiobus", MTX_DEF) +#define OWC_GPIOBUS_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); + +struct owc_gpiobus_softc +{ + device_t sc_dev; + device_t sc_busdev; + struct mtx sc_mtx; +}; + +static int owc_gpiobus_probe(device_t); +static int owc_gpiobus_attach(device_t); +static int owc_gpiobus_detach(device_t); + +#ifdef FDT +static void +owc_gpiobus_identify(driver_t *driver, device_t bus) +{ + phandle_t w1, root; + + /* + * Find all the 1-wire bus pseudo-nodes that are + * at the top level of the FDT. Would be nice to + * somehow preserve the node name of these busses, + * but there's no good place to put it. The driver's + * name is used for the device name, and the 1-wire + * bus overwrites the description. + */ + root = OF_finddevice("/"); + if (root == 0) + return; + for (w1 = OF_child(root); w1 != 0; w1 = OF_peer(w1)) { + if (!fdt_is_compatible_strict(w1, "w1-gpio")) + continue; + if (!OF_hasprop(w1, "gpios")) + continue; + ofw_gpiobus_add_fdt_child(bus, driver->name, w1); + } +} +#endif + +static int +owc_gpiobus_probe(device_t dev) +{ +#ifdef FDT + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_is_compatible(dev, "w1-gpio")) { + device_set_desc(dev, "FDT GPIO attached one-wire bus"); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +#else + device_set_desc(dev, "GPIO attached one-wire bus"); + return 0; +#endif +} + +static int +owc_gpiobus_attach(device_t dev) +{ + struct owc_gpiobus_softc *sc; + device_t *kids; + int nkid; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + sc->sc_busdev = device_get_parent(dev); + OWC_GPIOBUS_LOCK_INIT(sc); + nkid = 0; + if (device_get_children(dev, &kids, &nkid) == 0) + free(kids, M_TEMP); + if (nkid == 0) + device_add_child(dev, "ow", -1); + free(kids, M_TEMP); + bus_generic_attach(dev); + + return (0); +} + +static int +owc_gpiobus_detach(device_t dev) +{ + struct owc_gpiobus_softc *sc; + + sc = device_get_softc(dev); + OWC_GPIOBUS_LOCK_DESTROY(sc); + bus_generic_detach(dev); + return (0); +} + +/* + * In the diagrams below, R is driven by the resitor pullup, M is driven by the + * master, and S is driven by the slave / target. + */ + +/* + * These macros let what why we're doing stuff shine in the code + * below, and let the how be confined to here. + */ +#define GETBUS(sc) GPIOBUS_ACQUIRE_BUS((sc)->sc_busdev, \ + (sc)->sc_dev, GPIOBUS_WAIT) +#define RELBUS(sc) GPIOBUS_RELEASE_BUS((sc)->sc_busdev, \ + (sc)->sc_dev) +#define OUTPIN(sc) GPIOBUS_PIN_SETFLAGS((sc)->sc_busdev, \ + (sc)->sc_dev, OW_PIN, GPIO_PIN_OUTPUT) +#define INPIN(sc) GPIOBUS_PIN_SETFLAGS((sc)->sc_busdev, \ + (sc)->sc_dev, OW_PIN, GPIO_PIN_INPUT) +#define GETPIN(sc, bit) GPIOBUS_PIN_GET((sc)->sc_busdev, \ + (sc)->sc_dev, OW_PIN, bit) +#define LOW(sc) GPIOBUS_PIN_SET((sc)->sc_busdev, \ + (sc)->sc_dev, OW_PIN, GPIO_PIN_LOW) + +/* + * WRITE-ONE (see owll_if.m for timings) From Figure 4-1 AN-937 + * + * |<---------tSLOT---->|<-tREC->| + * High RRRRM | RRRRRRRRRRRR|RRRRRRRRM + * M | R | | | M + * M| R | | | M + * Low MMMMMMM | | | MMMMMM... + * |<-tLOW1->| | | + * |<------15us--->| | + * |<--------60us---->| + */ +static int +owc_gpiobus_write_one(device_t dev, struct ow_timing *t) +{ + struct owc_gpiobus_softc *sc; + int error; + + sc = device_get_softc(dev); + error = GETBUS(sc); + if (error != 0) + return error; + + critical_enter(); + + /* Force low */ + OUTPIN(sc); + LOW(sc); + DELAY(t->t_low1); + + /* Allow resister to float line high */ + INPIN(sc); + DELAY(t->t_slot - t->t_low1 + t->t_rec); + + critical_exit(); + + RELBUS(sc); + + return 0; +} + +/* + * WRITE-ZERO (see owll_if.m for timings) From Figure 4-2 AN-937 + * + * |<---------tSLOT------>|<-tREC->| + * High RRRRM | | |RRRRRRRM + * M | | R M + * M| | | |R M + * Low MMMMMMMMMMMMMMMMMMMMMR MMMMMM... + * |<--15us->| | | + * |<------60us--->| | + * |<-------tLOW0------>| + */ +static int +owc_gpiobus_write_zero(device_t dev, struct ow_timing *t) +{ + struct owc_gpiobus_softc *sc; + int error; + + sc = device_get_softc(dev); + error = GETBUS(sc); + if (error != 0) + return error; + + critical_enter(); + + /* Force low */ + OUTPIN(sc); + LOW(sc); + DELAY(t->t_low0); + + /* Allow resister to float line high */ + INPIN(sc); + DELAY(t->t_slot - t->t_low0 + t->t_rec); + + critical_exit(); + + RELBUS(sc); + + return 0; +} + +/* + * READ-DATA (see owll_if.m for timings) From Figure 4-3 AN-937 + * + * |<---------tSLOT------>|<-tREC->| + * High RRRRM | rrrrrrrrrrrrrrrRRRRRRRM + * M | r | R M + * M| r | |R M + * Low MMMMMMMSSSSSSSSSSSSSSR MMMMMM... + * |< sample > | + * |<------tRDV---->| | + * ->| |<-tRELEASE + * + * r -- allowed to pull high via the resitor when slave writes a 1-bit + * + */ +static int +owc_gpiobus_read_data(device_t dev, struct ow_timing *t, int *bit) +{ + struct owc_gpiobus_softc *sc; + int error; + + sc = device_get_softc(dev); + error = GETBUS(sc); + if (error != 0) + return error; + + critical_enter(); + + /* Force low */ + OUTPIN(sc); + LOW(sc); + DELAY(t->t_lowr); + + /* Allow resister to float line high or not */ + INPIN(sc); + DELAY(t->t_rdv - t->t_lowr - 3); + + /* Read */ + GETPIN(sc, bit); + DELAY(t->t_slot); + + critical_exit(); + + RELBUS(sc); + + return 0; +} + +/* + * RESET AND PRESENCE PULSE (see owll_if.m for timings) From Figure 4-4 AN-937 + * + * |<---------tRSTH------------>| + * High RRRM | | RRRRRRRS | RRRR RRM + * M | |R| |S | R M + * M| R | | S |R M + * Low MMMMMMMM MMMMMM| | | SSSSSSSSSS MMMMMM + * |<----tRSTL--->| | |<-tPDL---->| + * | ->| |<-tR | | + * || + * + * Note: for Regular Speed operations, tRSTL + tR should be less than 960us to + * avoid interferring with other devives on the bus + */ +static int +owc_gpiobus_reset_and_presence(device_t dev, struct ow_timing *t, int *bit) +{ + struct owc_gpiobus_softc *sc; + int error; + int buf = -1; + + sc = device_get_softc(dev); + error = GETBUS(sc); + if (error != 0) + return error; + + + critical_enter(); + + /* Force low */ + OUTPIN(sc); + LOW(sc); + DELAY(t->t_rstl); + + /* Allow resister to float line high and then wait for reset pulse */ + INPIN(sc); + DELAY(t->t_pdh + 5); + + /* Read presence pulse */ + GETPIN(sc, &buf); + + critical_exit(); + + DELAY(t->t_rsth - (t->t_pdh + 5)); /* Timing not critical for this one */ + + *bit = !!buf; + + RELBUS(sc); + + return 0; +} + +static devclass_t owc_gpiobus_devclass; + +static device_method_t owc_gpiobus_methods[] = { + /* Device interface */ +#ifdef FDT + DEVMETHOD(device_identify, owc_gpiobus_identify), +#endif + DEVMETHOD(device_probe, owc_gpiobus_probe), + DEVMETHOD(device_attach, owc_gpiobus_attach), + DEVMETHOD(device_detach, owc_gpiobus_detach), + + DEVMETHOD(owll_write_one, owc_gpiobus_write_one), + DEVMETHOD(owll_write_zero, owc_gpiobus_write_zero), + DEVMETHOD(owll_read_data, owc_gpiobus_read_data), + DEVMETHOD(owll_reset_and_presence, owc_gpiobus_reset_and_presence), + { 0, 0 } +}; + +static driver_t owc_gpiobus_driver = { + "owc", + owc_gpiobus_methods, + sizeof(struct owc_gpiobus_softc), +}; + +DRIVER_MODULE(owc_gpiobus_fdt, gpiobus, owc_gpiobus_driver, owc_gpiobus_devclass, 0, 0); +MODULE_DEPEND(owc_gpiobus_fdt, ow, 1, 1, 1); Index: sys/dev/ow/owll.h =================================================================== --- /dev/null +++ sys/dev/ow/owll.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 unmodified, 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. + * + * $FreeBSD$ + */ + +#ifndef DEV_OW_OWLL_H +#define DEV_OW_OWLL_H 1 + +/* + * Generalized parameters for the mode of operation in the bus. All units + * are in nanoseconds, and assume that all timings are < 4s. + * See owll_if.m for timings, and refer to AN937 for details. + */ +struct ow_timing +{ + uint32_t t_slot; /* Slot time */ + uint32_t t_low0; /* Time low for a 0 bit. */ + uint32_t t_low1; /* Time low for a 1 bit. */ + uint32_t t_lowr; /* Time slave holds line down per bit */ + uint32_t t_release; /* Time after t_rdv to float high */ + uint32_t t_rec; /* After sample before M low */ + uint32_t t_rdv; /* Time to poll the bit after M low */ + uint32_t t_rstl; /* Time M low on reset */ + uint32_t t_rsth; /* Time M high on reset */ + uint32_t t_pdl; /* Time S low on reset */ + uint32_t t_pdh; /* Time R high after M low on reset */ +}; + +#include "owll_if.h" + +#endif /* DEV_OW_OWLL_H */ Index: sys/dev/ow/owll_if.m =================================================================== --- /dev/null +++ sys/dev/ow/owll_if.m @@ -0,0 +1,150 @@ +#- +# Copyright (c) 2015 M. Warner Losh +# 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 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 AUTHOR 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. +# +# $FreeBSD$ +# + +#include + +INTERFACE owll; + +# +# Dallas Semiconductor 1 Wire bus Link Layer (owll) +# +# See Maxim Application Note AN937: Book of iButton Standards for the +# one wire protocol specification. +# http://pdfserv.maximintegrated.com/en/an/AN937.pdf +# +# This file provides an interface to the logical layer of the protocol. +# Although the first implementation is done with GPIO bit banging, some +# SoCs list 1wire controllers in their spec sheets which presumably has +# more smarts. +# +# Chapter 4 has all the electrical timing diagrams that make up the link +# layer of this protocol. +# +# Two speed classes are defined. Regular speed and Overdrive speed. +# It is the responsibility of a device implementing owll interface +# to ensure that the timings are met: +# +# Regular Overdrive +# +# 60us <= tSLOT < 120us 6us <= tSLOT <= 16us +# 60us <= tLOW0 < tSLOT < 120us 6us <= tLOW0 < tSLOT < 16us +# 1us <= tLOW1 < 15us 1us <= tLOW < 2us +# 1us < tLOWR < 15us 1us <= tLOWR < 2us +# 0 <= tRELEASE < 45us 0 <= tRELEASE < 4us +# 1us <= tREC < inf 1us <= tREC < inf +# tRDV = 15us tRDV = 2us +# 480us <= tRSTL < inf 48us <= tRSTL < 80us +# 480us <= tRSTH < inf 48us <= tRSTH < inf +# 15us < tPDH < 60us 2us <= tPDH < 6us +# 60us < tPDL < 240us 8us <= tPDL < 24us +# +# In the diagrams below, R is driven by the resitor pullup, M is driven by +# the master, and S is driven by the slave / target. +# +# All of these methods are expected to be called from the "network"/bus layer +# for doing its operations. See 1wn_if.m for those. +# +# Note: This is the polling / busy-wait interface. An interrupt-based interface +# may be different. But an interrupt-based, non-blocking interface can be tricky. +# +# Only the owbus should talk to this interface. +# + +# WRITE-ONE (see above for timings) From Figure 4-1 AN-937 +# +# |<---------tSLOT---->|<-tREC->| +# High RRRRM | RRRRRRRRRRRR|RRRRRRRRM +# M | R | | | M +# M| R | | | M +# Low MMMMMMM | | | MMMMMM... +# |<-tLOW1->| | | +# |<------15us--->| | +# |<--------60us---->| +# +# +METHOD int write_one { + device_t lldev; /* Link Level device (eg bridge) */ + struct ow_timing *timing; /* timing values */ +}; + + +# WRITE-ZERO (see above for timings) From Figure 4-2 AN-937 +# +# |<---------tSLOT------>|<-tREC->| +# High RRRRM | | |RRRRRRRM +# M | | R M +# M| | | |R M +# Low MMMMMMMMMMMMMMMMMMMMMR MMMMMM... +# |<--15us->| | | +# |<------60us--->| | +# |<-------tLOW0------>| +# +# +METHOD int write_zero { + device_t lldev; /* Link Level device (eg bridge) */ + struct ow_timing *timing; /* timing values */ +}; + +# READ-DATA (see above for timings) From Figure 4-3 AN-937 +# +# |<---------tSLOT------>|<-tREC->| +# High RRRRM | rrrrrrrrrrrrrrrRRRRRRRM +# M | r | R M +# M| r | |R M +# Low MMMMMMMSSSSSSSSSSSSSSR MMMMMM... +# |< sample > | +# |<------tRDV---->| | +# ->| |<-tRELEASE +# +# r -- allowed to pull high via the resitor when slave writes a 1-bit +# +METHOD int read_data { + device_t lldev; /* Link Level device (eg bridge) */ + struct ow_timing *timing; /* timing values */ + int *bit; /* Bit we sampled */ +}; + +# RESET AND PRESENCE PULSE (see above for timings) From Figure 4-4 AN-937 +# +# |<---------tRSTH------------>| +# High RRRM | | RRRRRRRS | RRRR RRM +# M | |R| |S | R M +# M| R | | S |R M +# Low MMMMMMMM MMMMMM| | | SSSSSSSSSS MMMMMM +# |<----tRSTL--->| | |<-tPDL---->| +# | ->| |<-tR | | +# || +# +# Note: for Regular Speed operations, tRSTL + tR should be less than 960us to +# avoid interferring with other devives on the bus +# +METHOD int reset_and_presence { + device_t lldev; /* Link level device (eg bridge) */ + struct ow_timing *timing; /* timing values */ + int *present; /* 0 -- no slave 1 -- slave */ +}; Index: sys/dev/ow/own.h =================================================================== --- /dev/null +++ sys/dev/ow/own.h @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2015 M. Warner Losh + * 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 unmodified, 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. + * + * $FreeBSD$ + */ + +#ifndef DEV_OW_OWN_H +#define DEV_OW_OWN_H 1 + +#include "own_if.h" + +static inline int +own_send_command(device_t pdev, struct ow_cmd *cmd) +{ + device_t ndev = device_get_parent(pdev); + + return OWN_SEND_COMMAND(ndev, pdev, cmd); +} + +/* + * How args for own_acquire_bus + */ +#define OWN_WAIT 1 +#define OWN_DONTWAIT 2 + +static inline int +own_acquire_bus(device_t pdev, int how) +{ + device_t ndev = device_get_parent(pdev); + + return OWN_ACQUIRE_BUS(ndev, pdev, how); +} + +static inline void +own_release_bus(device_t pdev) +{ + device_t ndev = device_get_parent(pdev); + + OWN_RELEASE_BUS(ndev, pdev); +} + +static inline uint8_t +own_crc(device_t pdev, uint8_t *buffer, size_t len) +{ + device_t ndev = device_get_parent(pdev); + + return OWN_CRC(ndev, pdev, buffer, len); +} + +static inline void +own_self_command(device_t dev, struct ow_cmd *cmd, uint8_t xpt_cmd) +{ + uint8_t *mep; + + memset(cmd, 0, sizeof(*cmd)); + cmd->rom_cmd = MATCH_ROM; + cmd->rom_extra_len = 8; + mep = ow_get_romid(dev); + memcpy(&cmd->rom_extra, mep, 8); + cmd->flags = OW_FLAG_SEND_XPT_CMD; + cmd->xpt_cmd = xpt_cmd; +} + +static inline void +own_command_wait(device_t dev, struct ow_cmd *cmd) +{ + + own_acquire_bus(dev, OWN_WAIT); + own_send_command(dev, cmd); + own_release_bus(dev); +} + +#endif /* DEV_OW_OWLL_H */ Index: sys/dev/ow/own_if.m =================================================================== --- /dev/null +++ sys/dev/ow/own_if.m @@ -0,0 +1,76 @@ +#- +# Copyright (c) 2015 M. Warner Losh +# 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 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 AUTHOR 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. +# +# $FreeBSD$ +# + +#include +#include + +INTERFACE own; + +# +# Dallas Semiconductor 1 Wire bus network and transport layer (own) +# +# See Maxim Application Note AN937: Book of iButton Standards for the +# one wire protocol specification. +# http://pdfserv.maximintegrated.com/en/an/AN937.pdf +# + +# +# Send a command up the stack. +# +METHOD int send_command { + device_t ndev; /* Network (bus) level device */ + device_t pdev; /* Device to send command for */ + struct ow_cmd *cmd; /* Pointer to filled in command */ +}; + +# +# Grab exclusive use of the bus (advisory) +# +METHOD int acquire_bus { + device_t ndev; + device_t pdev; + int how; +}; + +# +# Release exclusive use of the bus (advisory) +# +METHOD void release_bus { + device_t ndev; + device_t pdev; +}; + +# +# Compute a CRC for a given range of bytes +# +METHOD uint8_t crc { + device_t ndev; + device_t pdev; + uint8_t *buffer; + size_t len; +}; Index: sys/modules/Makefile =================================================================== --- sys/modules/Makefile +++ sys/modules/Makefile @@ -265,6 +265,7 @@ ${_nxge} \ ${_opensolaris} \ oce \ + ow \ ${_padlock} \ ${_padlock_rng} \ patm \ Index: sys/modules/ow/Makefile =================================================================== --- /dev/null +++ sys/modules/ow/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +SYSDIR?=${.CURDIR}/../.. +.include "${SYSDIR}/conf/kern.opts.mk" + +SUBDIR = ow owc ow_temp + +.include Index: sys/modules/ow/ow/Makefile =================================================================== --- /dev/null +++ sys/modules/ow/ow/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/ow + +KMOD= ow +SRCS= ow.c +SRCS+= own_if.c own_if.h owll_if.c owll_if.h bus_if.h device_if.h + +.include Index: sys/modules/ow/ow_temp/Makefile =================================================================== --- /dev/null +++ sys/modules/ow/ow_temp/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/ow + +KMOD= ow_temp +SRCS= ow_temp.c +SRCS+= own_if.h bus_if.h device_if.h + +.include Index: sys/modules/ow/owc/Makefile =================================================================== --- /dev/null +++ sys/modules/ow/owc/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/ow + +KMOD= owc +SRCS= owc_gpiobus.c +SRCS+= gpio_if.h gpiobus_if.h owll_if.h ofw_bus_if.h bus_if.h device_if.h +SRCS+= opt_platform.h + +.include