Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152101404
D2956.id6744.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
64 KB
Referenced Files
None
Subscribers
None
D2956.id6744.diff
View Options
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 <imp@freebsd.org>
+ * 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 <imp@freebsd.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/libkern.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <dev/ow/ow.h>
+#include <dev/ow/owll.h>
+#include <dev/ow/own.h>
+
+/*
+ * 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 <imp@freebsd.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <sys/bus.h>
+#include <sys/errno.h>
+#include <sys/libkern.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+
+#include <dev/ow/ow.h>
+#include <dev/ow/own.h>
+
+#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 <imp@freebsd.org>
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include <dev/gpio/gpiobusvar.h>
+#include "gpiobus_if.h"
+
+#include <dev/ow/owll.h>
+
+#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...
+ * |<tLOWR>< 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 | |
+ * |<tPDH>|
+ *
+ * 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 <imp@freebsd.org>
+ * 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 <imp@freebsd.org>
+# 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 <sys/bus.h>
+
+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...
+# |<tLOWR>< 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 | |
+# |<tPDH>|
+#
+# 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 <imp@freebsd.org>
+ * 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 <imp@freebsd.org>
+# 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 <sys/bus.h>
+#include <dev/ow/ow.h>
+
+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 <bsd.subdir.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 13, 5:56 PM (9 h, 52 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31419904
Default Alt Text
D2956.id6744.diff (64 KB)
Attached To
Mode
D2956: 1 wire stuff: basics and temperature
Attached
Detach File
Event Timeline
Log In to Comment